def generate_key(self, slot, algorithm, pin_policy=PIN_POLICY.DEFAULT, touch_policy=TOUCH_POLICY.DEFAULT): if ALGO.is_rsa(algorithm): ensure_not_cve201715361_vulnerable_firmware_version(self.version) if algorithm not in self.supported_algorithms: raise UnsupportedAlgorithm( 'Algorithm not supported on this YubiKey: {}'.format( algorithm), algorithm_id=algorithm) data = Tlv(TAG.ALGO, six.int2byte(algorithm)) if pin_policy: data += Tlv(TAG.PIN_POLICY, six.int2byte(pin_policy)) if touch_policy: data += Tlv(TAG.TOUCH_POLICY, six.int2byte(touch_policy)) data = Tlv(0xac, data) resp = self.send_cmd(INS.GENERATE_ASYMMETRIC, 0, slot, data) if algorithm in [ALGO.RSA1024, ALGO.RSA2048]: data = _parse_tlv_dict(Tlv(resp[1:]).value) return rsa.RSAPublicNumbers(int_from_bytes(data[0x82], 'big'), int_from_bytes(data[0x81], 'big')).public_key( default_backend()) elif algorithm in [ALGO.ECCP256, ALGO.ECCP384]: curve = ec.SECP256R1 if algorithm == ALGO.ECCP256 else ec.SECP384R1 return ec.EllipticCurvePublicNumbers.from_encoded_point( curve(), resp[5:]).public_key(default_backend()) raise UnsupportedAlgorithm('Invalid algorithm: {}'.format(algorithm), algorithm_id=algorithm)
def _load_ssh_ecdsa_public_key(expected_key_type, decoded_data, backend): curve_name, rest = _read_next_string(decoded_data) data, rest = _read_next_string(rest) if expected_key_type != b"ecdsa-sha2-" + curve_name: raise ValueError( 'Key header and key body contain different key type values.') if rest: raise ValueError('Key body contains extra bytes.') curve = { b"nistp256": ec.SECP256R1, b"nistp384": ec.SECP384R1, b"nistp521": ec.SECP521R1, }[curve_name]() if six.indexbytes(data, 0) != 4: raise NotImplementedError( "Compressed elliptic curve points are not supported") # key_size is in bits, and sometimes it's not evenly divisible by 8, so we # add 7 to round up the number of bytes. if len(data) != 1 + 2 * ((curve.key_size + 7) // 8): raise ValueError("Malformed key bytes") x = utils.int_from_bytes(data[1:1 + (curve.key_size + 7) // 8], byteorder='big') y = utils.int_from_bytes(data[1 + (curve.key_size + 7) // 8:], byteorder='big') return ec.EllipticCurvePublicNumbers(x, y, curve).public_key(backend)
def generate_rsa_key(self, key_slot, key_size, timestamp=None): """Requires Admin PIN verification.""" ensure_not_cve201715361_vulnerable_firmware_version(self.version) if timestamp is None: timestamp = int(time.time()) neo = self.version < (4, 0, 0) if not neo: attributes = _format_rsa_attributes(key_size) self._put_data(key_slot.key_id, attributes) elif key_size != 2048: raise ValueError('Unsupported key size!') resp = self.send_cmd(0, INS.GENERATE_ASYM, 0x80, 0x00, key_slot.crt) data = Tlv.parse_dict(Tlv.unpack(0x7f49, resp)) numbers = rsa.RSAPublicNumbers( int_from_bytes(data[0x82], 'big'), int_from_bytes(data[0x81], 'big') ) self._put_data(key_slot.gen_time, struct.pack('>I', timestamp)) # TODO: Calculate and write fingerprint return numbers.public_key(default_backend())
def _load_ssh_ecdsa_public_key(expected_key_type, decoded_data, backend): curve_name, rest = _read_next_string(decoded_data) data, rest = _read_next_string(rest) if expected_key_type != b"ecdsa-sha2-" + curve_name: raise ValueError( 'Key header and key body contain different key type values.' ) if rest: raise ValueError('Key body contains extra bytes.') curve = { b"nistp256": ec.SECP256R1, b"nistp384": ec.SECP384R1, b"nistp521": ec.SECP521R1, }[curve_name]() if six.indexbytes(data, 0) != 4: raise NotImplementedError( "Compressed elliptic curve points are not supported" ) # key_size is in bits, and sometimes it's not evenly divisible by 8, so we # add 7 to round up the number of bytes. if len(data) != 1 + 2 * ((curve.key_size + 7) // 8): raise ValueError("Malformed key bytes") x = utils.int_from_bytes( data[1:1 + (curve.key_size + 7) // 8], byteorder='big' ) y = utils.int_from_bytes( data[1 + (curve.key_size + 7) // 8:], byteorder='big' ) return ec.EllipticCurvePublicNumbers(x, y, curve).public_key(backend)
def _get_e_n(backend, handle): # TODO: These buffers could be dynamically sized in the future, but # it would require two calls to the PKCS11 layer. Right now it will # work with a single call as long as the key is 8192-bit or smaller and # the modulus isn't some ludicrous value. attrs = build_attributes([ ( backend._binding.CKA_MODULUS, backend._ffi.new("unsigned char[]", 1024) ), ( backend._binding.CKA_PUBLIC_EXPONENT, backend._ffi.new("unsigned char[]", 64) ), ], backend) session = backend._session_pool.acquire() res = backend._lib.C_GetAttributeValue( session[0], handle, attrs.template, len(attrs.template) ) backend._check_error(res) n = utils.int_from_bytes( backend._ffi.buffer( attrs.template[0].value, attrs.template[0].value_len )[:], 'big' ) e = utils.int_from_bytes( backend._ffi.buffer( attrs.template[1].value, attrs.template[1].value_len )[:], 'big' ) return e, n
def generate_key(self, slot, algorithm, pin_policy=PIN_POLICY.DEFAULT, touch_policy=TOUCH_POLICY.DEFAULT): if ALGO.is_rsa(algorithm): ensure_not_cve201715361_vulnerable_firmware_version(self.version) if algorithm not in self.supported_algorithms: raise UnsupportedAlgorithm( 'Algorithm not supported on this YubiKey: {}' .format(algorithm), algorithm_id=algorithm) data = Tlv(TAG.ALGO, six.int2byte(algorithm)) if pin_policy: data += Tlv(TAG.PIN_POLICY, six.int2byte(pin_policy)) if touch_policy: data += Tlv(TAG.TOUCH_POLICY, six.int2byte(touch_policy)) data = Tlv(0xac, data) resp = self.send_cmd(INS.GENERATE_ASYMMETRIC, 0, slot, data) if algorithm in [ALGO.RSA1024, ALGO.RSA2048]: data = _parse_tlv_dict(Tlv(resp[1:]).value) return rsa.RSAPublicNumbers( int_from_bytes(data[0x82], 'big'), int_from_bytes(data[0x81], 'big') ).public_key(default_backend()) elif algorithm in [ALGO.ECCP256, ALGO.ECCP384]: curve = ec.SECP256R1 if algorithm == ALGO.ECCP256 else ec.SECP384R1 return ec.EllipticCurvePublicNumbers.from_encoded_point( curve(), resp[5:] ).public_key(default_backend()) raise UnsupportedAlgorithm( 'Invalid algorithm: {}'.format(algorithm), algorithm_id=algorithm)
def get_public_key(self): """Get the public key of the key pair. This will return either a :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or a :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey` depending on the algorithm of the key. Ed25519 keys use an internal representation which can be serialized using the :func:`~yubihsm.eddsa.serialize_ed25519_public_key` function. :return: The public key of the key pair. """ msg = struct.pack('!H', self.id) ret = self.session.send_secure_cmd(COMMAND.GET_PUBLIC_KEY, msg) algo = ALGORITHM(six.indexbytes(ret, 0)) raw_key = ret[1:] if algo in [ALGORITHM.RSA_2048, ALGORITHM.RSA_3072, ALGORITHM.RSA_4096]: num = int_from_bytes(raw_key, 'big') pubkey = rsa.RSAPublicNumbers(e=0x10001, n=num) elif algo in [ ALGORITHM.EC_P224, ALGORITHM.EC_P256, ALGORITHM.EC_P384, ALGORITHM.EC_P521, ALGORITHM.EC_K256, ALGORITHM.EC_BP256, ALGORITHM.EC_BP384, ALGORITHM.EC_BP512 ]: c_len = len(raw_key) // 2 x = int_from_bytes(raw_key[:c_len], 'big') y = int_from_bytes(raw_key[c_len:], 'big') pubkey = ec.EllipticCurvePublicNumbers( curve=algo.to_curve(), x=x, y=y) elif algo in [ALGORITHM.EC_ED25519]: return _Ed25519PublicKey(raw_key) return pubkey.public_key(backend=default_backend())
def from_jwk(cls, jwk): """ Create a :py:class:`~oneid.keychain.Keypair` from a JWK :param jwk: oneID-standard JWK :return: :py:class:`~oneid.keychain.Keypair` instance :raises InvalidFormatError: if not a valid JWK """ if jwk['kty'] != 'EC' or jwk['crv'] != 'P-256': raise exceptions.InvalidFormatError public_numbers = ec.EllipticCurvePublicNumbers( x=int_from_bytes(utils.base64url_decode(jwk['x']), 'big'), y=int_from_bytes(utils.base64url_decode(jwk['y']), 'big'), curve=ec.SECP256R1(), ) ret = cls() ret._public_key = public_numbers.public_key(_BACKEND) if 'd' in jwk: private_numbers = ec.EllipticCurvePrivateNumbers( private_value=int_from_bytes(utils.base64url_decode(jwk['d']), 'big'), public_numbers=public_numbers, ) ret._private_key = private_numbers.private_key(_BACKEND) if 'kid' in jwk: ret.identity = jwk['kid'] return ret
def from_jwk(jwk): try: obj = json.loads(jwk) except ValueError: raise InvalidKeyError("Key is not valid JSON") if obj.get("kty") != "EC": raise InvalidKeyError("Not an Elliptic curve key") if "x" not in obj or "y" not in obj: raise InvalidKeyError("Not an Elliptic curve key") x = base64url_decode(force_bytes(obj.get("x"))) y = base64url_decode(force_bytes(obj.get("y"))) curve = obj.get("crv") if curve == "P-256": if len(x) == len(y) == 32: curve_obj = ec.SECP256R1() else: raise InvalidKeyError( "Coords should be 32 bytes for curve P-256" ) elif curve == "P-384": if len(x) == len(y) == 48: curve_obj = ec.SECP384R1() else: raise InvalidKeyError( "Coords should be 48 bytes for curve P-384" ) elif curve == "P-521": if len(x) == len(y) == 66: curve_obj = ec.SECP521R1() else: raise InvalidKeyError( "Coords should be 66 bytes for curve P-521" ) else: raise InvalidKeyError("Invalid curve: {}".format(curve)) public_numbers = ec.EllipticCurvePublicNumbers( x=int_from_bytes(x, "big"), y=int_from_bytes(y, "big"), curve=curve_obj, ) if "d" not in obj: return public_numbers.public_key() d = base64url_decode(force_bytes(obj.get("d"))) if len(d) != len(x): raise InvalidKeyError( "D should be {} bytes for curve {}", len(x), curve ) return ec.EllipticCurvePrivateNumbers( int_from_bytes(d, "big"), public_numbers ).private_key()
def __init__(self): if CRYPTOGRAPHY_MISSING: self.active = False else: self.DH_PRIME_1024 = int_from_bytes(self.DH_PRIME_1024_BYTES, 'big') self.pkey = int_from_bytes(os.urandom(128), 'big') self.pubkey = pow(2, self.pkey, self.DH_PRIME_1024)
def _raw_to_der(self, raw_signature): """Convert signature from RAW encoding to DER encoding.""" component_length = self._sig_component_length() if len(raw_signature) != int(2 * component_length): raise ValueError("Invalid signature") r_bytes = raw_signature[:component_length] s_bytes = raw_signature[component_length:] r = int_from_bytes(r_bytes, "big") s = int_from_bytes(s_bytes, "big") return encode_dss_signature(r, s)
def _split_raw_signature(sig): """ Split raw signature into components :param sig: The signature :return: A 2-tuple """ c_length = len(sig) // 2 r = int_from_bytes(sig[:c_length], byteorder="big") s = int_from_bytes(sig[c_length:], byteorder="big") return r, s
def from_jwk(jwk): try: obj = json.loads(jwk) except ValueError: raise InvalidKeyError('Key is not valid JSON') if obj.get('kty') != 'EC': raise InvalidKeyError('Not an Elliptic curve key') if 'x' not in obj or 'y' not in obj: raise InvalidKeyError('Not an Elliptic curve key') x = base64url_decode(force_bytes(obj.get('x'))) y = base64url_decode(force_bytes(obj.get('y'))) curve = obj.get('crv') if curve == 'P-256': if len(x) == len(y) == 32: curve_obj = ec.SECP256R1() else: raise InvalidKeyError( "Coords should be 32 bytes for curve P-256") elif curve == 'P-384': if len(x) == len(y) == 48: curve_obj = ec.SECP384R1() else: raise InvalidKeyError( "Coords should be 48 bytes for curve P-384") elif curve == 'P-521': if len(x) == len(y) == 66: curve_obj = ec.SECP521R1() else: raise InvalidKeyError( "Coords should be 66 bytes for curve P-521") else: raise InvalidKeyError("Invalid curve: {}".format(curve)) public_numbers = ec.EllipticCurvePublicNumbers( x=int_from_bytes(x, 'big'), y=int_from_bytes(y, 'big'), curve=curve_obj) if 'd' not in obj: return public_numbers.public_key(default_backend()) d = base64url_decode(force_bytes(obj.get('d'))) if len(d) != len(x): raise InvalidKeyError("D should be {} bytes for curve {}", len(x), curve) return ec.EllipticCurvePrivateNumbers(int_from_bytes( d, 'big'), public_numbers).private_key(default_backend())
def _load_ecdsa(key, is_verifier): if key.get('kty') != 'EC': raise JWKError('Not an Elliptic curve key') if 'x' not in key or 'y' not in key: raise JWKError('Not an Elliptic curve key') x = base64.urlsafe_b64decode(key.get('x')) y = base64.urlsafe_b64decode(key.get('y')) curve = key.get('crv') if curve == 'P-256': if len(x) == len(y) == 32: alg = 'ES256' curve_obj = ec.SECP256R1() else: raise JWKError("Coords should be 32 bytes for curve P-256") elif curve == 'P-384': if len(x) == len(y) == 48: alg = "ES384" curve_obj = ec.SECP384R1() else: raise JWKError("Coords should be 48 bytes for curve P-384") elif curve == 'P-521': if len(x) == len(y) == 66: alg = "ES512" curve_obj = ec.SECP521R1() else: raise JWKError("Coords should be 66 bytes for curve P-521") else: raise JWKError("Invalid curve: {}".format(curve)) public_numbers = ec.EllipticCurvePublicNumbers(x=int_from_bytes(x, 'big'), y=int_from_bytes(y, 'big'), curve=curve_obj) if not is_verifier: if 'd' not in key: raise JWKError("Signing ECDSA keys must contain private key") d = base64.urlsafe_b64decode(key.get('d')) if len(d) != len(x): raise JWKError("D should be {} bytes for curve {}", len(x), curve) key = ec.EllipticCurvePrivateNumbers(int_from_bytes( d, 'big'), public_numbers).private_key(default_backend()) else: key = public_numbers.public_key(default_backend()) return alg, key
def verify(self, message, signature): # First convert (r||s) raw signature to ASN1 encoded signature. sig_bytes = _helpers.to_bytes(signature) if len(sig_bytes) != 64: return False r = utils.int_from_bytes(sig_bytes[:32], byteorder="big") s = utils.int_from_bytes(sig_bytes[32:], byteorder="big") asn1_sig = encode_dss_signature(r, s) message = _helpers.to_bytes(message) try: self._pubkey.verify(asn1_sig, message, ec.ECDSA(hashes.SHA256())) return True except (ValueError, cryptography.exceptions.InvalidSignature): return False
def from_encoded_point(cls, curve, data): if not isinstance(curve, EllipticCurve): raise TypeError("curve must be an EllipticCurve instance") if data.startswith(b'\x04'): # key_size is in bits. Convert to bytes and round up byte_length = (curve.key_size + 7) // 8 if len(data) == 2 * byte_length + 1: x = utils.int_from_bytes(data[1:byte_length + 1], 'big') y = utils.int_from_bytes(data[byte_length + 1:], 'big') return cls(x, y, curve) else: raise ValueError('Invalid elliptic curve point data length') else: raise ValueError('Unsupported elliptic curve point type')
def test_dh_vectors_with_q(self, backend, vector): parameters = dh.DHParameterNumbers( int(vector["p"], 16), int(vector["g"], 16), int(vector["q"], 16) ) public1 = dh.DHPublicNumbers(int(vector["ystatcavs"], 16), parameters) private1 = dh.DHPrivateNumbers(int(vector["xstatcavs"], 16), public1) public2 = dh.DHPublicNumbers(int(vector["ystatiut"], 16), parameters) private2 = dh.DHPrivateNumbers(int(vector["xstatiut"], 16), public2) key1 = private1.private_key(backend) key2 = private2.private_key(backend) symkey1 = key1.exchange(public2.public_key(backend)) symkey2 = key2.exchange(public1.public_key(backend)) assert int_from_bytes(symkey1, "big") == int(vector["z"], 16) assert int_from_bytes(symkey2, "big") == int(vector["z"], 16)
def test_dh_vectors_with_q(self, backend, vector): parameters = dh.DHParameterNumbers(int(vector["p"], 16), int(vector["g"], 16), int(vector["q"], 16)) public1 = dh.DHPublicNumbers(int(vector["ystatcavs"], 16), parameters) private1 = dh.DHPrivateNumbers(int(vector["xstatcavs"], 16), public1) public2 = dh.DHPublicNumbers(int(vector["ystatiut"], 16), parameters) private2 = dh.DHPrivateNumbers(int(vector["xstatiut"], 16), public2) key1 = private1.private_key(backend) key2 = private2.private_key(backend) symkey1 = key1.exchange(public2.public_key(backend)) symkey2 = key2.exchange(public1.public_key(backend)) assert int_from_bytes(symkey1, 'big') == int(vector["z"], 16) assert int_from_bytes(symkey2, 'big') == int(vector["z"], 16)
def generate_self_signed_certificate(common_name="Test", valid_from=None, valid_to=None): valid_from = valid_from if valid_from else datetime.datetime.utcnow() valid_to = valid_to if valid_to else valid_from + datetime.timedelta( days=1) private_key = _generate_private_key() public_key = private_key.public_key() builder = x509.CertificateBuilder() builder = builder.public_key(public_key) builder = builder.subject_name( x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, common_name)])) # Same as subject on self-signed certificates. builder = builder.issuer_name( x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, common_name)])) # x509.random_serial_number added in cryptography 1.6 serial = int_from_bytes(os.urandom(20), "big") >> 1 builder = builder.serial_number(serial) builder = builder.not_valid_before(valid_from) builder = builder.not_valid_after(valid_to) return _sign_cert(private_key, builder)
def __init__(self, private_key=None): ''' takes in a b64 encoded string or standard text private key and returns a PrivateKey object ''' if private_key: base64_data = False if isinstance(private_key, str): private_key = private_key.encode() try: data = base64.b64encode(base64.b64decode(private_key)) if data == private_key: private_key = base64.b64decode(data) base64_data = True except binascii.Error: pass if isinstance(private_key, bytes) and not base64_data: self.key = sz.load_pem_private_key(private_key, None, default_backend()) elif isinstance(private_key, bytes) and base64_data: data = utils.int_from_bytes(private_key, 'big') self.key = ec.derive_private_key(data, ec.SECP256R1(), default_backend()) else: self.key = ec.generate_private_key(ec.SECP256R1(), default_backend()) self._pub_key = PEMPublicKey(self.key.public_key())
def dh_shared_secret(message: bytes, private_secret: dh.DHPublicNumbers) -> dh.DHPrivateNumbers: """ Compute the shared secret from private secret and the other party's message. """ gx = utils.int_from_bytes(message, 'big') gxy = pow(gx, private_secret.y, private_secret.parameter_numbers.p) return dh.DHPrivateNumbers(gxy, private_secret)
def __init__(self) -> None: self.object_path = None # type: Optional[str] self.aes_key = None # type: Optional[bytes] self.encrypted = True # 128-bytes-long strong random number self.my_private_key = int_from_bytes(os.urandom(0x80), 'big') self.my_public_key = pow(2, self.my_private_key, DH_PRIME_1024)
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 parse_ec_coordinate(cb64url, curve): curve_byte_len = (curve.bit_size() + 7) >> 3 c_bytes = jose_base64_url_decode(cb64url) if len(c_bytes) != curve_byte_len: raise Exception("invalid number of octets: got %d, should be %d", len(c_bytes), curve_byte_len) return cry_utils.int_from_bytes(c_bytes, 'big')
def generate_self_signed_certificate( self, slot, public_key, common_name, valid_from, valid_to, touch_callback=None): algorithm = ALGO.from_public_key(public_key) builder = x509.CertificateBuilder() builder = builder.public_key(public_key) builder = builder.subject_name( x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, common_name), ])) # Same as subject on self-signed certificates. builder = builder.issuer_name( x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, common_name), ])) # x509.random_serial_number added in cryptography 1.6 serial = int_from_bytes(os.urandom(20), 'big') >> 1 builder = builder.serial_number(serial) builder = builder.not_valid_before(valid_from) builder = builder.not_valid_after(valid_to) try: cert = self.sign_cert_builder( slot, algorithm, builder, touch_callback) except APDUError as e: logger.error('Failed to generate certificate for slot %s', slot, exc_info=e) raise self.import_certificate(slot, cert, verify=False)
def verify_host(digest, signature, public_key_data): """ verify a signature using the host software """ try: public_key_data = b'\x04' + public_key_data r = int_from_bytes(signature[0:32], byteorder='big', signed=False) s = int_from_bytes(signature[32:64], byteorder='big', signed=False) sig = utils.encode_dss_signature(r, s) public_key = ec.EllipticCurvePublicNumbers.from_encoded_point(ec.SECP256R1(), public_key_data).public_key(default_backend()) public_key.verify(sig, digest, ec.ECDSA(utils.Prehashed(hashes.SHA256()))) return True except InvalidSignature: return False
def __init__(self): self.object_path = None self.server_public_key = None self.aes_key = None self.encrypted = True # 128-bytes-long strong random number self.my_private_key = int_from_bytes(os.urandom(0x80), 'big') self.my_public_key = pow(2, self.my_private_key, DH_PRIME_1024)
def _unpad_message(padded, padding): e = 65537 dummy = rsa.generate_private_key(e, len(padded) * 8, default_backend()) # Raw (textbook) RSA encrypt n = dummy.public_key().public_numbers().n encrypted = int_to_bytes(pow(int_from_bytes(padded, "big"), e, n), len(padded)) return dummy.decrypt(encrypted, padding)
def test_dh_vectors(self, backend, vector): parameters = dh.DHParameterNumbers(int(vector["p"]), int(vector["g"])) public = dh.DHPublicNumbers(int(vector["y"]), parameters) private = dh.DHPrivateNumbers(int(vector["x"]), public) key = private.private_key(backend) symkey = key.exchange(public.public_key(backend)) assert int_from_bytes(symkey, 'big') == int(vector["k"], 16)
def challenge_response(s, key_clie_pri, key_clie_pub, key_serv_pub): # implement a Challenge-Response Authentication protocol and derive a session key # Stage 1 # Client Sends to server a magic number (serial) and the signature of magic number # encrypted with the servers public key seq_id = 1 # holds the sequence numbers in packet's serial = int_from_bytes(os.urandom(4), byteorder="big") m = size_in_8bit(seq_id) + size_in_32bit(serial) serial_sig = rsa_module.sign_data(m, key_clie_pri) message1 = serial_sig + m ciphertext1 = rsa_module.rsa_cbc_encrypt(message1, key_serv_pub) s.sendall(ciphertext1) # time delay if under attack time.sleep(1) # Stage 2 # Recieve Data ciphertext2 = s.recv(size) # Decrypt Data message2 = rsa_module.rsa_cbc_dencrypt(ciphertext2, key_clie_pri) # Verify Data serial_sig_server = message2[:256] rsa_module.verify_data(message2[256:], serial_sig_server, key_serv_pub) # Extract Data seq_id_server = message2[256:256 + 8] serial_reply = message2[256 + 8:256 + 8 + 32] serial_server = message2[256 + 8 + 32:256 + 8 + 32 + 32] if serial_reply != size_in_32bit(serial): print "Signature don't match" return False print "Server is authenticated" # update sequence id seq_id = seq_id + size_bin_int(seq_id_server) m = size_in_8bit(seq_id) + serial_server serial_sig = rsa_module.sign_data(m, key_clie_pri) message3 = serial_sig + m ciphertext3 = rsa_module.rsa_cbc_encrypt(message3, key_serv_pub) s.sendall(ciphertext3) time.sleep(1) print "Challenge Response was Successful" # Stage 4 get AES key from server (Session Key) session_key = s.recv(size) session_key = b64decode(session_key) aes_data = rsa_module.rsa_cbc_dencrypt(session_key, key_clie_pri) aes_sig = aes_data[:256] aes_key = aes_data[256:] rsa_module.verify_data(aes_key, aes_sig, key_serv_pub) return aes_key
def dh_shared_secret( message: bytes, private_secret: dh.DHPublicNumbers) -> dh.DHPrivateNumbers: """ Compute the shared secret from private secret and the other party's message. """ gx = utils.int_from_bytes(message, 'big') gxy = pow(gx, private_secret.y, private_secret.parameter_numbers.p) return dh.DHPrivateNumbers(gxy, private_secret)
def test_dh_parameters_allows_rfc3526_groups(self, backend, vector): p = int_from_bytes(binascii.unhexlify(vector["p"]), 'big') params = dh.DHParameterNumbers(p, int(vector["g"])) param = params.parameters(backend) key = param.generate_private_key() # This confirms that a key generated with this group # will pass DH_check when we serialize and de-serialize it via # the Numbers path. roundtripped_key = key.private_numbers().private_key(backend) assert key.private_numbers() == roundtripped_key.private_numbers()
def _read_next_mpint(data): """ Reads the next mpint from the data. Currently, all mpints are interpreted as unsigned. """ mpint_data, rest = _read_next_string(data) return (utils.int_from_bytes(mpint_data, byteorder='big', signed=False), rest)
def set_server_public_key(self, server_public_key): common_secret = pow(int_from_bytes(server_public_key, 'big'), self.pkey, self.DH_PRIME_1024) common_secret = self.int_to_bytes(common_secret) # Prepend NULL bytes if needed common_secret = b'\x00' * (0x80 - len(common_secret)) + common_secret # HKDF with null salt, empty info and SHA-256 hash salt = b'\x00' * 0x20 pseudo_random_key = hmac.new(salt, common_secret, sha256).digest() output_block = hmac.new(pseudo_random_key, b'\x01', sha256).digest() # Resulting AES key should be 128-bit self.aes_key = output_block[:0x10]
def _ssh_read_next_mpint(data): """ Reads the next mpint from the data. Currently, all mpints are interpreted as unsigned. """ mpint_data, rest = _ssh_read_next_string(data) return ( utils.int_from_bytes(mpint_data, byteorder='big', signed=False), rest )
def set_server_public_key(self, server_public_key: Sequence): common_secret = pow(int_from_bytes(server_public_key, 'big'), self.pkey, self.DH_PRIME_1024) common_secret = int_to_bytes(common_secret) hkdf = HKDF(algorithm=hashes.SHA256(), length=16, salt=None, info=None, backend=default_backend()) self.aes_key = hkdf.derive(common_secret)
def from_encoded_point(cls, curve, data): if not isinstance(curve, EllipticCurve): raise TypeError("curve must be an EllipticCurve instance") warnings.warn( "Support for unsafe construction of public numbers from " "encoded data will be removed in a future version. " "Please use EllipticCurvePublicKey.from_encoded_point", utils.DeprecatedIn25, stacklevel=2, ) if data.startswith(b'\x04'): # key_size is in bits. Convert to bytes and round up byte_length = (curve.key_size + 7) // 8 if len(data) == 2 * byte_length + 1: x = utils.int_from_bytes(data[1:byte_length + 1], 'big') y = utils.int_from_bytes(data[byte_length + 1:], 'big') return cls(x, y, curve) else: raise ValueError('Invalid elliptic curve point data length') else: raise ValueError('Unsupported elliptic curve point type')
def test_exchange_algorithm(self, backend): parameters = dh.generate_parameters(2, 512, backend) key1 = parameters.generate_private_key() key2 = parameters.generate_private_key() shared_key_bytes = key2.exchange(key1.public_key()) symkey = int_from_bytes(shared_key_bytes, 'big') symkey_manual = pow(key1.public_key().public_numbers().y, key2.private_numbers().x, parameters.parameter_numbers().p) assert symkey == symkey_manual
def getMP(data, count=1): """ Get multiple precision integer out of the string. A multiple precision integer is stored as a 4-byte length followed by length bytes of the integer. If count is specified, get count integers out of the string. The return value is a tuple of count integers followed by the rest of the data. """ mp = [] c = 0 for i in range(count): length, = struct.unpack('>L', data[c:c + 4]) mp.append(int_from_bytes(data[c + 4:c + 4 + length], 'big')) c += 4 + length return tuple(mp) + (data[c:],)
def test_certificate(): from cryptography import utils from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives import serialization from cryptography.x509.oid import NameOID one_day = datetime.timedelta(1, 0, 0) private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend()) public_key = private_key.public_key() builder = x509.CertificateBuilder() builder = builder.subject_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, u'example.com'), ])) builder = builder.issuer_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, u'example.com'), ])) builder = builder.not_valid_before(datetime.datetime.today() - one_day) builder = builder.not_valid_after(datetime.datetime.today() + one_day) builder = builder.serial_number( utils.int_from_bytes(os.urandom(20), "big") >> 1) builder = builder.public_key(public_key) builder = builder.add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True) certificate = builder.sign( private_key=private_key, algorithm=hashes.SHA256(), backend=default_backend()) certificate_pem = certificate.public_bytes(serialization.Encoding.PEM) public_key_bytes = certificate.public_key().public_bytes( serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo) private_key_bytes = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()) yield certificate, certificate_pem, public_key_bytes, private_key_bytes
def test_int_from_bytes_bytearray(): assert utils.int_from_bytes(bytearray(b"\x02\x10"), "big") == 528 with pytest.raises(TypeError): utils.int_from_bytes(["list", "is", "not", "bytes"], "big")
from paramiko.client import SSHClient as ParamikoSSHClient from paramiko import py3compat from sshaolin import common from sshaolin.models import CommandResponse # this is a hack to preimport dependencies imported in a thread during connect # which causes a deadlock. https://github.com/paramiko/paramiko/issues/104 py3compat.u("".encode()) # dirty hack 2.0 also issue 104 # Try / Catch to prevent users using paramiko<2.0.0 from raising an ImportError try: from cryptography.hazmat.backends import default_backend from cryptography.utils import int_from_bytes int_from_bytes(b"a", "big") default_backend() except ImportError: pass class CommandOperationTimeOut(socket.timeout): pass class ProxyTypes(object): SOCKS5 = 2 SOCKS4 = 1 def read_pipe(pipe, fp_out):
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 random_serial_number(): return utils.int_from_bytes(os.urandom(20), "big") >> 1
def test_int_from_bytes_bytearray(): assert utils.int_from_bytes(bytearray(b"\x02\x10"), "big") == 528
def random_nat(n: int) -> int: """ Generate a random natural number L{n} bytes long. """ return utils.int_from_bytes(random_bytes(n), 'big', signed=False)