File: crypto_test.rb

package info (click to toggle)
ruby-gpgme 2.0.23-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,920 kB
  • sloc: ruby: 3,129; ansic: 2,559; sh: 7; makefile: 5
file content (237 lines) | stat: -rw-r--r-- 7,381 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# -*- encoding: utf-8 -*-
require 'test_helper'
require 'tempfile'

describe GPGME::Crypto do
  before do
    skip unless ensure_keys GPGME::PROTOCOL_OpenPGP
  end

  describe "default options functionality" do
    it "allows operation from instances normally" do
      crypto = GPGME::Crypto.new
      encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
      assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
    end

    it "can set default options when using the instance way" do
      crypto = GPGME::Crypto.new :always_trust => true
      encrypted = crypto.encrypt TEXT[:plain], :recipients => KEYS.first[:sha]
      assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
    end

    it "but they can still be overwritten" do
      crypto = GPGME::Crypto.new :always_trust => false
      encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
      assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
    end
  end

  describe "roundtrip encryption/decryption" do
    it "does the roundtrip encrypting" do
      crypto = GPGME::Crypto.new
      encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
      assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
    end

    it "does so even with armored encrypted stuff" do
      crypto = GPGME::Crypto.new
      encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :armor => true
      assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
    end
  end

  describe :encrypt do
    it "should raise an error if the recipients aren't trusted" do
      assert_raises GPGME::Error::UnusablePublicKey do
        GPGME::Crypto.new.encrypt TEXT[:plain]
      end
    end

    it "doesn't raise an error and returns something when encrypting nothing" do
      data = GPGME::Crypto.new.encrypt nil, :always_trust => true
      refute_empty data.read
      data = GPGME::Crypto.new.encrypt "", :always_trust => true
      refute_empty data.read
    end

    it "can specify which key(s) to use for encrypting with a string" do
      crypto    = GPGME::Crypto.new :always_trust => true
      key       = KEYS.last
      encrypted = crypto.encrypt TEXT[:plain], :recipients => key[:sha]
      assert_equal TEXT[:plain], crypto.decrypt(encrypted).read

      remove_key key
      encrypted.seek 0
      assert_raises GPGME::Error::NoSecretKey do
        crypto.decrypt(encrypted)
      end
      import_key key
    end

    it "can specify which key to use for encrypting with a Key object" do
      crypto    = GPGME::Crypto.new :always_trust => true
      key       = KEYS.last
      real_key  = GPGME::Key.find(:public, key[:sha]).first

      encrypted = crypto.encrypt TEXT[:plain], :recipients => real_key
      assert_equal TEXT[:plain], crypto.decrypt(encrypted).read

      remove_key key
      encrypted.seek 0
      assert_raises GPGME::Error::NoSecretKey do
        crypto.decrypt(encrypted)
      end
      import_key key
    end

    it "can also sign at the same time" do
      crypto      = GPGME::Crypto.new :always_trust => true
      encrypted   = crypto.encrypt TEXT[:plain], :sign => true
      signatures  = 0

      crypto.verify(encrypted) do |signature|
        assert_instance_of GPGME::Signature, signature
        signatures += 1
      end

      assert_equal 1, signatures
    end

    it "can be signed by more than one person" do
      crypto      = GPGME::Crypto.new :always_trust => true
      encrypted   = crypto.encrypt TEXT[:plain], :sign => true, :signers => KEYS.map{|k| k[:sha]}
      signatures  = 0

      crypto.verify(encrypted) do |signature|
        assert_instance_of GPGME::Signature, signature
        signatures += 1
      end

      assert_equal 4, signatures
    end

    it "outputs to a file if specified" do
      crypto    = GPGME::Crypto.new :always_trust => true
      file      = Tempfile.new "test"
      crypto.encrypt TEXT[:plain], :output => file
      file_contents = file.read
      file.seek 0

      refute_empty file_contents
      assert_equal TEXT[:plain], crypto.decrypt(file).read
    end

    # TODO find how to test
    # it "raises GPGME::Error::UnusablePublicKey"
    # it "raises GPGME::Error::UnusableSecretKey"
  end

  describe "symmetric encryption/decryption" do
    before do
      info = GPGME::Engine.info.first
      skip if /\A2\.[01]|\A1\./ === info.version
    end

    it "requires a password to encrypt" do
      GPGME::Crypto.new.encrypt TEXT[:plain], :symmetric => true
    end

    it "requires a password to decrypt" do
      crypto = GPGME::Crypto.new
      encrypted_data = crypto.encrypt TEXT[:plain],
        :symmetric => true, :password => "gpgme"

      crypto.decrypt encrypted_data
    end

    it "can encrypt and decrypt with the same password" do
      crypto = GPGME::Crypto.new :symmetric => true, :password => "gpgme"
      encrypted_data = crypto.encrypt TEXT[:plain]
      plain = crypto.decrypt encrypted_data

      assert_equal "Hi there", plain.read
    end
  end

  describe :decrypt do
    it "decrypts encrypted stuff" do
      assert_equal TEXT[:plain], GPGME::Crypto.new.decrypt(TEXT[:encrypted]).read
    end

    it "will not get into the signatures block if there's none" do
      GPGME::Crypto.new.decrypt(TEXT[:encrypted]) do |signature|
        flunk "If I'm here means there was some signature"
      end
      pass
    end

    it "will get signature elements if the encrypted thing was signed" do
      signatures = 0
      GPGME::Crypto.new.decrypt(TEXT[:signed]) do |signature|
        assert_instance_of GPGME::Signature, signature
        signatures += 1
      end
      assert_equal 1, signatures
    end

    it "writes to the output if passed" do
      buffer = GPGME::Data.new
      GPGME::Crypto.new.decrypt(TEXT[:encrypted], :output => buffer)
      assert_equal TEXT[:plain], buffer.read
    end

    # TODO find ways to test this
    # it "raises UnsupportedAlgorithm"
    # it "raises WrongKeyUsage"

    it "raises DecryptFailed when the decrypting key isn't available" do
      assert_raises GPGME::Error::NoSecretKey do
        GPGME::Crypto.new.decrypt(TEXT[:unavailable])
      end
    end
  end

  describe :sign do
    it "signs normal strings" do
      crypto = GPGME::Crypto.new
      signatures = 0
      sign = crypto.sign "Hi there"

      crypto.verify(sign) do |signature|
        assert_instance_of GPGME::Signature, signature
        assert signature.valid?
        signatures += 1
      end

      assert_equal 1, signatures
    end

    # TODO Find how to import an expired public key
    # it "raises an error if trying to sign with an expired key" do
    #   with_key EXPIRED_KEY do
    #     crypto  = GPGME::Crypto.new
    #     assert_raises GPGME::Error::General do
    #       sign = crypto.sign "Hi there", :signer => EXPIRED_KEY[:sha]
    #     end
    #   end
    # end

    it "selects who to sign for" do
      crypto  = GPGME::Crypto.new
      sign    = crypto.sign "Hi there", :signer => KEYS.last[:sha]
      key     = GPGME::Key.get(KEYS.last[:sha])

      signatures = 0

      crypto.verify(sign) do |signature|
        assert_instance_of GPGME::Signature, signature
        assert_equal key, signature.key
        signatures += 1
      end

      assert_equal 1, signatures
    end

  end
end