|
11 | 11 | from cryptography.hazmat.primitives.asymmetric import ec
|
12 | 12 | from cryptography.hazmat.primitives.asymmetric import padding
|
13 | 13 | from cryptography.hazmat.primitives.asymmetric import utils
|
| 14 | +from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature, encode_dss_signature |
| 15 | +from cryptography.utils import int_from_bytes, int_to_bytes |
14 | 16 |
|
15 | 17 | try:
|
16 | 18 | from builtins import str
|
@@ -174,16 +176,30 @@ def __init__(self, algorithm='SHA256'):
|
174 | 176 | raise UnSupported('algorithm: {}'.format(algorithm))
|
175 | 177 |
|
176 | 178 | def sign(self, msg, key):
|
177 |
| - return key.sign(msg, ec.ECDSA(self.hash_algorithm())) |
| 179 | + # cryptography returns ASN.1-encoded signature data; decode as JWS uses raw signatures (r||s) |
| 180 | + asn1sig = key.sign(msg, ec.ECDSA(self.hash_algorithm())) |
| 181 | + (r, s) = decode_dss_signature(asn1sig) |
| 182 | + return int_to_bytes(r) + int_to_bytes(s) |
178 | 183 |
|
179 | 184 | def verify(self, msg, sig, key):
|
180 | 185 | try:
|
181 |
| - key.verify(sig, msg, ec.ECDSA(self.hash_algorithm())) |
| 186 | + # cryptography uses ASN.1-encoded signature data; split JWS signature (r||s) and encode before verification |
| 187 | + (r, s) = self._split_raw_signature(sig) |
| 188 | + asn1sig = encode_dss_signature(r, s) |
| 189 | + key.verify(asn1sig, msg, ec.ECDSA(self.hash_algorithm())) |
182 | 190 | except InvalidSignature as err:
|
183 | 191 | raise BadSignature(err)
|
184 | 192 | else:
|
185 | 193 | return True
|
186 | 194 |
|
| 195 | + @staticmethod |
| 196 | + def _split_raw_signature(sig): |
| 197 | + """Split raw signature into components""" |
| 198 | + c_length = len(sig) // 2 |
| 199 | + r = int_from_bytes(sig[:c_length], byteorder='big') |
| 200 | + s = int_from_bytes(sig[c_length:], byteorder='big') |
| 201 | + return (r, s) |
| 202 | + |
187 | 203 |
|
188 | 204 | class PSSSigner(Signer):
|
189 | 205 | def __init__(self, algorithm='SHA256'):
|
|
0 commit comments