77from lxml import etree
88from lxml .etree import Element , SubElement
99
10- from cryptography .hazmat .primitives .asymmetric import rsa , dsa , ec
10+ from cryptography .hazmat .primitives .asymmetric import dsa , ec , rsa , utils
1111from cryptography .hazmat .primitives .asymmetric .padding import PKCS1v15
1212from cryptography .hazmat .primitives .hashes import Hash , SHA1 , SHA224 , SHA256 , SHA384 , SHA512
1313from cryptography .hazmat .backends import default_backend
@@ -386,6 +386,12 @@ def sign(self, data, key=None, passphrase=None, cert=None, reference_uri=None, k
386386 r = decoded_signature ['r' ]
387387 s = decoded_signature ['s' ]
388388 signature = long_to_bytes (r ).rjust (32 , b"\0 " ) + long_to_bytes (s ).rjust (32 , b"\0 " )
389+ elif self .sign_alg .startswith ("ecdsa-" ):
390+ # Note: The output of the ECDSA signer is a DER-encoded ASN.1 sequence of two DER integers.
391+ (r , s ) = utils .decode_dss_signature (signature )
392+ int_len = key .key_size // 8
393+ signature = long_to_bytes (r , blocksize = int_len )
394+ signature += long_to_bytes (s , blocksize = int_len )
389395
390396 signature_value_element .text = ensure_str (b64encode (signature ))
391397
@@ -553,9 +559,14 @@ def _verify_signature_with_pubkey(self, signed_info_c14n, raw_signature, key_val
553559 y = bytes_to_long (key_data [len (key_data )// 2 :])
554560 curve_class = self .known_ecdsa_curves [named_curve .get ("URI" )]
555561 key = ec .EllipticCurvePublicNumbers (x = x , y = y , curve = curve_class ()).public_key (backend = default_backend ())
556- key .verify (raw_signature ,
557- data = signed_info_c14n ,
558- signature_algorithm = ec .ECDSA (self ._get_signature_digest_method (signature_alg )))
562+ dss_signature = self ._encode_dss_signature (raw_signature , key .key_size )
563+ key .verify (
564+ dss_signature ,
565+ data = signed_info_c14n ,
566+ signature_algorithm = ec .ECDSA (
567+ self ._get_signature_digest_method (signature_alg )
568+ ),
569+ )
559570 elif "dsa-" in signature_alg :
560571 dsa_key_value = self ._find (key_value , "DSAKeyValue" )
561572 p = self ._get_long (dsa_key_value , "P" )
@@ -581,6 +592,18 @@ def _verify_signature_with_pubkey(self, signed_info_c14n, raw_signature, key_val
581592 else :
582593 raise NotImplementedError ()
583594
595+ def _encode_dss_signature (self , raw_signature , key_size_bits ):
596+ want_raw_signature_len = key_size_bits // 8 * 2
597+ if len (raw_signature ) != want_raw_signature_len :
598+ raise InvalidSignature (
599+ "Expected %d byte SignatureValue, got %d"
600+ % (want_raw_signature_len , len (raw_signature ))
601+ )
602+ int_len = len (raw_signature ) // 2
603+ r = bytes_to_long (raw_signature [:int_len ])
604+ s = bytes_to_long (raw_signature [int_len :])
605+ return utils .encode_dss_signature (r , s )
606+
584607 def _get_inclusive_ns_prefixes (self , transform_node ):
585608 inclusive_namespaces = transform_node .find ("./ec:InclusiveNamespaces[@PrefixList]" , namespaces = namespaces )
586609 if inclusive_namespaces is None :
@@ -758,6 +781,10 @@ def verify(self, data, require_x509=True, x509_cert=None, cert_subject_name=None
758781 raise InvalidSignature ("Certificate subject common name mismatch" )
759782
760783 signature_digest_method = self ._get_signature_digest_method (signature_alg ).name
784+ if "ecdsa-" in signature_alg :
785+ raw_signature = self ._encode_dss_signature (
786+ raw_signature , signing_cert .get_pubkey ().bits ()
787+ )
761788 try :
762789 verify (signing_cert , raw_signature , signed_info_c14n , signature_digest_method )
763790 except OpenSSLCryptoError as e :
0 commit comments