codekingpro/portable-devtools
114k
1"""2 authlib.jose.rfc75183 ~~~~~~~~~~~~~~~~~~~~4 5 "alg" (Algorithm) Header Parameter Values for JWS per `Section 3`_.6 7 .. _`Section 3`: https://tools.ietf.org/html/rfc7518#section-38"""9 10import hmac11import hashlib12from cryptography.hazmat.primitives import hashes13from cryptography.hazmat.primitives.asymmetric.utils import (14 decode_dss_signature, encode_dss_signature15)16from cryptography.hazmat.primitives.asymmetric.ec import ECDSA17from cryptography.hazmat.primitives.asymmetric import padding18from cryptography.exceptions import InvalidSignature19from ..rfc7515 import JWSAlgorithm20from .oct_key import OctKey21from .rsa_key import RSAKey22from .ec_key import ECKey23from .util import encode_int, decode_int24 25 26class NoneAlgorithm(JWSAlgorithm):27 name = 'none'28 description = 'No digital signature or MAC performed'29 30 def prepare_key(self, raw_data):31 return None32 33 def sign(self, msg, key):34 return b''35 36 def verify(self, msg, sig, key):37 return False38 39 40class HMACAlgorithm(JWSAlgorithm):41 """HMAC using SHA algorithms for JWS. Available algorithms:42 43 - HS256: HMAC using SHA-25644 - HS384: HMAC using SHA-38445 - HS512: HMAC using SHA-51246 """47 SHA256 = hashlib.sha25648 SHA384 = hashlib.sha38449 SHA512 = hashlib.sha51250 51 def __init__(self, sha_type):52 self.name = f'HS{sha_type}'53 self.description = f'HMAC using SHA-{sha_type}'54 self.hash_alg = getattr(self, f'SHA{sha_type}')55 56 def prepare_key(self, raw_data):57 return OctKey.import_key(raw_data)58 59 def sign(self, msg, key):60 # it is faster than the one in cryptography61 op_key = key.get_op_key('sign')62 return hmac.new(op_key, msg, self.hash_alg).digest()63 64 def verify(self, msg, sig, key):65 op_key = key.get_op_key('verify')66 v_sig = hmac.new(op_key, msg, self.hash_alg).digest()67 return hmac.compare_digest(sig, v_sig)68 69 70class RSAAlgorithm(JWSAlgorithm):71 """RSA using SHA algorithms for JWS. Available algorithms:72 73 - RS256: RSASSA-PKCS1-v1_5 using SHA-25674 - RS384: RSASSA-PKCS1-v1_5 using SHA-38475 - RS512: RSASSA-PKCS1-v1_5 using SHA-51276 """77 SHA256 = hashes.SHA25678 SHA384 = hashes.SHA38479 SHA512 = hashes.SHA51280 81 def __init__(self, sha_type):82 self.name = f'RS{sha_type}'83 self.description = f'RSASSA-PKCS1-v1_5 using SHA-{sha_type}'84 self.hash_alg = getattr(self, f'SHA{sha_type}')85 self.padding = padding.PKCS1v15()86 87 def prepare_key(self, raw_data):88 return RSAKey.import_key(raw_data)89 90 def sign(self, msg, key):91 op_key = key.get_op_key('sign')92 return op_key.sign(msg, self.padding, self.hash_alg())93 94 def verify(self, msg, sig, key):95 op_key = key.get_op_key('verify')96 try:97 op_key.verify(sig, msg, self.padding, self.hash_alg())98 return True99 except InvalidSignature:100 return False101 102 103class ECAlgorithm(JWSAlgorithm):104 """ECDSA using SHA algorithms for JWS. Available algorithms:105 106 - ES256: ECDSA using P-256 and SHA-256107 - ES384: ECDSA using P-384 and SHA-384108 - ES512: ECDSA using P-521 and SHA-512109 """110 SHA256 = hashes.SHA256111 SHA384 = hashes.SHA384112 SHA512 = hashes.SHA512113 114 def __init__(self, name, curve, sha_type):115 self.name = name116 self.curve = curve117 self.description = f'ECDSA using {self.curve} and SHA-{sha_type}'118 self.hash_alg = getattr(self, f'SHA{sha_type}')119 120 def prepare_key(self, raw_data):121 key = ECKey.import_key(raw_data)122 if key['crv'] != self.curve:123 raise ValueError(f'Key for "{self.name}" not supported, only "{self.curve}" allowed')124 return key125 126 def sign(self, msg, key):127 op_key = key.get_op_key('sign')128 der_sig = op_key.sign(msg, ECDSA(self.hash_alg()))129 r, s = decode_dss_signature(der_sig)130 size = key.curve_key_size131 return encode_int(r, size) + encode_int(s, size)132 133 def verify(self, msg, sig, key):134 key_size = key.curve_key_size135 length = (key_size + 7) // 8136 137 if len(sig) != 2 * length:138 return False139 140 r = decode_int(sig[:length])141 s = decode_int(sig[length:])142 der_sig = encode_dss_signature(r, s)143 144 try:145 op_key = key.get_op_key('verify')146 op_key.verify(der_sig, msg, ECDSA(self.hash_alg()))147 return True148 except InvalidSignature:149 return False150 151 152class RSAPSSAlgorithm(JWSAlgorithm):153 """RSASSA-PSS using SHA algorithms for JWS. Available algorithms:154 155 - PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256156 - PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384157 - PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512158 """159 SHA256 = hashes.SHA256160 SHA384 = hashes.SHA384161 SHA512 = hashes.SHA512162 163 def __init__(self, sha_type):164 self.name = f'PS{sha_type}'165 tpl = 'RSASSA-PSS using SHA-{} and MGF1 with SHA-{}'166 self.description = tpl.format(sha_type, sha_type)167 self.hash_alg = getattr(self, f'SHA{sha_type}')168 169 def prepare_key(self, raw_data):170 return RSAKey.import_key(raw_data)171 172 def sign(self, msg, key):173 op_key = key.get_op_key('sign')174 return op_key.sign(175 msg,176 padding.PSS(177 mgf=padding.MGF1(self.hash_alg()),178 salt_length=self.hash_alg.digest_size179 ),180 self.hash_alg()181 )182 183 def verify(self, msg, sig, key):184 op_key = key.get_op_key('verify')185 try:186 op_key.verify(187 sig,188 msg,189 padding.PSS(190 mgf=padding.MGF1(self.hash_alg()),191 salt_length=self.hash_alg.digest_size192 ),193 self.hash_alg()194 )195 return True196 except InvalidSignature:197 return False198 199 200JWS_ALGORITHMS = [201 NoneAlgorithm(), # none202 HMACAlgorithm(256), # HS256203 HMACAlgorithm(384), # HS384204 HMACAlgorithm(512), # HS512205 RSAAlgorithm(256), # RS256206 RSAAlgorithm(384), # RS384207 RSAAlgorithm(512), # RS512208 ECAlgorithm('ES256', 'P-256', 256),209 ECAlgorithm('ES384', 'P-384', 384),210 ECAlgorithm('ES512', 'P-521', 512),211 ECAlgorithm('ES256K', 'secp256k1', 256), # defined in RFC8812212 RSAPSSAlgorithm(256), # PS256213 RSAPSSAlgorithm(384), # PS384214 RSAPSSAlgorithm(512), # PS512215]216 