File: test_04_PGP_objects.py

package info (click to toggle)
python-pgpy 0.6.0-1.4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,212 kB
  • sloc: python: 8,448; makefile: 155; sh: 10
file content (312 lines) | stat: -rw-r--r-- 11,760 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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
""" test the functionality of PGPKeyring
"""
import pytest
import glob
import os

from pgpy import PGPKey
from pgpy import PGPKeyring
from pgpy import PGPMessage
from pgpy import PGPSignature
from pgpy import PGPUID
from pgpy.types import Fingerprint


@pytest.fixture
def abe_image():
    with open('tests/testdata/abe.jpg', 'rb') as abef:
        abebytes = bytearray(os.path.getsize('tests/testdata/abe.jpg'))
        abef.readinto(abebytes)

    return PGPUID.new(abebytes)


_msgfiles = sorted(glob.glob('tests/testdata/messages/*.asc'))


class TestPGPMessage(object):
    @pytest.mark.parametrize('msgfile', _msgfiles, ids=[os.path.basename(f) for f in _msgfiles])
    def test_load_from_file(self, msgfile):
        # TODO: figure out a good way to verify that all went well here, because
        #       PGPy reorders signatures sometimes, and also unwraps compressed messages
        #       so comparing str(msg) to the contents of msgfile doesn't actually work
        msg = PGPMessage.from_file(msgfile)

        with open(msgfile, 'r') as mf:
            mt = mf.read()

            assert len(str(msg)) == len(mt)


@pytest.fixture
def un():
    return PGPUID.new('Temperair\xe9e Youx\'seur')


@pytest.fixture
def unc():
    return PGPUID.new('Temperair\xe9e Youx\'seur', comment='\u2603')


@pytest.fixture
def une():
    return PGPUID.new('Temperair\xe9e Youx\'seur', email='snowman@not.an.email.addre.ss')


@pytest.fixture
def unce():
    return PGPUID.new('Temperair\xe9e Youx\'seur', comment='\u2603', email='snowman@not.an.email.addre.ss')


@pytest.fixture
def abe():
    return PGPUID.new('Abraham Lincoln', comment='Honest Abe', email='abraham.lincoln@whitehouse.gov')


class TestPGPUID(object):
    def test_userid(self, abe):
        assert abe.name == 'Abraham Lincoln'
        assert abe.comment == 'Honest Abe'
        assert abe.email == 'abraham.lincoln@whitehouse.gov'
        assert abe.image is None

    def test_userphoto(self, abe_image):
        assert abe_image.name == ""
        assert abe_image.comment == ""
        assert abe_image.email == ""
        with open('tests/testdata/abe.jpg', 'rb') as abef:
            abebytes = bytearray(os.path.getsize('tests/testdata/abe.jpg'))
            abef.readinto(abebytes)
        assert abe_image.image == abebytes

    def test_format(self, un, unc, une, unce):
        assert "{:s}".format(un) == 'Temperair\xe9e Youx\'seur'
        assert "{:s}".format(unc) == 'Temperair\xe9e Youx\'seur (\u2603)'
        assert "{:s}".format(une) == 'Temperair\xe9e Youx\'seur <snowman@not.an.email.addre.ss>'
        assert "{:s}".format(unce) == 'Temperair\xe9e Youx\'seur (\u2603) <snowman@not.an.email.addre.ss>'


_keyfiles = sorted(glob.glob('tests/testdata/blocks/*key*.asc'))
_fingerprints = {'dsapubkey.asc': '2B5BBB143BA0B290DCEE6668B798AE8990877201',
                 'dsaseckey.asc': '2B5BBB143BA0B290DCEE6668B798AE8990877201',
                 'eccpubkey.asc': '502D1A5365D1C0CAA69945390BA52DF0BAA59D9C',
                 'eccseckey.asc': '502D1A5365D1C0CAA69945390BA52DF0BAA59D9C',
                 'openpgp.js.pubkey.asc': 'C7C38ECEE94A4AD32DDB064E14AB44C74D1BDAB8',
                 'openpgp.js.seckey.asc': 'C7C38ECEE94A4AD32DDB064E14AB44C74D1BDAB8',
                 'rsapubkey.asc': 'F4294BC8094A7E0585C85E8637473B3758C44F36',
                 'rsaseckey.asc': 'F4294BC8094A7E0585C85E8637473B3758C44F36',}


class TestPGPKey(object):
    @pytest.mark.parametrize('kf', _keyfiles, ids=[os.path.basename(f) for f in _keyfiles])
    def test_load_from_file(self, kf):
        key, _ = PGPKey.from_file(kf)

        assert key.fingerprint == _fingerprints[os.path.basename(kf)]

    @pytest.mark.parametrize('kf', _keyfiles, ids=[os.path.basename(f) for f in _keyfiles])
    def test_load_from_str(self, kf):
        with open(kf, 'r') as tkf:
            key, _ = PGPKey.from_blob(tkf.read())

        assert key.fingerprint == _fingerprints[os.path.basename(kf)]

    @pytest.mark.regression(issue=140)
    @pytest.mark.parametrize('kf', _keyfiles, ids=[os.path.basename(f) for f in _keyfiles])
    def test_load_from_bytes(self, kf):
        with open(kf, 'rb') as tkf:
            key, _ = PGPKey.from_blob(tkf.read())

        assert key.fingerprint == _fingerprints[os.path.basename(kf)]

    @pytest.mark.regression(issue=140)
    @pytest.mark.parametrize('kf', _keyfiles, ids=[os.path.basename(f) for f in _keyfiles])
    def test_load_from_bytearray(self, kf):
        tkb = bytearray(os.stat(kf).st_size)
        with open(kf, 'rb') as tkf:
            tkf.readinto(tkb)

        key, _ = PGPKey.from_blob(tkb)

        assert key.fingerprint == _fingerprints[os.path.basename(kf)]

    @pytest.mark.parametrize('kf', sorted(filter(lambda f: not f.endswith('enc.asc'), glob.glob('tests/testdata/keys/*.asc'))))
    def test_save(self, kf):
        # load the key and export it back to binary
        key, _ = PGPKey.from_file(kf)
        pgpyblob = key.__bytes__()

        # try loading the exported key
        reloaded, _ = PGPKey.from_file(kf)

        assert pgpyblob == reloaded.__bytes__()


@pytest.fixture(scope='module')
def keyring():
    return PGPKeyring()


class TestPGPKeyring(object):
    def test_load(self, keyring):
        # load from filenames
        keys = keyring.load(glob.glob('tests/testdata/*test.asc'), glob.glob('tests/testdata/signatures/*.key.asc'))

        # keys
        assert all(isinstance(k, Fingerprint) for k in keys)

        # __len__
        assert len(keys) == 10
        assert len(keyring) == 16

        # __contains__
        #  RSA von TestKey
        selectors = ["F429 4BC8 094A 7E05 85C8 5E86 3747 3B37 58C4 4F36", "37473B3758C44F36", "58C44F36",
                     "RSA von TestKey", "rsa@test.key"]
        for selector in selectors:
            assert selector in keyring

        #  DSA von TestKey
        selectors = ["EBC8 8A94 ACB1 10F1 BE3F E3C1 2B47 4BB0 2084 C712", "2B474BB02084C712", "2084C712",
                     "DSA von TestKey", "dsa@test.key"]
        for selector in selectors:
            assert selector in keyring

        # fingerprints filtering
        #  we have 10 keys
        assert len(keyring.fingerprints()) == 10
        #  10 public halves, 6 private halves
        assert len(keyring.fingerprints(keyhalf='public')) == 10
        assert len(keyring.fingerprints(keyhalf='private')) == 6
        #  we have 5 primary keys; 5 public and 2 private
        assert len(keyring.fingerprints(keytype='primary')) == 5
        assert len(keyring.fingerprints(keytype='primary', keyhalf='public')) == 5
        assert len(keyring.fingerprints(keytype='primary', keyhalf='private')) == 2
        #  and the other 5; 5 public and 4 private
        assert len(keyring.fingerprints(keytype='sub')) == 5
        assert len(keyring.fingerprints(keytype='sub', keyhalf='public')) == 5
        assert len(keyring.fingerprints(keytype='sub', keyhalf='private')) == 4

        # now test sorting:
        rvt = keyring._get_keys("RSA von TestKey")
        assert len(rvt) == 2
        assert not rvt[0].is_public
        assert rvt[1].is_public

    @pytest.mark.parametrize('kf', _keyfiles, ids=[os.path.basename(f) for f in _keyfiles])
    def test_load_key_instance(self, keyring, kf):
        key, _ = PGPKey.from_file(kf)

        keys = keyring.load(key)

        assert key.fingerprint in keyring
        for uid in key.userids:
            if uid.name != "":
                assert uid.name in keyring
            if uid.email != "":
                assert uid.email in keyring
        with keyring.key(key.fingerprint) as loaded_key:
            assert loaded_key.fingerprint == key.fingerprint

    def test_select_fingerprint(self, keyring):
        for fp, name in [("F429 4BC8 094A 7E05 85C8 5E86 3747 3B37 58C4 4F36", "RSA von TestKey"),
                         (Fingerprint("F429 4BC8 094A 7E05 85C8 5E86 3747 3B37 58C4 4F36"), "RSA von TestKey"),
                         ("EBC8 8A94 ACB1 10F1 BE3F E3C1 2B47 4BB0 2084 C712", "DSA von TestKey"),
                         (Fingerprint("EBC8 8A94 ACB1 10F1 BE3F E3C1 2B47 4BB0 2084 C712"), "DSA von TestKey"),]:
            with keyring.key(fp) as key:
                assert key.fingerprint == fp
                assert key.userids[0].name == name

    def test_select_keyid(self, keyring):
        with keyring.key("37473B3758C44F36") as rsa:
            assert rsa.userids[0].name == "RSA von TestKey"

        with keyring.key("2B474BB02084C712") as dsa:
            assert dsa.userids[0].name == "DSA von TestKey"

    def test_select_shortid(self, keyring):
        with keyring.key("58C44F36") as rsa:
            assert rsa.userids[0].name == "RSA von TestKey"

        with keyring.key("2084C712") as dsa:
            assert dsa.userids[0].name == "DSA von TestKey"

    def test_select_name(self, keyring):
        with keyring.key("RSA von TestKey") as rsa:
            assert rsa.userids[0].name == "RSA von TestKey"

        with keyring.key("DSA von TestKey") as dsa:
            assert dsa.userids[0].name == "DSA von TestKey"

    def test_select_comment(self, keyring):
        with keyring.key("2048-bit RSA") as rsa:
            assert rsa.userids[0].name == "RSA von TestKey"

        with keyring.key("2048-bit DSA") as dsa:
            assert dsa.userids[0].name == "DSA von TestKey"

    def test_select_email(self, keyring):
        with keyring.key("rsa@test.key") as rsa:
            assert rsa.userids[0].name == "RSA von TestKey"

        with keyring.key("dsa@test.key") as dsa:
            assert dsa.userids[0].name == "DSA von TestKey"

    def test_select_pgpsignature(self, keyring):
        sig = PGPSignature()
        with open('tests/testdata/signatures/debian-sid.sig.asc', 'r') as sigf:
            sig.parse(sigf.read())

        with keyring.key(sig) as sigkey:
            assert sigkey.fingerprint.keyid == sig.signer

    def test_select_pgpmessage(self, keyring):
        m1 = PGPMessage()
        with open('tests/testdata/messages/message.rsa.cast5.asc', 'r') as m1f:
            m1.parse(m1f.read())

        with keyring.key(m1) as rsakey:
            assert rsakey.fingerprint == "00EC FAF5 48AE B655 F861  8193 EEE0 97A0 17B9 79CA"
            assert rsakey.parent.fingerprint == "F429 4BC8 094A 7E05 85C8 5E86 3747 3B37 58C4 4F36"

    def test_unload_key(self, keyring):
        with keyring.key("Test Repository Signing Key") as key:
            keyring.unload(key)

        # is the key and its subkeys actually gone?
        assert id(key) not in keyring._keys
        for pkid in iter(id(sk) for sk in key.subkeys.values()):
            assert pkid not in keyring._keys

        # aliases
        # userid components
        assert "Test Repository Signing Key" not in keyring
        assert "KUS" not in keyring
        assert "usc-kus@securityinnovation.com" not in keyring

        # fingerprints
        assert "513B 160A A994 8C1F 3D77 952D CE57 0774 D0FD CA20" not in keyring

        # keyid(s)
        assert "CE570774D0FDCA20" not in keyring

        # shortids
        assert "D0FDCA20" not in keyring

    def test_unload_key_half(self, keyring):
        with keyring.key('RSA von TestKey') as key:
            keyring.unload(key)

        # key was unloaded for real
        assert id(key) not in keyring._keys

        # but it was not a unique alias, because we only unloaded half of the key
        # userid components
        assert 'RSA von TestKey' in keyring
        assert '2048-bit RSA' in keyring
        assert 'rsa@test.key' in keyring

        # fingerprint, keyid, shortid
        assert 'F429 4BC8 094A 7E05 85C8  5E86 3747 3B37 58C4 4F36' in keyring
        assert '37473B3758C44F36' in keyring
        assert '58C44F36' in keyring