26
26
>>> pprint(json.loads(signature_json))
27
27
{'payload': 'aGVsbG8gd29ybGQ=',
28
28
'payloadType': 'http://example.com/HelloWorld',
29
- 'signatures': [{'sig': 'A3JqsQGtVsJ2O2xqrI5IcnXip5GToJ3F+FnZ+O88SjtR6rDAajabZKciJTfUiHqJPcIAriEGAHTVeCUjW2JIZA=='}]}
29
+ 'signatures': [{'keyid': '66301bbf',
30
+ 'sig': 'A3JqsQGtVsJ2O2xqrI5IcnXip5GToJ3F+FnZ+O88SjtR6rDAajabZKciJTfUiHqJPcIAriEGAHTVeCUjW2JIZA=='}]}
30
31
31
32
Verification example:
32
33
43
44
import base64 , binascii , dataclasses , json , struct
44
45
45
46
# Protocol requires Python 3.8+.
46
- from typing import Iterable , List , Protocol , Tuple
47
+ from typing import Iterable , List , Optional , Protocol , Tuple
47
48
48
49
49
50
class Signer (Protocol ):
50
51
def sign (self , message : bytes ) -> bytes :
51
52
"""Returns the signature of `message`."""
52
53
...
53
54
55
+ def keyid (self ) -> Optional [str ]:
56
+ """Returns the ID of this key, or None if not supported."""
57
+ ...
58
+
54
59
55
60
class Verifier (Protocol ):
56
61
def verify (self , message : bytes , signature : bytes ) -> bool :
57
62
"""Returns true if `message` was signed by `signature`."""
58
63
...
59
64
65
+ def keyid (self ) -> Optional [str ]:
66
+ """Returns the ID of this key, or None if not supported."""
67
+ ...
68
+
60
69
61
70
# Collection of verifiers, each of which is associated with a name.
62
71
VerifierList = Iterable [Tuple [str , Verifier ]]
@@ -88,14 +97,16 @@ def PAE(payloadType: str, payload: bytes) -> bytes:
88
97
89
98
90
99
def Sign (payloadType : str , payload : bytes , signer : Signer ) -> str :
100
+ signature = {
101
+ 'keyid' : signer .keyid (),
102
+ 'sig' : b64enc (signer .sign (PAE (payloadType , payload ))),
103
+ }
104
+ if not signature ['keyid' ]:
105
+ del signature ['keyid' ]
91
106
return json .dumps ({
92
- 'payload' :
93
- b64enc (payload ),
94
- 'payloadType' :
95
- payloadType ,
96
- 'signatures' : [{
97
- 'sig' : b64enc (signer .sign (PAE (payloadType , payload )))
98
- }],
107
+ 'payload' : b64enc (payload ),
108
+ 'payloadType' : payloadType ,
109
+ 'signatures' : [signature ],
99
110
})
100
111
101
112
@@ -107,6 +118,10 @@ def Verify(json_signature: str, verifiers: VerifierList) -> VerifiedPayload:
107
118
recognizedSigners = []
108
119
for signature in wrapper ['signatures' ]:
109
120
for name , verifier in verifiers :
121
+ if (signature .get ('keyid' ) is not None and
122
+ verifier .keyid () is not None and
123
+ signature .get ('keyid' ) != verifier .keyid ()):
124
+ continue
110
125
if verifier .verify (pae , b64dec (signature ['sig' ])):
111
126
recognizedSigners .append (name )
112
127
if not recognizedSigners :
0 commit comments