python: Add an idiomatic interface.
[gpgme.git] / lang / python / tests / t-keylist.py
1 #!/usr/bin/env python3
2
3 # Copyright (C) 2016 g10 Code GmbH
4 #
5 # This file is part of GPGME.
6 #
7 # GPGME is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # GPGME is distributed in the hope that it will be useful, but WITHOUT
13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
15 # Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this program; if not, see <http://www.gnu.org/licenses/>.
19
20 import sys
21 import pyme
22 from pyme import core, constants
23 import support
24
25 support.init_gpgme(constants.PROTOCOL_OpenPGP)
26 c = core.Context()
27
28 # Check expration of keys.  This test assumes three subkeys of which
29 # 2 are expired; it is used with the "Whisky" test key.  It has
30 # already been checked that these 3 subkeys are available.
31 def check_whisky(name, key):
32   sub1 = key.subkeys[2]
33   sub2 = key.subkeys[3]
34
35   assert sub1.expired and sub2.expired, \
36       "Subkey of `{}' not flagged as expired".format(name)
37   assert sub1.expires == 1129636886 and sub2.expires == 1129636939, \
38       "Subkey of `{}' has wrong expiration date".format(name)
39
40 keys = [
41     [ "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8",
42       [ [ "Alfa Test", "demo key", "alfa@example.net" ],
43         [ "Alpha Test", "demo key", "alpha@example.net" ],
44         [ "Alice", "demo key", "" ] ], 1 ],
45     [ "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", "5381EA4EE29BA37F",
46       [ [ "Bob", "demo key", "" ],
47         [ "Bravo Test", "demo key", "bravo@example.net" ] ], 1 ],
48     [ "61EE841A2A27EB983B3B3C26413F4AF31AFDAB6C", "E71E72ACBC43DA60",
49       [ [ "Charlie Test", "demo key", "charlie@example.net" ] ], 1 ],
50     [ "6560C59C43D031C54D7C588EEBA9F240EB9DC9E6", "06F22880B0C45424",
51       [ [ "Delta Test", "demo key", "delta@example.net" ] ], 1 ],
52     [ "3531152DE293E26A07F504BC318C1FAEFAEF6D1B", "B5C79E1A7272144D",
53       [ [ "Echelon", "demo key", "" ],
54         [ "Echo Test", "demo key", "echo@example.net" ],
55         [ "Eve", "demo key", "" ] ], 1 ],
56     [ "56D33268F7FE693FBB594762D4BF57F37372E243", "0A32EE79EE45198E",
57       [ [ "Foxtrot Test", "demo key", "foxtrot@example.net" ] ], 1 ],
58     [ "C9C07DCC6621B9FB8D071B1D168410A48FC282E6", "247491CC9DCAD354",
59       [ [ "Golf Test", "demo key", "golf@example.net" ] ], 1 ],
60     [ "9E91CBB11E4D4135583EF90513DB965534C6E3F1", "76E26537D622AD0A",
61       [ [ "Hotel Test", "demo key", "hotel@example.net" ] ], 1 ],
62     [ "CD538D6CC9FB3D745ECDA5201FE8FC6F04259677", "C1C8EFDE61F76C73",
63       [ [ "India Test", "demo key", "india@example.net" ] ], 1 ],
64     [ "F8F1EDC73995AB739AD54B380C820C71D2699313", "BD0B108735F8F136",
65       [ [ "Juliet Test", "demo key", "juliet@example.net" ] ], 1 ],
66     [ "3FD11083779196C2ECDD9594AD1B0FAD43C2D0C7", "86CBB34A9AF64D02",
67       [ [ "Kilo Test", "demo key", "kilo@example.net" ] ], 1 ],
68     [ "1DDD28CEF714F5B03B8C246937CAB51FB79103F8", "0363B449FE56350C",
69       [ [ "Lima Test", "demo key", "lima@example.net" ] ], 1 ],
70     [ "2686AA191A278013992C72EBBE794852BE5CF886", "5F600A834F31EAE8",
71       [ [ "Mallory", "demo key", "" ],
72         [ "Mike Test", "demo key", "mike@example.net" ] ], 1 ],
73     [ "5AB9D6D7BAA1C95B3BAA3D9425B00FD430CEC684", "4C1D63308B70E472",
74       [ [ "November Test", "demo key", "november@example.net" ] ], 1 ],
75     [ "43929E89F8F79381678CAE515F6356BA6D9732AC", "FF0785712681619F",
76       [ [ "Oscar Test", "demo key", "oscar@example.net" ] ], 1 ],
77     [ "6FAA9C201E5E26DCBAEC39FD5D15E01D3FF13206", "2764E18263330D9C",
78       [ [ "Papa test", "demo key", "papa@example.net" ] ], 1 ],
79     [ "A7969DA1C3297AA96D49843F1C67EC133C661C84", "6CDCFC44A029ACF4",
80       [ [ "Quebec Test", "demo key", "quebec@example.net" ] ], 1 ],
81     [ "38FBE1E4BF6A5E1242C8F6A13BDBEDB1777FBED3", "9FAB805A11D102EA",
82       [ [ "Romeo Test", "demo key", "romeo@example.net" ] ], 1 ],
83     [ "045B2334ADD69FC221076841A5E67F7FA3AE3EA1", "93B88B0F0F1B50B4",
84       [ [ "Sierra Test", "demo key", "sierra@example.net" ] ], 1 ],
85     [ "ECAC774F4EEEB0620767044A58CB9A4C85A81F38", "97B60E01101C0402",
86       [ [ "Tango Test", "demo key", "tango@example.net" ] ], 1 ],
87     [ "0DBCAD3F08843B9557C6C4D4A94C0F75653244D6", "93079B915522BDB9",
88       [ [ "Uniform Test", "demo key", "uniform@example.net" ] ], 1 ],
89     [ "E8143C489C8D41124DC40D0B47AF4B6961F04784", "04071FB807287134",
90       [ [ "Victor Test", "demo key", "victor@example.org" ] ], 1 ],
91     [ "E8D6C90B683B0982BD557A99DEF0F7B8EC67DBDE", "D7FBB421FD6E27F6",
92       [ [ "Whisky Test", "demo key", "whisky@example.net" ] ], 3,
93       check_whisky ],
94     [ "04C1DF62EFA0EBB00519B06A8979A6C5567FB34A", "5CC6F87F41E408BE",
95       [ [ "XRay Test", "demo key", "xray@example.net" ] ], 1 ],
96     [ "ED9B316F78644A58D042655A9EEF34CD4B11B25F", "5ADFD255F7B080AD",
97       [ [ "Yankee Test", "demo key", "yankee@example.net" ] ], 1 ],
98     [ "23FD347A419429BACCD5E72D6BC4778054ACD246", "EF9DC276A172C881",
99       [ [ "Zulu Test", "demo key", "zulu@example.net" ] ], 1 ],
100 ]
101
102 def check_global(key, uids, n_subkeys):
103     assert not key.revoked, "Key unexpectedly revoked"
104     assert not key.expired, "Key unexpectedly expired"
105     assert not key.disabled, "Key unexpectedly disabled"
106     assert not key.invalid, "Key unexpectedly invalid"
107     assert key.can_sign, "Key unexpectedly unusable for signing"
108     assert key.can_certify, "Key unexpectedly unusable for certifications"
109     assert not key.secret, "Key unexpectedly secret"
110     assert not key.protocol != constants.PROTOCOL_OpenPGP, \
111         "Key has unexpected protocol: {}".format(key.protocol)
112     assert not key.issuer_serial, \
113         "Key unexpectedly carries issuer serial: {}".format(key.issuer_serial)
114     assert not key.issuer_name, \
115         "Key unexpectedly carries issuer name: {}".format(key.issuer_name)
116     assert not key.chain_id, \
117         "Key unexpectedly carries chain ID: {}".format(key.chain_id)
118
119     # Only key Alfa is trusted
120     assert key.uids[0].name == 'Alfa Test' \
121       or key.owner_trust == constants.VALIDITY_UNKNOWN, \
122         "Key has unexpected owner trust: {}".format(key.owner_trust)
123     assert key.uids[0].name != 'Alfa Test' \
124       or key.owner_trust == constants.VALIDITY_ULTIMATE, \
125         "Key has unexpected owner trust: {}".format(key.owner_trust)
126
127     assert len(key.subkeys) - 1 == n_subkeys, \
128         "Key `{}' has unexpected number of subkeys".format(uids[0][0])
129
130
131 def check_subkey(fpr, which, subkey):
132     assert not subkey.revoked, which + " key unexpectedly revoked"
133     assert not subkey.expired, which + " key unexpectedly expired"
134     assert not subkey.disabled, which + " key unexpectedly disabled"
135     assert not subkey.invalid, which + " key unexpectedly invalid"
136
137     if which == "Primary":
138         assert not subkey.can_encrypt, \
139             which + " key unexpectedly usable for encryption"
140         assert subkey.can_sign, \
141             which + " key unexpectedly unusable for signing"
142         assert subkey.can_certify, \
143             which + " key unexpectedly unusable for certifications"
144     else:
145         assert subkey.can_encrypt, \
146             which + " key unexpectedly unusable for encryption"
147         assert not subkey.can_sign, \
148             which + " key unexpectedly usable for signing"
149         assert not subkey.can_certify, \
150             which + " key unexpectedly usable for certifications"
151
152     assert not subkey.secret, which + " key unexpectedly secret"
153     assert not subkey.is_cardkey, "Public key marked as card key"
154     assert not subkey.card_number, "Public key with card number set"
155     assert not subkey.pubkey_algo != (constants.PK_DSA if which == "Primary"
156                                       else constants.PK_ELG_E), \
157         which + " key has unexpected public key algo: {}".\
158             format(subkey.pubkey_algo)
159     assert subkey.length == 1024, \
160         which + " key has unexpected length: {}".format(subkey.length)
161     assert fpr.endswith(subkey.keyid), \
162         which + " key has unexpected key ID: {}".format(subkey.keyid)
163     assert which == "Secondary" or subkey.fpr == fpr, \
164         which + " key has unexpected fingerprint: {}".format(subkey.fpr)
165     assert not subkey.expires, \
166         which + " key unexpectedly expires: {}".format(subkey.expires)
167
168 def check_uid(which, ref, uid):
169     assert not uid.revoked, which + " user ID unexpectedly revoked"
170     assert not uid.invalid, which + " user ID unexpectedly invalid"
171     assert uid.validity == (constants.VALIDITY_UNKNOWN
172                             if uid.name.split()[0]
173                             not in {'Alfa', 'Alpha', 'Alice'} else
174                             constants.VALIDITY_ULTIMATE), \
175       which + " user ID has unexpectedly validity: {}".format(uid.validity)
176     assert not uid.signatures, which + " user ID unexpectedly signed"
177     assert uid.name == ref[0], \
178       "Unexpected name in {} user ID: {!r}".format(which.lower(), uid.name)
179     assert uid.comment == ref[1], \
180       "Unexpected comment in {} user ID: {!r}".format(which.lower(),
181                                                       uid.comment)
182     assert uid.email == ref[2], \
183       "Unexpected email in {} user ID: {!r}".format(which.lower(), uid.email)
184
185 i = 0
186 c.op_keylist_start(None, False)
187 key = c.op_keylist_next ()
188 while key:
189     try:
190         if len(keys[i]) == 4:
191             fpr, sec_keyid, uids, n_subkeys = keys[i]
192             misc_check = None
193         else:
194             fpr, sec_keyid, uids, n_subkeys, misc_check = keys[i]
195     except IndexError:
196         # There are more keys.  We don't check for that.
197         break
198
199     # Global key flags.
200     check_global(key, uids, n_subkeys)
201     check_subkey(fpr, "Primary", key.subkeys[0])
202     check_subkey(sec_keyid, "Secondary", key.subkeys[1])
203
204     assert len(key.uids) == len(uids)
205     check_uid("First", uids[0], key.uids[0])
206     if len(key.uids) > 1:
207       check_uid("Second", uids[1], key.uids[1])
208     if len(key.uids) > 2:
209       check_uid("Third", uids[2], key.uids[2])
210
211     if misc_check:
212         misc_check (uids[0][0], key)
213     key = c.op_keylist_next ()
214     i += 1
215
216 c.op_keylist_end()
217 result = c.op_keylist_result()
218 assert not result.truncated, "Key listing unexpectedly truncated"
219
220
221 for i, key in enumerate(c.op_keylist_all(None, False)):
222     try:
223         if len(keys[i]) == 4:
224             fpr, sec_keyid, uids, n_subkeys = keys[i]
225             misc_check = None
226         else:
227             fpr, sec_keyid, uids, n_subkeys, misc_check = keys[i]
228     except IndexError:
229         # There are more keys.  We don't check for that.
230         break
231
232     # Global key flags.
233     check_global(key, uids, n_subkeys)
234     check_subkey(fpr, "Primary", key.subkeys[0])
235     check_subkey(sec_keyid, "Secondary", key.subkeys[1])
236
237     assert len(key.uids) == len(uids)
238     check_uid("First", uids[0], key.uids[0])
239     if len(key.uids) > 1:
240       check_uid("Second", uids[1], key.uids[1])
241     if len(key.uids) > 2:
242       check_uid("Third", uids[2], key.uids[2])
243
244     if misc_check:
245         misc_check (uids[0][0], key)