def sign(self, message): message = _helpers.to_bytes(message) asn1_signature = self._key.sign(message, ec.ECDSA(hashes.SHA256())) # Convert ASN1 encoded signature to (r||s) raw signature. (r, s) = decode_dss_signature(asn1_signature) return utils.int_to_bytes(r, 32) + utils.int_to_bytes(s, 32)
def encode_point(self): # key_size is in bits. Convert to bytes and round up byte_length = (self.curve.key_size + 7) // 8 return ( b'\x04' + utils.int_to_bytes(self.x, byte_length) + utils.int_to_bytes(self.y, byte_length) )
def add_kid(kid_b64, key_b64): kid = b64decode(kid_b64) asn1data = b64decode(key_b64) pub = serialization.load_der_public_key(asn1data) if (isinstance(pub, RSAPublicKey)): kids[kid_b64] = CoseKey.from_dict({ KpKty: KtyRSA, KpAlg: Ps256, # RSSASSA-PSS-with-SHA-256-and-MFG1 RSAKpE: int_to_bytes(pub.public_numbers().e), RSAKpN: int_to_bytes(pub.public_numbers().n) }) elif (isinstance(pub, EllipticCurvePublicKey)): kids[kid_b64] = CoseKey.from_dict({ KpKty: KtyEC2, EC2KpCurve: P256, # Ought o be pk.curve - but the two libs clash KpAlg: Es256, # ecdsa-with-SHA256 EC2KpX: pub.public_numbers().x.to_bytes(32, byteorder="big"), EC2KpY: pub.public_numbers().y.to_bytes(32, byteorder="big") }) else: print( f"Skipping unexpected/unknown key type (keyid={kid_b64}, {pub.__class__.__name__}).", file=sys.stderr)
def _get_key_data(self, key): def _der_len(data): ln = len(data) if ln <= 128: res = [ln] elif ln <= 255: res = [0x81, ln] else: res = [0x82, (ln >> 8) & 0xff, ln & 0xff] return bytearray(res) private_numbers = key.private_numbers() data = a2b_hex('B603840181') if isinstance(key, rsa.RSAPrivateKey): ln = key.key_size // 8 // 2 data += b'\x7f\x48\x08\x91\x03\x92\x81\x80\x93\x81\x80\x5f\x48\x82\x01\x03\x01\x00\x01' # noqa: E501 data += int_to_bytes(private_numbers.p, ln) data += int_to_bytes(private_numbers.q, ln) return b'\x4d' + _der_len(data) + data elif isinstance(key, ec.EllipticCurvePrivateKey): ln = key.key_size // 8 privkey = int_to_bytes(private_numbers.private_value, ln) data += b'\x7f\x48\x02\x92' + _der_len(privkey) data += b'\x5f\x48' + _der_len(privkey) + privkey return b'\x4d' + _der_len(data) + data
def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized utils._check_byteslike("key_material", key_material) self._used = True # inverse floor division (equivalent to ceiling) rounds = -(-self._length // self._algorithm.digest_size) output = [b""] # For counter mode, the number of iterations shall not be # larger than 2^r-1, where r <= 32 is the binary length of the counter # This ensures that the counter values used as an input to the # PRF will not repeat during a particular call to the KDF function. r_bin = utils.int_to_bytes(1, self._rlen) if rounds > pow(2, len(r_bin) * 8) - 1: raise ValueError("There are too many iterations.") for i in range(1, rounds + 1): h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) counter = utils.int_to_bytes(i, self._rlen) if self._location == CounterLocation.BeforeFixed: h.update(counter) h.update(self._generate_fixed_input()) if self._location == CounterLocation.AfterFixed: h.update(counter) output.append(h.finalize()) return b"".join(output)[:self._length]
def derive(self, key_material): if self._used: raise AlreadyFinalized utils._check_byteslike("key_material", key_material) self._used = True # inverse floor division (equivalent to ceiling) rounds = -(-self._length // self._algorithm.digest_size) output = [b''] # For counter mode, the number of iterations shall not be # larger than 2^r-1, where r <= 32 is the binary length of the counter # This ensures that the counter values used as an input to the # PRF will not repeat during a particular call to the KDF function. r_bin = utils.int_to_bytes(1, self._rlen) if rounds > pow(2, len(r_bin) * 8) - 1: raise ValueError('There are too many iterations.') for i in range(1, rounds + 1): h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) counter = utils.int_to_bytes(i, self._rlen) if self._location == CounterLocation.BeforeFixed: h.update(counter) h.update(self._generate_fixed_input()) if self._location == CounterLocation.AfterFixed: h.update(counter) output.append(h.finalize()) return b''.join(output)[:self._length]
def get_key_alg_and_jwk(key): if isinstance(key, rsa.RSAPrivateKey): # See https://tools.ietf.org/html/rfc7518#section-6.3 numbers = key.public_key().public_numbers() return "RS256", { "kty": "RSA", "e": bytes_to_base64url(int_to_bytes(numbers.e)), "n": bytes_to_base64url(int_to_bytes(numbers.n)) } elif isinstance(key, ec.EllipticCurvePrivateKey): # See https://tools.ietf.org/html/rfc7518#section-6.2 numbers = key.public_key().public_numbers() if isinstance(numbers.curve, ec.SECP256R1): alg = 'ES256' crv = 'P-256' elif isinstance(numbers.curve, ec.SECP384R1): alg = 'ES384' crv = 'P-384' elif isinstance(numbers.curve, ec.SECP521R1): alg = 'ES512' crv = 'P-521' else: raise ValueError("Unsupported EC curve in key: {}".format(key)) full_octets = (int(crv[2:]) + 7) // 8 return alg, { "kty": "EC", "crv": crv, "x": bytes_to_base64url(int_to_bytes(numbers.x, full_octets)), "y": bytes_to_base64url(int_to_bytes(numbers.y, full_octets)) } elif "cryptography.hazmat.primitives.asymmetric.ed25519" in sys.modules and isinstance( key, ed25519.Ed25519PrivateKey): # See https://tools.ietf.org/html/rfc8037#appendix-A.2 return "EdDSA", { "kty": "OKP", "crv": "Ed25519", "x": bytes_to_base64url(key.public_key().public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw)) } elif "cryptography.hazmat.primitives.asymmetric.ed448" in sys.modules and isinstance( key, ed448.Ed448PrivateKey): return "EdDSA", { "kty": "OKP", "crv": "Ed448", "x": bytes_to_base64url(key.public_key().public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw)) } else: raise ValueError("Unsupported key: {}".format(key))
def encode_manifest(self, ca_key_path=None, ca_cert_path=None): """ Function generate secure signed element object which contains payload, protected, header and signature. Inputs: ca_key_path log signer key path which sign the jws data ca_cert_path log signer cert path which contains cert extension and cert fingerprint Outputs: signed_se return encoded manifest which contains securesignedelement object ca_key_path log signer key path which sign the jws data ca_cert_path log signer cert path which contains cert extension and cert fingerprint """ # Read ca key if ca_key_path is None: ca_cert_path = None ca_key_path, ca_key = self.__load_ca_key(ca_key_path) ca_cert_path, ca_cert = self.__load_ca_cert(ca_key, ca_cert_path) # Precompute the JWT header sse_protected_header = { 'typ': 'JWT', 'alg': 'ES256', 'kid': self.__jws_b64encode( ca_cert.extensions.get_extension_for_class( x509.SubjectKeyIdentifier).value.digest), 'x5t#S256': self.__jws_b64encode(ca_cert.fingerprint(hashes.SHA256())) } se_object = self.get_manifest() signed_se = { 'payload': self.__jws_b64encode(json.dumps( se_object).encode('ascii')), 'protected': self.__jws_b64encode( json.dumps(sse_protected_header).encode('ascii')), 'header': { 'uniqueId': self.uniqueId } } # Sign sse object tbs = signed_se['protected'] + '.' + signed_se['payload'] signature = ca_key.sign(tbs.encode('ascii'), ec.ECDSA(hashes.SHA256())) r_int, s_int = crypto_utils.decode_dss_signature(signature) signed_se['signature'] = self.__jws_b64encode( int_to_bytes(r_int, 32) + int_to_bytes(s_int, 32)) return { 'signed_se': signed_se, 'ca_key_path': ca_key_path, 'ca_cert_path': ca_cert_path }
def sign(self, message): message = _helpers.to_bytes(message) asn1_signature = self._key.sign(message, ec.ECDSA(hashes.SHA256())) # Convert ASN1 encoded signature to (r||s) raw signature. (r, s) = decode_dss_signature(asn1_signature) return ((r.to_bytes(32, byteorder="big") + s.to_bytes(32, byteorder="big")) if _helpers.is_python_3() else (utils.int_to_bytes(r, 32) + utils.int_to_bytes(s, 32)))
def _decode_signature(signature, hash_algorithm): hash_algorithms_map = {'SHA256': 256} try: num_bits = hash_algorithms_map[hash_algorithm] except KeyError: raise ValueError( f'Wrong hash algorithm: {hash_algorithm}. Allowed: {list(hash_algorithms_map.keys())}' ) num_bytes = (num_bits + 7) // 8 r, s = decode_dss_signature(signature) return int_to_bytes(r, num_bytes) + int_to_bytes(s, num_bytes)
def to_map(self): public_key_map = self.public_key().to_map() d_bytes = cry_utils.int_to_bytes(self.numbers.private_value) octet_length = (len(cry_utils.int_to_bytes(self.numbers.private_value - 1)) + 7) >> 3 d_bytes = b'\x00' * (octet_length - len(d_bytes)) + d_bytes private_key_map = { 'd': util.jose_base64_url_encode(d_bytes).decode('utf-8') } private_key_map.update(public_key_map) return private_key_map
def _dsc(config_env: Dict): if TEST_CONTEXT in config_env.keys( ) and CERTIFICATE in config_env[TEST_CONTEXT].keys(): cert_code = config_env[TEST_CONTEXT][CERTIFICATE] x = y = e = n = None cert = x509.load_pem_x509_certificate( f'-----BEGIN CERTIFICATE-----\n{cert_code}\n-----END CERTIFICATE-----' .encode()) fingerprint = cert.fingerprint(SHA256()) keyid = fingerprint[0:8] if isinstance(cert.public_key(), rsa.RSAPublicKey): e = int_to_bytes(cert.public_key().public_numbers().e) n = int_to_bytes(cert.public_key().public_numbers().n) elif isinstance(cert.public_key(), ec.EllipticCurvePublicKey): x = int_to_bytes(cert.public_key().public_numbers().x) y = int_to_bytes(cert.public_key().public_numbers().y) else: raise Exception( f'Unsupported Certificate Algorithm: {cert.signature_algorithm_oid} for verification.' ) try: dsc_supported_operations = { eku.dotted_string for eku in cert.extensions.get_extension_for_class( x509.ExtendedKeyUsage).value } except ExtensionNotFound: dsc_supported_operations = set() dsc_not_valid_before = cert.not_valid_before.replace( tzinfo=timezone.utc) dsc_not_valid_after = cert.not_valid_after.replace(tzinfo=timezone.utc) key = None if x and y: key = CoseKey.from_dict({ KpKeyOps: [VerifyOp], KpKty: KtyEC2, EC2KpCurve: P256, # Ought o be pk.curve - but the two libs clash KpAlg: Es256, # ECDSA using P-256 and SHA-256 EC2KpX: x, EC2KpY: y, }) elif e and n: key = CoseKey.from_dict({ KpKeyOps: [VerifyOp], KpKty: KtyRSA, KpAlg: Ps256, # RSASSA-PSS using SHA-256 and MGF1 with SHA-256 RSAKpE: e, RSAKpN: n, }) return key, keyid, dsc_supported_operations, dsc_not_valid_before, dsc_not_valid_after
def encode_point(self): warnings.warn( "encode_point has been deprecated on EllipticCurvePublicNumbers" " and will be removed in a future version. Please use " "EllipticCurvePublicKey.public_bytes to obtain both " "compressed and uncompressed point encoding.", utils.PersistentlyDeprecated2019, stacklevel=2, ) # key_size is in bits. Convert to bytes and round up byte_length = (self.curve.key_size + 7) // 8 return (b"\x04" + utils.int_to_bytes(self.x, byte_length) + utils.int_to_bytes(self.y, byte_length))
def crypto_sign_msg(self, msg): if self.algo == 'rsa': return self.privkey.sign(msg, padding.PKCS1v15(), hashes.SHA256()) elif self.algo == 'ec': hash_algos = { 256: hashes.SHA256(), 384: hashes.SHA384(), 521: hashes.SHA512() } sig_der = self.privkey.sign(msg, ec.ECDSA(hash_algos[self.bits])) num_bytes = (self.bits + 7) // 8 r, s = utils.decode_dss_signature(sig_der) return int_to_bytes(r, num_bytes) + int_to_bytes(s, num_bytes)
def put_key( self, slot: SLOT, private_key: Union[rsa.RSAPrivateKeyWithSerialization, ec.EllipticCurvePrivateKeyWithSerialization, ], pin_policy: PIN_POLICY = PIN_POLICY.DEFAULT, touch_policy: TOUCH_POLICY = TOUCH_POLICY.DEFAULT, ) -> None: key_type = KEY_TYPE.from_public_key(private_key.public_key()) _check_key_support(self.version, key_type, pin_policy, touch_policy) ln = key_type.bit_len // 8 numbers = private_key.private_numbers() if key_type.algorithm == ALGORITHM.RSA: numbers = cast(rsa.RSAPrivateNumbers, numbers) if numbers.public_numbers.e != 65537: raise ValueError("RSA exponent must be 65537") ln //= 2 data = (Tlv(0x01, int_to_bytes(numbers.p, ln)) + Tlv(0x02, int_to_bytes(numbers.q, ln)) + Tlv(0x03, int_to_bytes(numbers.dmp1, ln)) + Tlv(0x04, int_to_bytes(numbers.dmq1, ln)) + Tlv(0x05, int_to_bytes(numbers.iqmp, ln))) else: numbers = cast(ec.EllipticCurvePrivateNumbers, numbers) data = Tlv(0x06, int_to_bytes(numbers.private_value, ln)) if pin_policy: data += Tlv(TAG_PIN_POLICY, int_to_bytes(pin_policy)) if touch_policy: data += Tlv(TAG_TOUCH_POLICY, int_to_bytes(touch_policy)) self.protocol.send_apdu(0, INS_IMPORT_KEY, key_type, slot, data) return key_type
def test_token_info_by_ec(self): ec_key = generate_ec_private_key() public_numbers = ec_key.public_key().public_numbers() x = urlsafe_b64encode(int_to_bytes(public_numbers.x)).decode() y = urlsafe_b64encode(int_to_bytes(public_numbers.y)).decode() private_key = ec_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()).decode() payload = { 'sub': 'testuser', 'u_idx': 123123, 'exp': int(time.time()) + 60 * 60, 'client_id': 'asfeih29snv8as213i', 'scope': 'all' } headers = { 'kid': 'ES999', } valid_token = jwt.encode(payload=payload, key=private_key, algorithm='ES256', headers=headers).decode() with requests_mock.Mocker() as m: m.get(RidiOAuth2Config.get_key_url(), text=json.dumps({ 'keys': [{ "kty": "EC", "use": "sig", "crv": "P-256", "kid": "ES999", "x": x, "y": y, "alg": "ES256" }] })) token_info = get_token_info(token=valid_token) self.assertEqual(token_info.subject, payload['sub']) self.assertEqual(token_info.u_idx, payload['u_idx']) self.assertEqual(token_info.expire_timestamp, payload['exp']) self.assertEqual(token_info.client_id, payload['client_id']) self.assertIn(payload['scope'], token_info.scope)
def jwk(self): pubnums = self.pubkey.public_numbers() if self.algo == 'rsa': return { 'kty': 'RSA', 'n': acme_b64encode(int_to_bytes(pubnums.n)), 'e': acme_b64encode(int_to_bytes(pubnums.e)) } elif self.algo == 'ec': return { 'kty': 'EC', 'crv': 'P-{0}'.format(self.bits), 'x': acme_b64encode(int_to_bytes(pubnums.x)), 'y': acme_b64encode(int_to_bytes(pubnums.y)) }
def test_blobEC(self): """ Return the over-the-wire SSH format of the EC public key. """ from cryptography import utils byteLength = (self.ecObj.curve.key_size + 7) // 8 self.assertEqual( keys.Key(self.ecObj).blob(), common.NS(keydata.ECDatanistp256['curve']) + common.NS(keydata.ECDatanistp256['curve'][-8:]) + common. NS(b'\x04' + utils.int_to_bytes( self.ecObj.private_numbers().public_numbers.x, byteLength) + utils.int_to_bytes( self.ecObj.private_numbers().public_numbers.y, byteLength)))
def encode_point(self): warnings.warn( "encode_point has been deprecated on EllipticCurvePublicNumbers" " and will be removed in a future version. Please use " "EllipticCurvePublicKey.public_bytes to obtain both " "compressed and uncompressed point encoding.", utils.DeprecatedIn25, stacklevel=2, ) # key_size is in bits. Convert to bytes and round up byte_length = (self.curve.key_size + 7) // 8 return ( b'\x04' + utils.int_to_bytes(self.x, byte_length) + utils.int_to_bytes(self.y, byte_length) )
def ssh_public_key(keypair: rsa.RSAPrivateKeyWithSerialization) -> str: """ converts an rsa keypair to openssh format public key :param keypair: keypair. :type keypair: cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization :return: string of public key """ eb = utils.int_to_bytes(keypair.public_key().public_numbers().e) nb = utils.int_to_bytes(keypair.public_key().public_numbers().n) if eb[0] & 0x80: eb = bytes([0x00]) + eb if nb[0] & 0x80: nb = bytes([0x00]) + nb keyparts = [b'ssh-rsa', eb, nb] keystring = b''.join([struct.pack(">I", len(kp)) + kp for kp in keyparts]) return str(b'ssh-rsa ' + b64encode(keystring), encoding='utf-8')
def put(cls, session, object_id, label, domains, capabilities, key): """Import a private key into the YubiHSM. RSA and EC keys can be created by using the cryptography APIs. You can then pass either a :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey` or a :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey` as `key`. EdDSA keys can be created using the Cryptography APIs if available, or by calling :func:`~yubihsm.eddsa.load_ed25519_private_key`. :param AuthSession session: The session to import via. :param int object_id: The ID to set for the object. Set to 0 to let the YubiHSM designate an ID. :param str label: A text label to give the object. :param int domains: The set of domains to assign the object to. :param int capabilities: The set of capabilities to give the object. :param key: The private key to import. :return: A reference to the newly created object. :rtype: AsymmetricKey """ if isinstance(key, rsa.RSAPrivateKey): numbers = key.private_numbers() serialized = int_to_bytes(numbers.p) + int_to_bytes(numbers.q) algo = getattr(ALGORITHM, "RSA_%d" % key.key_size) elif isinstance(key, ec.EllipticCurvePrivateKey): numbers = key.private_numbers() serialized = int_to_bytes(numbers.private_value, (key.curve.key_size + 7) // 8) algo = ALGORITHM.for_curve(key.curve) elif _is_ed25519_private_key(key): serialized = _serialize_ed25519_private_key(key) algo = ALGORITHM.EC_ED25519 else: raise ValueError("Unsupported key") msg = (struct.pack( "!H%dsHQB" % LABEL_LENGTH, object_id, _label_pack(label), domains, capabilities, algo, ) + serialized) return cls._from_command(session, COMMAND.PUT_ASYMMETRIC_KEY, msg)
def _key_identifier_from_public_key(public_key): if isinstance(public_key, RSAPublicKey): data = public_key.public_bytes( serialization.Encoding.DER, serialization.PublicFormat.PKCS1, ) elif isinstance(public_key, EllipticCurvePublicKey): data = public_key.public_numbers().encode_point() else: # This is a very slow way to do this. serialized = public_key.public_bytes( serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo) spki, remaining = decoder.decode(serialized, asn1Spec=_SubjectPublicKeyInfo()) assert not remaining # the univ.BitString object is a tuple of bits. We need bytes and # pyasn1 really doesn't want to give them to us. To get it we'll # build an integer and convert that to bytes. bits = 0 for bit in spki.getComponentByName("subjectPublicKey"): bits = bits << 1 | bit data = utils.int_to_bytes(bits) return hashlib.sha1(data).digest()
def enable_encryptor_by_pem_file(self, pem_pub_file, curve_name = 'secp256k1', strength = 128): if not self.can_encryptor: raise Exception("can not enable encryptor after a quest send") if curve_name not in ['secp256k1', 'secp256r1', 'secp192r1', 'secp224r1']: curve_name = 'secp256k1' self.encryptor_curve = ec.SECP256K1() if curve_name == 'secp256k1': self.encryptor_curve = ec.SECP256K1() elif curve_name == 'secp256r1': self.encryptor_curve = ec.SECP256R1() elif curve_name == 'secp192r1': self.encryptor_curve = ec.SECP192R1() else: self.encryptor_curve = ec.SECP224R1() if strength not in [128, 256]: strength = 128 self.encryptor_strength = strength pri_key = ec.generate_private_key(self.encryptor_curve, default_backend()) pub_key = pri_key.public_key() peer_pub_key = load_pem_public_key(open(pem_pub_file, 'rb').read(), backend=default_backend()) secret = pri_key.exchange(ec.ECDH(), peer_pub_key) self.encrypted_iv = hashlib.md5(secret).digest() if strength == 128: self.encrypted_key = secret[0:16] else: if len(secret) == 32: self.encrypted_key = secret else: self.encrypted_key = hashlib.sha256(secret).digest() self.encrypted_send_pub_key = utils.int_to_bytes(pub_key.public_numbers().x, 32) + utils.int_to_bytes(pub_key.public_numbers().y, 32)
def dh_message(private_secret: dh.DHPublicNumbers) -> bytes: """ Generate the public part, a message to be sent to the other party. """ gx = pow(private_secret.parameter_numbers.g, private_secret.y, private_secret.parameter_numbers.p) return utils.int_to_bytes(gx)
def to_map(self): jwk = { 'kty': self.key_type(), 'kid': self.key_id(), 'crv': self.curve_name, } x_bytes = cry_utils.int_to_bytes(self.numbers.x) y_bytes = cry_utils.int_to_bytes(self.numbers.y) octet_length = (self.curve.bit_size() + 7) >> 3 x_bytes = b'\x00' * (octet_length - len(x_bytes)) + x_bytes y_bytes = b'\x00' * (octet_length - len(y_bytes)) + y_bytes jwk['x'] = util.jose_base64_url_encode(x_bytes).decode('utf-8') jwk['y'] = util.jose_base64_url_encode(y_bytes).decode('utf-8') return jwk
def _key_identifier_from_public_key(public_key): if isinstance(public_key, RSAPublicKey): data = public_key.public_bytes( serialization.Encoding.DER, serialization.PublicFormat.PKCS1, ) elif isinstance(public_key, EllipticCurvePublicKey): data = public_key.public_numbers().encode_point() else: # This is a very slow way to do this. serialized = public_key.public_bytes( serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo ) spki, remaining = decoder.decode( serialized, asn1Spec=_SubjectPublicKeyInfo() ) assert not remaining # the univ.BitString object is a tuple of bits. We need bytes and # pyasn1 really doesn't want to give them to us. To get it we'll # build an integer and convert that to bytes. bits = 0 for bit in spki.getComponentByName("subjectPublicKey"): bits = bits << 1 | bit data = utils.int_to_bytes(bits) return hashlib.sha1(data).digest()
def _generate_fixed_input(self): if self._fixed_data and isinstance(self._fixed_data, bytes): return self._fixed_data l = utils.int_to_bytes(self._length * 8, self._llen) return b"".join([self._label, b"\x00", self._context, l])
def _get_key_attributes(self, key): if isinstance(key, rsa.RSAPrivateKey): return struct.pack('>BHHB', 0x01, key.key_size, 32, 0) if isinstance(key, ec.EllipticCurvePrivateKey): return int_to_bytes(self._get_opgp_algo_id_from_ec(key)) + a2b_hex( self._get_oid_from_ec(key)) raise ValueError('Not a valid private key!')
def to_map(self): return { 'kty': self.key_type(), 'kid': self.key_id(), 'n': util.jose_base64_url_encode(cry_utils.int_to_bytes(self.numbers.n)).decode('utf-8'), 'e': util.jose_base64_url_encode(util.serialize_rsa_public_exponent_param(self.numbers.e)).decode('utf-8') }
def _generate_fixed_input(self) -> bytes: if self._fixed_data and isinstance(self._fixed_data, bytes): return self._fixed_data l_val = utils.int_to_bytes(self._length * 8, self._llen) return b"".join([self._label, b"\x00", self._context, l_val])
def encode_der_integer(x): if not isinstance(x, int): raise ValueError("Value must be an integer") if x < 0: raise ValueError("Negative integers are not supported") n = x.bit_length() // 8 + 1 return int_to_bytes(x, n)
def test_rsa_pkcs1_decrypt_errors(self): rawmessages = [ # no actual padding bytes: b"\x00\x02\x00" + b"\xc3" * 236 + b"\x00", # first byte != 0x00: b"\x01\x02" + b"\xc3" * 237 + b"\x00", # second byte != 0x02: b"\x00\x01" + b"\xc3" * 237 + b"\x00", # only 7 bytes of padding: b"\x00\x02" + b"\xc3" * 7 + b"\x00" + b"\x3c" * 246, ] rsakey = rsa.generate_private_key(public_exponent=0x10001, key_size=2048, backend=default_backend()) key = AsymmetricKey.put(self.session, 0, "pkcs1 test", 0xFFFF, CAPABILITY.DECRYPT_PKCS, rsakey) numbers = key.get_public_key().public_numbers() for m in rawmessages: error = ERROR.OK m = m.ljust(256, b"\xc3") m_int = int_from_bytes(m, "big") enc = pow(m_int, numbers.e, numbers.n) try: key.decrypt_pkcs1v1_5(int_to_bytes(enc).rjust(256, b"\x00")) except YubiHsmDeviceError as e: error = e.code self.assertEqual(error, ERROR.INVALID_DATA) key.delete()
def number_as_bytes(number, pad_bits=None): """ Given a number, format as a little endian array of bytes """ result = int_to_bytes(number)[::-1] while pad_bits is not None and len(result) < (pad_bits // 8): result += b'\x00' return result
def _to_mpint(val): """Storage format for signed bigint.""" if val < 0: raise ValueError("negative mpint not allowed") if not val: return b"" nbytes = (val.bit_length() + 8) // 8 return utils.int_to_bytes(val, nbytes)
def MP(number): if number == 0: return b'\000' * 4 assert number > 0 bn = int_to_bytes(number) if ord(bn[0:1]) & 128: bn = b'\000' + bn return struct.pack('>L', len(bn)) + bn
def _valid_byte_length(self, value): if not isinstance(value, int): raise TypeError('value must be of type int') value_bin = utils.int_to_bytes(1, value) if not 1 <= len(value_bin) <= 4: return False return True
def load_rsa_public_numbers(self, numbers): rsa._check_public_key_components(numbers.e, numbers.n) attrs = build_attributes([ (self._binding.CKA_TOKEN, False), # don't persist it (self._binding.CKA_CLASS, self._binding.CKO_PUBLIC_KEY), (self._binding.CKA_KEY_TYPE, self._binding.CKK_RSA), (self._binding.CKA_MODULUS, utils.int_to_bytes(numbers.n)), (self._binding.CKA_PUBLIC_EXPONENT, utils.int_to_bytes(numbers.e)), ], self) session = self._session_pool.acquire() # TODO: do we want to delete the object from the session when it # is no longer in scope? object_handle = self._ffi.new("CK_OBJECT_HANDLE *") res = self._lib.C_CreateObject( session[0], attrs.template, len(attrs.template), object_handle ) self._check_error(res) return _RSAPublicKey(self, object_handle[0])
def generate_rsa_private_key(self, public_exponent, key_size): # TODO: we need to be able to pass templates in. right now all keys # are generated as session only and exportable. And this is all # untested so far session = self._session_pool.acquire() public_handle = self._ffi.new("CK_OBJECT_HANDLE *") private_handle = self._ffi.new("CK_OBJECT_HANDLE *") mech = self._ffi.new("CK_MECHANISM *") mech.mechanism = self._binding.CKM_RSA_PKCS_KEY_PAIR_GEN pub_attrs = build_attributes([ ( self._binding.CKA_PUBLIC_EXPONENT, utils.int_to_bytes(public_exponent) ), (self._binding.CKA_MODULUS_BITS, key_size), (self._binding.CKA_TOKEN, False), # don't persist it (self._binding.CKA_PRIVATE, False), (self._binding.CKA_ENCRYPT, True), (self._binding.CKA_VERIFY, True), ], self) priv_attrs = build_attributes([ (self._binding.CKA_TOKEN, False), # don't persist it (self._binding.CKA_PRIVATE, False), (self._binding.CKA_DECRYPT, True), (self._binding.CKA_SIGN, True), (self._binding.CKA_EXTRACTABLE, True) ], self) # TODO: remember that you can get the public key values from # CKA_MODULUS and CKA_PUBLIC_EXPONENT. but you can't perform # operations on them so we probably still need to think of these as # keypairs res = self._lib.C_GenerateKeyPair( session[0], mech, pub_attrs.template, len(pub_attrs.template), priv_attrs.template, len(priv_attrs.template), public_handle, private_handle ) self._check_error(res) return _RSAPrivateKey(self, private_handle[0])
def _get_key_data(key): if isinstance(key, rsa.RSAPrivateKey): if key.public_key().public_numbers().e != 65537: raise UnsupportedAlgorithm( 'Unsupported RSA exponent: %d' % key.public_key().public_numbers().e, key=key) if key.key_size == 1024: algo = ALGO.RSA1024 ln = 64 elif key.key_size == 2048: algo = ALGO.RSA2048 ln = 128 else: raise UnsupportedAlgorithm( 'Unsupported RSA key size: %d' % key.key_size, key=key) priv = key.private_numbers() data = Tlv(0x01, int_to_bytes(priv.p, ln)) + \ Tlv(0x02, int_to_bytes(priv.q, ln)) + \ Tlv(0x03, int_to_bytes(priv.dmp1, ln)) + \ Tlv(0x04, int_to_bytes(priv.dmq1, ln)) + \ Tlv(0x05, int_to_bytes(priv.iqmp, ln)) elif isinstance(key, ec.EllipticCurvePrivateKey): if isinstance(key.curve, ec.SECP256R1): algo = ALGO.ECCP256 ln = 32 elif isinstance(key.curve, ec.SECP384R1): algo = ALGO.ECCP384 ln = 48 else: raise UnsupportedAlgorithm( 'Unsupported elliptic curve: %s', key.curve, key=key) priv = key.private_numbers() data = Tlv(0x06, int_to_bytes(priv.private_value, ln)) else: raise UnsupportedAlgorithm('Unsupported key type!', key=key) return algo, data
def _der_to_raw(self, der_signature): """Convert signature from DER encoding to RAW encoding.""" r, s = decode_dss_signature(der_signature) component_length = self._sig_component_length() return int_to_bytes(r, component_length) + int_to_bytes(s, component_length)
def _digest_for_signature(self, signing_key, signature): """ Provides the signed digest we should have given this key and signature. :param str signing_key: key block used to make this signature :param str signature: signed digest for this descriptor content :returns: the digest string encoded in uppercase hex :raises: ValueError if unable to provide a validly signed digest """ if not stem.prereq.is_crypto_available(): raise ValueError('Generating the signed digest requires the cryptography module') from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import load_der_public_key from cryptography.utils import int_to_bytes, int_from_bytes key = load_der_public_key(_bytes_for_block(signing_key), default_backend()) modulus = key.public_numbers().n public_exponent = key.public_numbers().e sig_as_bytes = _bytes_for_block(signature) sig_as_long = int_from_bytes(sig_as_bytes, byteorder='big') # convert signature to an int blocksize = len(sig_as_bytes) # 256B for NetworkStatusDocuments, 128B for others # use the public exponent[e] & the modulus[n] to decrypt the int decrypted_int = pow(sig_as_long, public_exponent, modulus) # convert the int to a byte array decrypted_bytes = int_to_bytes(decrypted_int, blocksize) ############################################################################ # The decrypted bytes should have a structure exactly along these lines. # 1 byte - [null '\x00'] # 1 byte - [block type identifier '\x01'] - Should always be 1 # N bytes - [padding '\xFF' ] # 1 byte - [separator '\x00' ] # M bytes - [message] # Total - 128 bytes # More info here http://www.ietf.org/rfc/rfc2313.txt # esp the Notes in section 8.1 ############################################################################ try: if decrypted_bytes.index(DIGEST_TYPE_INFO) != 0: raise ValueError('Verification failed, identifier missing') except ValueError: raise ValueError('Verification failed, malformed data') try: identifier_offset = 2 # find the separator seperator_index = decrypted_bytes.index(DIGEST_SEPARATOR, identifier_offset) except ValueError: raise ValueError('Verification failed, seperator not found') digest_hex = codecs.encode(decrypted_bytes[seperator_index + 1:], 'hex_codec') return stem.util.str_tools._to_unicode(digest_hex.upper())
def _encode_general_name(backend, name): if isinstance(name, x509.DNSName): gn = backend._lib.GENERAL_NAME_new() backend.openssl_assert(gn != backend._ffi.NULL) gn.type = backend._lib.GEN_DNS ia5 = backend._lib.ASN1_IA5STRING_new() backend.openssl_assert(ia5 != backend._ffi.NULL) # ia5strings are supposed to be ITU T.50 but to allow round-tripping # of broken certs that encode utf8 we'll encode utf8 here too. value = name.value.encode("utf8") res = backend._lib.ASN1_STRING_set(ia5, value, len(value)) backend.openssl_assert(res == 1) gn.d.dNSName = ia5 elif isinstance(name, x509.RegisteredID): gn = backend._lib.GENERAL_NAME_new() backend.openssl_assert(gn != backend._ffi.NULL) gn.type = backend._lib.GEN_RID obj = backend._lib.OBJ_txt2obj( name.value.dotted_string.encode('ascii'), 1 ) backend.openssl_assert(obj != backend._ffi.NULL) gn.d.registeredID = obj elif isinstance(name, x509.DirectoryName): gn = backend._lib.GENERAL_NAME_new() backend.openssl_assert(gn != backend._ffi.NULL) dir_name = _encode_name(backend, name.value) gn.type = backend._lib.GEN_DIRNAME gn.d.directoryName = dir_name elif isinstance(name, x509.IPAddress): gn = backend._lib.GENERAL_NAME_new() backend.openssl_assert(gn != backend._ffi.NULL) if isinstance(name.value, ipaddress.IPv4Network): packed = ( name.value.network_address.packed + utils.int_to_bytes(((1 << 32) - name.value.num_addresses), 4) ) elif isinstance(name.value, ipaddress.IPv6Network): packed = ( name.value.network_address.packed + utils.int_to_bytes((1 << 128) - name.value.num_addresses, 16) ) else: packed = name.value.packed ipaddr = _encode_asn1_str(backend, packed, len(packed)) gn.type = backend._lib.GEN_IPADD gn.d.iPAddress = ipaddr elif isinstance(name, x509.OtherName): gn = backend._lib.GENERAL_NAME_new() backend.openssl_assert(gn != backend._ffi.NULL) other_name = backend._lib.OTHERNAME_new() backend.openssl_assert(other_name != backend._ffi.NULL) type_id = backend._lib.OBJ_txt2obj( name.type_id.dotted_string.encode('ascii'), 1 ) backend.openssl_assert(type_id != backend._ffi.NULL) data = backend._ffi.new("unsigned char[]", name.value) data_ptr_ptr = backend._ffi.new("unsigned char **") data_ptr_ptr[0] = data value = backend._lib.d2i_ASN1_TYPE( backend._ffi.NULL, data_ptr_ptr, len(name.value) ) if value == backend._ffi.NULL: backend._consume_errors() raise ValueError("Invalid ASN.1 data") other_name.type_id = type_id other_name.value = value gn.type = backend._lib.GEN_OTHERNAME gn.d.otherName = other_name elif isinstance(name, x509.RFC822Name): gn = backend._lib.GENERAL_NAME_new() backend.openssl_assert(gn != backend._ffi.NULL) # ia5strings are supposed to be ITU T.50 but to allow round-tripping # of broken certs that encode utf8 we'll encode utf8 here too. data = name.value.encode("utf8") asn1_str = _encode_asn1_str(backend, data, len(data)) gn.type = backend._lib.GEN_EMAIL gn.d.rfc822Name = asn1_str elif isinstance(name, x509.UniformResourceIdentifier): gn = backend._lib.GENERAL_NAME_new() backend.openssl_assert(gn != backend._ffi.NULL) # ia5strings are supposed to be ITU T.50 but to allow round-tripping # of broken certs that encode utf8 we'll encode utf8 here too. data = name.value.encode("utf8") asn1_str = _encode_asn1_str(backend, data, len(data)) gn.type = backend._lib.GEN_URI gn.d.uniformResourceIdentifier = asn1_str else: raise ValueError( "{0} is an unknown GeneralName type".format(name) ) return gn
def _ssh_write_mpint(value): data = utils.int_to_bytes(value) if six.indexbytes(data, 0) & 0x80: data = b"\x00" + data return _ssh_write_string(data)