diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-04-12 12:45:55 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-04-12 13:42:15 +0300 |
commit | a592841bc0deb67c364dea234d7c5adbe0dadad5 (patch) | |
tree | 90a280604bae87f20b5007a185611c45040bdd17 /contrib/python/PyJWT/py2/jwt/algorithms.py | |
parent | dd11d72c358cf78610025a4d12ef888be70054bf (diff) | |
download | ydb-a592841bc0deb67c364dea234d7c5adbe0dadad5.tar.gz |
Intermediate changes
Diffstat (limited to 'contrib/python/PyJWT/py2/jwt/algorithms.py')
-rw-r--r-- | contrib/python/PyJWT/py2/jwt/algorithms.py | 403 |
1 files changed, 0 insertions, 403 deletions
diff --git a/contrib/python/PyJWT/py2/jwt/algorithms.py b/contrib/python/PyJWT/py2/jwt/algorithms.py deleted file mode 100644 index 13436883417..00000000000 --- a/contrib/python/PyJWT/py2/jwt/algorithms.py +++ /dev/null @@ -1,403 +0,0 @@ -import hashlib -import hmac -import json - - -from .compat import constant_time_compare, string_types -from .exceptions import InvalidKeyError -from .utils import ( - base64url_decode, base64url_encode, der_to_raw_signature, - force_bytes, force_unicode, from_base64url_uint, raw_to_der_signature, - to_base64url_uint -) - -try: - from cryptography.hazmat.primitives import hashes - from cryptography.hazmat.primitives.serialization import ( - load_pem_private_key, load_pem_public_key, load_ssh_public_key - ) - from cryptography.hazmat.primitives.asymmetric.rsa import ( - RSAPrivateKey, RSAPublicKey, RSAPrivateNumbers, RSAPublicNumbers, - rsa_recover_prime_factors, rsa_crt_dmp1, rsa_crt_dmq1, rsa_crt_iqmp - ) - from cryptography.hazmat.primitives.asymmetric.ec import ( - EllipticCurvePrivateKey, EllipticCurvePublicKey - ) - from cryptography.hazmat.primitives.asymmetric import ec, padding - from cryptography.hazmat.backends import default_backend - from cryptography.exceptions import InvalidSignature - - has_crypto = True -except ImportError: - has_crypto = False - -requires_cryptography = set(['RS256', 'RS384', 'RS512', 'ES256', 'ES384', - 'ES521', 'ES512', 'PS256', 'PS384', 'PS512']) - - -def get_default_algorithms(): - """ - Returns the algorithms that are implemented by the library. - """ - default_algorithms = { - 'none': NoneAlgorithm(), - 'HS256': HMACAlgorithm(HMACAlgorithm.SHA256), - 'HS384': HMACAlgorithm(HMACAlgorithm.SHA384), - 'HS512': HMACAlgorithm(HMACAlgorithm.SHA512) - } - - if has_crypto: - default_algorithms.update({ - 'RS256': RSAAlgorithm(RSAAlgorithm.SHA256), - 'RS384': RSAAlgorithm(RSAAlgorithm.SHA384), - 'RS512': RSAAlgorithm(RSAAlgorithm.SHA512), - 'ES256': ECAlgorithm(ECAlgorithm.SHA256), - 'ES384': ECAlgorithm(ECAlgorithm.SHA384), - 'ES521': ECAlgorithm(ECAlgorithm.SHA512), - 'ES512': ECAlgorithm(ECAlgorithm.SHA512), # Backward compat for #219 fix - 'PS256': RSAPSSAlgorithm(RSAPSSAlgorithm.SHA256), - 'PS384': RSAPSSAlgorithm(RSAPSSAlgorithm.SHA384), - 'PS512': RSAPSSAlgorithm(RSAPSSAlgorithm.SHA512) - }) - - return default_algorithms - - -class Algorithm(object): - """ - The interface for an algorithm used to sign and verify tokens. - """ - def prepare_key(self, key): - """ - Performs necessary validation and conversions on the key and returns - the key value in the proper format for sign() and verify(). - """ - raise NotImplementedError - - def sign(self, msg, key): - """ - Returns a digital signature for the specified message - using the specified key value. - """ - raise NotImplementedError - - def verify(self, msg, key, sig): - """ - Verifies that the specified digital signature is valid - for the specified message and key values. - """ - raise NotImplementedError - - @staticmethod - def to_jwk(key_obj): - """ - Serializes a given RSA key into a JWK - """ - raise NotImplementedError - - @staticmethod - def from_jwk(jwk): - """ - Deserializes a given RSA key from JWK back into a PublicKey or PrivateKey object - """ - raise NotImplementedError - - -class NoneAlgorithm(Algorithm): - """ - Placeholder for use when no signing or verification - operations are required. - """ - def prepare_key(self, key): - if key == '': - key = None - - if key is not None: - raise InvalidKeyError('When alg = "none", key value must be None.') - - return key - - def sign(self, msg, key): - return b'' - - def verify(self, msg, key, sig): - return False - - -class HMACAlgorithm(Algorithm): - """ - Performs signing and verification operations using HMAC - and the specified hash function. - """ - SHA256 = hashlib.sha256 - SHA384 = hashlib.sha384 - SHA512 = hashlib.sha512 - - def __init__(self, hash_alg): - self.hash_alg = hash_alg - - def prepare_key(self, key): - key = force_bytes(key) - - invalid_strings = [ - b'-----BEGIN PUBLIC KEY-----', - b'-----BEGIN CERTIFICATE-----', - b'-----BEGIN RSA PUBLIC KEY-----', - b'ssh-rsa' - ] - - if any([string_value in key for string_value in invalid_strings]): - raise InvalidKeyError( - 'The specified key is an asymmetric key or x509 certificate and' - ' should not be used as an HMAC secret.') - - return key - - @staticmethod - def to_jwk(key_obj): - return json.dumps({ - 'k': force_unicode(base64url_encode(force_bytes(key_obj))), - 'kty': 'oct' - }) - - @staticmethod - def from_jwk(jwk): - obj = json.loads(jwk) - - if obj.get('kty') != 'oct': - raise InvalidKeyError('Not an HMAC key') - - return base64url_decode(obj['k']) - - def sign(self, msg, key): - return hmac.new(key, msg, self.hash_alg).digest() - - def verify(self, msg, key, sig): - return constant_time_compare(sig, self.sign(msg, key)) - - -if has_crypto: - - class RSAAlgorithm(Algorithm): - """ - Performs signing and verification operations using - RSASSA-PKCS-v1_5 and the specified hash function. - """ - SHA256 = hashes.SHA256 - SHA384 = hashes.SHA384 - SHA512 = hashes.SHA512 - - def __init__(self, hash_alg): - self.hash_alg = hash_alg - - def prepare_key(self, key): - if isinstance(key, RSAPrivateKey) or \ - isinstance(key, RSAPublicKey): - return key - - if isinstance(key, string_types): - key = force_bytes(key) - - try: - if key.startswith(b'ssh-rsa'): - key = load_ssh_public_key(key, backend=default_backend()) - else: - key = load_pem_private_key(key, password=None, backend=default_backend()) - except ValueError: - key = load_pem_public_key(key, backend=default_backend()) - else: - raise TypeError('Expecting a PEM-formatted key.') - - return key - - @staticmethod - def to_jwk(key_obj): - obj = None - - if getattr(key_obj, 'private_numbers', None): - # Private key - numbers = key_obj.private_numbers() - - obj = { - 'kty': 'RSA', - 'key_ops': ['sign'], - 'n': force_unicode(to_base64url_uint(numbers.public_numbers.n)), - 'e': force_unicode(to_base64url_uint(numbers.public_numbers.e)), - 'd': force_unicode(to_base64url_uint(numbers.d)), - 'p': force_unicode(to_base64url_uint(numbers.p)), - 'q': force_unicode(to_base64url_uint(numbers.q)), - 'dp': force_unicode(to_base64url_uint(numbers.dmp1)), - 'dq': force_unicode(to_base64url_uint(numbers.dmq1)), - 'qi': force_unicode(to_base64url_uint(numbers.iqmp)) - } - - elif getattr(key_obj, 'verify', None): - # Public key - numbers = key_obj.public_numbers() - - obj = { - 'kty': 'RSA', - 'key_ops': ['verify'], - 'n': force_unicode(to_base64url_uint(numbers.n)), - 'e': force_unicode(to_base64url_uint(numbers.e)) - } - else: - raise InvalidKeyError('Not a public or private key') - - return json.dumps(obj) - - @staticmethod - def from_jwk(jwk): - try: - obj = json.loads(jwk) - except ValueError: - raise InvalidKeyError('Key is not valid JSON') - - if obj.get('kty') != 'RSA': - raise InvalidKeyError('Not an RSA key') - - if 'd' in obj and 'e' in obj and 'n' in obj: - # Private key - if 'oth' in obj: - raise InvalidKeyError('Unsupported RSA private key: > 2 primes not supported') - - other_props = ['p', 'q', 'dp', 'dq', 'qi'] - props_found = [prop in obj for prop in other_props] - any_props_found = any(props_found) - - if any_props_found and not all(props_found): - raise InvalidKeyError('RSA key must include all parameters if any are present besides d') - - public_numbers = RSAPublicNumbers( - from_base64url_uint(obj['e']), from_base64url_uint(obj['n']) - ) - - if any_props_found: - numbers = RSAPrivateNumbers( - d=from_base64url_uint(obj['d']), - p=from_base64url_uint(obj['p']), - q=from_base64url_uint(obj['q']), - dmp1=from_base64url_uint(obj['dp']), - dmq1=from_base64url_uint(obj['dq']), - iqmp=from_base64url_uint(obj['qi']), - public_numbers=public_numbers - ) - else: - d = from_base64url_uint(obj['d']) - p, q = rsa_recover_prime_factors( - public_numbers.n, d, public_numbers.e - ) - - numbers = RSAPrivateNumbers( - d=d, - p=p, - q=q, - dmp1=rsa_crt_dmp1(d, p), - dmq1=rsa_crt_dmq1(d, q), - iqmp=rsa_crt_iqmp(p, q), - public_numbers=public_numbers - ) - - return numbers.private_key(default_backend()) - elif 'n' in obj and 'e' in obj: - # Public key - numbers = RSAPublicNumbers( - from_base64url_uint(obj['e']), from_base64url_uint(obj['n']) - ) - - return numbers.public_key(default_backend()) - else: - raise InvalidKeyError('Not a public or private key') - - def sign(self, msg, key): - return key.sign(msg, padding.PKCS1v15(), self.hash_alg()) - - def verify(self, msg, key, sig): - try: - key.verify(sig, msg, padding.PKCS1v15(), self.hash_alg()) - return True - except InvalidSignature: - return False - - class ECAlgorithm(Algorithm): - """ - Performs signing and verification operations using - ECDSA and the specified hash function - """ - SHA256 = hashes.SHA256 - SHA384 = hashes.SHA384 - SHA512 = hashes.SHA512 - - def __init__(self, hash_alg): - self.hash_alg = hash_alg - - def prepare_key(self, key): - if isinstance(key, EllipticCurvePrivateKey) or \ - isinstance(key, EllipticCurvePublicKey): - return key - - if isinstance(key, string_types): - key = force_bytes(key) - - # Attempt to load key. We don't know if it's - # a Signing Key or a Verifying Key, so we try - # the Verifying Key first. - try: - if key.startswith(b'ecdsa-sha2-'): - key = load_ssh_public_key(key, backend=default_backend()) - else: - key = load_pem_public_key(key, backend=default_backend()) - except ValueError: - key = load_pem_private_key(key, password=None, backend=default_backend()) - - else: - raise TypeError('Expecting a PEM-formatted key.') - - return key - - def sign(self, msg, key): - der_sig = key.sign(msg, ec.ECDSA(self.hash_alg())) - - return der_to_raw_signature(der_sig, key.curve) - - def verify(self, msg, key, sig): - try: - der_sig = raw_to_der_signature(sig, key.curve) - except ValueError: - return False - - try: - key.verify(der_sig, msg, ec.ECDSA(self.hash_alg())) - return True - except InvalidSignature: - return False - - class RSAPSSAlgorithm(RSAAlgorithm): - """ - Performs a signature using RSASSA-PSS with MGF1 - """ - - def sign(self, msg, key): - return key.sign( - msg, - padding.PSS( - mgf=padding.MGF1(self.hash_alg()), - salt_length=self.hash_alg.digest_size - ), - self.hash_alg() - ) - - def verify(self, msg, key, sig): - try: - key.verify( - sig, - msg, - padding.PSS( - mgf=padding.MGF1(self.hash_alg()), - salt_length=self.hash_alg.digest_size - ), - self.hash_alg() - ) - return True - except InvalidSignature: - return False |