3535_PADDING = padding .PKCS1v15 ()
3636
3737
38- class ES256Verifier (base .Verifier ):
38+ class EsVerifier (base .Verifier ):
3939 """Verifies ECDSA cryptographic signatures using public keys.
4040
4141 Args:
@@ -46,28 +46,38 @@ class ES256Verifier(base.Verifier):
4646
4747 def __init__ (self , public_key ):
4848 self ._pubkey = public_key
49+ # ECDSA raw signature has (r||s) format where r,s are two
50+ # integers of size 32 bytes for P-256 curve and 48 bytes
51+ # for P-384 curve. For P-256 curve, we use SHA256 hash algo,
52+ # and for P-384 curve we use SHA384 algo.
53+ if isinstance (public_key .curve , ec .SECP384R1 ):
54+ self ._r_s_size = 48
55+ self ._sha_algo = hashes .SHA384 ()
56+ else :
57+ self ._r_s_size = 32
58+ self ._sha_algo = hashes .SHA256 ()
4959
5060 @_helpers .copy_docstring (base .Verifier )
5161 def verify (self , message , signature ):
5262 # First convert (r||s) raw signature to ASN1 encoded signature.
5363 sig_bytes = _helpers .to_bytes (signature )
54- if len (sig_bytes ) != 64 :
64+ if len (sig_bytes ) != self . _r_s_size * 2 :
5565 return False
5666 r = (
57- int .from_bytes (sig_bytes [:32 ], byteorder = "big" )
67+ int .from_bytes (sig_bytes [:self . _r_s_size ], byteorder = "big" )
5868 if _helpers .is_python_3 ()
59- else utils .int_from_bytes (sig_bytes [:32 ], byteorder = "big" )
69+ else utils .int_from_bytes (sig_bytes [:self . _r_s_size ], byteorder = "big" )
6070 )
6171 s = (
62- int .from_bytes (sig_bytes [32 :], byteorder = "big" )
72+ int .from_bytes (sig_bytes [self . _r_s_size :], byteorder = "big" )
6373 if _helpers .is_python_3 ()
64- else utils .int_from_bytes (sig_bytes [32 :], byteorder = "big" )
74+ else utils .int_from_bytes (sig_bytes [self . _r_s_size :], byteorder = "big" )
6575 )
6676 asn1_sig = encode_dss_signature (r , s )
6777
6878 message = _helpers .to_bytes (message )
6979 try :
70- self ._pubkey .verify (asn1_sig , message , ec .ECDSA (hashes . SHA256 () ))
80+ self ._pubkey .verify (asn1_sig , message , ec .ECDSA (self . _sha_algo ))
7181 return True
7282 except (ValueError , cryptography .exceptions .InvalidSignature ):
7383 return False
@@ -101,7 +111,11 @@ def from_string(cls, public_key):
101111 return cls (pubkey )
102112
103113
104- class ES256Signer (base .Signer , base .FromServiceAccountMixin ):
114+ class ES256Verifier (EsVerifier ):
115+ pass
116+
117+
118+ class EsSigner (base .Signer , base .FromServiceAccountMixin ):
105119 """Signs messages with an ECDSA private key.
106120
107121 Args:
@@ -116,6 +130,16 @@ class ES256Signer(base.Signer, base.FromServiceAccountMixin):
116130 def __init__ (self , private_key , key_id = None ):
117131 self ._key = private_key
118132 self ._key_id = key_id
133+ # ECDSA raw signature has (r||s) format where r,s are two
134+ # integers of size 32 bytes for P-256 curve and 48 bytes
135+ # for P-384 curve. For P-256 curve, we use SHA256 hash algo,
136+ # and for P-384 curve we use SHA384 algo.
137+ if isinstance (private_key .curve , ec .SECP384R1 ):
138+ self ._r_s_size = 48
139+ self ._sha_algo = hashes .SHA384 ()
140+ else :
141+ self ._r_s_size = 32
142+ self ._sha_algo = hashes .SHA256 ()
119143
120144 @property # type: ignore
121145 @_helpers .copy_docstring (base .Signer )
@@ -125,14 +149,14 @@ def key_id(self):
125149 @_helpers .copy_docstring (base .Signer )
126150 def sign (self , message ):
127151 message = _helpers .to_bytes (message )
128- asn1_signature = self ._key .sign (message , ec .ECDSA (hashes . SHA256 () ))
152+ asn1_signature = self ._key .sign (message , ec .ECDSA (self . _sha_algo ))
129153
130154 # Convert ASN1 encoded signature to (r||s) raw signature.
131155 (r , s ) = decode_dss_signature (asn1_signature )
132156 return (
133- (r .to_bytes (32 , byteorder = "big" ) + s .to_bytes (32 , byteorder = "big" ))
157+ (r .to_bytes (self . _r_s_size , byteorder = "big" ) + s .to_bytes (self . _r_s_size , byteorder = "big" ))
134158 if _helpers .is_python_3 ()
135- else (utils .int_to_bytes (r , 32 ) + utils .int_to_bytes (s , 32 ))
159+ else (utils .int_to_bytes (r , self . _r_s_size ) + utils .int_to_bytes (s , self . _r_s_size ))
136160 )
137161
138162 @classmethod
@@ -173,3 +197,7 @@ def __setstate__(self, state):
173197 """Pickle helper that deserializes the _key attribute."""
174198 state ["_key" ] = serialization .load_pem_private_key (state ["_key" ], None )
175199 self .__dict__ .update (state )
200+
201+
202+ class ES256Signer (EsSigner ):
203+ pass
0 commit comments