def test_derive_private_key_success(backend): curve = ec.SECP256K1() _skip_curve_unsupported(backend, curve) private_numbers = ec.generate_private_key(curve, backend).private_numbers() derived_key = ec.derive_private_key( private_numbers.private_value, curve, backend ) assert private_numbers == derived_key.private_numbers()
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 test_for_curve(self): self.assertEqual(ALGORITHM.for_curve(ec.SECP224R1()), ALGORITHM.EC_P224) self.assertEqual(ALGORITHM.for_curve(ec.SECP256R1()), ALGORITHM.EC_P256) self.assertEqual(ALGORITHM.for_curve(ec.SECP384R1()), ALGORITHM.EC_P384) self.assertEqual(ALGORITHM.for_curve(ec.SECP521R1()), ALGORITHM.EC_P521) self.assertEqual(ALGORITHM.for_curve(ec.SECP256K1()), ALGORITHM.EC_K256) self.assertEqual(ALGORITHM.for_curve(BRAINPOOLP256R1()), ALGORITHM.EC_BP256) self.assertEqual(ALGORITHM.for_curve(BRAINPOOLP384R1()), ALGORITHM.EC_BP384) self.assertEqual(ALGORITHM.for_curve(BRAINPOOLP512R1()), ALGORITHM.EC_BP512)
def test_derive_private_key_errors(backend): curve = ec.SECP256K1() _skip_curve_unsupported(backend, curve) with pytest.raises(TypeError): ec.derive_private_key("one", curve, backend) # type: ignore[arg-type] with pytest.raises(TypeError): ec.derive_private_key(10, "five", backend) # type: ignore[arg-type] with pytest.raises(ValueError): ec.derive_private_key(-7, curve, backend)
def create(cls, password: Optional[bytes]) -> 'KeyPair': """ :raises WalletLocked: wallet password was not provided """ if not password: raise WalletLocked new_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) private_key_bytes = get_private_key_bytes(new_key, encryption_algorithm=serialization.BestAvailableEncryption(password)) address = get_address_b58_from_public_key(new_key.public_key()) return cls(private_key_bytes=private_key_bytes, address=address, used=False)
def sign_transaction(self, private_value): private_key_obj = ec.derive_private_key(private_value, ec.SECP256K1(), default_backend()) pub_key = private_key_obj.public_key().public_bytes( Encoding.DER, PublicFormat.SubjectPublicKeyInfo).hex() if pub_key != self.sender: raise Exception('You cannot sign transactions for other wallets') data = self.get_data_bytes() self.signature = private_key_obj.sign(data, ec.ECDSA(hashes.SHA256())) return self.signature
def generate_keys(self): private_key_obj = ec.derive_private_key(self.private_value, ec.SECP256K1(), default_backend()) public_key_obj = private_key_obj.public_key() # private key hex string self.private_key = private_key_obj.private_bytes( Encoding.DER, PrivateFormat.PKCS8, NoEncryption()).hex() # public key hex string self.public_key = public_key_obj.public_bytes( Encoding.DER, PublicFormat.SubjectPublicKeyInfo).hex()
def test_ecc_key(self): """ ECC 키쌍을 생성하여 인증서 생성, ECDSA 서명/검증 테스트 """ logging.debug("----- ECDSA Test Start -----") # 키쌍 생성 pri_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) pub_key = pri_key.public_key() pri_der = pri_key.private_bytes( encoding=serialization.Encoding.DER, format=serialization.PrivateFormat.PKCS8, # encryption_algorithm=serialization.NoEncryption() encryption_algorithm=serialization.BestAvailableEncryption( password=b'qwer1234')) pub_der = pub_key.public_bytes( encoding=serialization.Encoding.DER, format=serialization.PublicFormat.SubjectPublicKeyInfo) pri_b64 = base64.b64encode(pri_der, altchars=None) pub_b64 = base64.b64encode(pub_der, altchars=None) logging.debug("Private Key : \n%s", pri_b64) logging.debug("Public Key : \n%s", pub_b64) # 인증서 생성 cert = self._generate_cert(pub_key=pub_key, issuer_key=pri_key, subject_name="test") cert_key = cert.public_key() # ECDSA 서명 생성 및 검증 테스트 data = b"test" signature = self._generate_sign(pri_key=pri_key, data=data) sign_b64 = base64.b64encode(signature, altchars=None) logging.debug("Sign : %s", sign_b64) validation_result = self._verify_signature(pub_key=cert_key, data=data, signature=signature) logging.debug("Verify : %s", validation_result) self.assertEqual(validation_result, True) # ECDSA 서명을 생성하는 다른 방법 signature = pri_key.sign(data, ec.ECDSA(hashes.SHA256())) validation_result = self._verify_signature(pub_key=cert_key, data=data, signature=signature) logging.debug("----- ECDSA Test End -----\n") self.assertTrue(validation_result)
def test_derive_private_key_errors(backend): curve = ec.SECP256K1() _skip_curve_unsupported(backend, curve) with pytest.raises(TypeError): ec.derive_private_key('one', curve, backend) with pytest.raises(TypeError): ec.derive_private_key(10, 'five', backend) with pytest.raises(ValueError): ec.derive_private_key(-7, curve, backend)
def generate_ca_cert(self, cn, ou, o, expire_period=None, password=None): """CA 인증서 생성 Peer 인증서 발급 전용 인증서(ECC Key) :param cn: 주체 CommonName :param ou: 주체 OrganizationalUnitName :param o: 주체 OrganizationName :param expire_period: 인증서 유효기간(year) :param password: 개인키 암호화 비밀번호(8자리 이상) """ sign_pri_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) sign_pub_key = sign_pri_key.public_key() subject_name = x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, cn), x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, ou), x509.NameAttribute(NameOID.ORGANIZATION_NAME, o), x509.NameAttribute(NameOID.COUNTRY_NAME, "kr") ]) serial_number = self.__LAST_CA_INDEX + 1 key_usage = x509.KeyUsage(digital_signature=True, content_commitment=False, key_encipherment=True, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=False, encipher_only=False, decipher_only=False) if expire_period is None: expire_period = self.__ca_expired new_cert = self.__generate_cert(pub_key=sign_pub_key, subject_name=subject_name, issuer_name=subject_name, serial_number=serial_number, expire_period=expire_period, key_usage=key_usage, issuer_priv=sign_pri_key) cert_pem = new_cert.public_bytes(encoding=serialization.Encoding.PEM) if password is None: pri_pem = sign_pri_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() ) else: pri_pem = sign_pri_key.private_bytes( encoding=serialization.Encoding.DER, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.BestAvailableEncryption(password=password) ) self.__save(self.__CA_PATH, cert_pem, pri_pem) self.__LAST_CA_INDEX += 1 self.__show_certificate(new_cert)
def test(): data = b'this is some data I"d like to sign' with open("/tmp/data", "wb") as fp: fp.write(data) private_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) signature = private_key.sign(data, ec.ECDSA(hashes.SHA256())).hex() public_key = private_key.public_key().public_bytes( serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint).hex() convert = Convert(public_key, signature, "/tmp/data") convert.to_openssl()
def _get_curve_by_name(self, name): if name == 'P-256': return ec.SECP256R1() elif name == 'P-384': return ec.SECP384R1() elif name == 'P-521': return ec.SECP521R1() elif name == 'secp256k1': return ec.SECP256K1() elif name in _OKP_CURVES_TABLE: return name else: raise InvalidJWKValue('Unknown Elliptic Curve Type')
def sk_to_pk(sk): # type: (int) -> bytes """Converts private keys to public keys. The input is an integer as returned by seed_to_sk. The output is an uncompressed secp256k1 public key, as a byte string, as described in SEC 1 v2.0 section 2.3.3. """ from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat import backends priv_key = ec.derive_private_key(sk, ec.SECP256K1(), backends.default_backend()) k = priv_key.public_key().public_numbers().encode_point() return k
def generate_private_key(key_type): """ Generates a new private key based on key_type. Valid key types: RSA2048, RSA4096', 'ECCPRIME192V1', 'ECCPRIME256V1', 'ECCSECP192R1', 'ECCSECP224R1', 'ECCSECP256R1', 'ECCSECP384R1', 'ECCSECP521R1', 'ECCSECP256K1', 'ECCSECT163K1', 'ECCSECT233K1', 'ECCSECT283K1', 'ECCSECT409K1', 'ECCSECT571K1', 'ECCSECT163R2', 'ECCSECT233R1', 'ECCSECT283R1', 'ECCSECT409R1', 'ECCSECT571R2' :param key_type: :return: """ _CURVE_TYPES = { "ECCPRIME192V1": ec.SECP192R1(), # duplicate "ECCPRIME256V1": ec.SECP256R1(), # duplicate "ECCSECP192R1": ec.SECP192R1(), # duplicate "ECCSECP224R1": ec.SECP224R1(), "ECCSECP256R1": ec.SECP256R1(), # duplicate "ECCSECP384R1": ec.SECP384R1(), "ECCSECP521R1": ec.SECP521R1(), "ECCSECP256K1": ec.SECP256K1(), "ECCSECT163K1": ec.SECT163K1(), "ECCSECT233K1": ec.SECT233K1(), "ECCSECT283K1": ec.SECT283K1(), "ECCSECT409K1": ec.SECT409K1(), "ECCSECT571K1": ec.SECT571K1(), "ECCSECT163R2": ec.SECT163R2(), "ECCSECT233R1": ec.SECT233R1(), "ECCSECT283R1": ec.SECT283R1(), "ECCSECT409R1": ec.SECT409R1(), "ECCSECT571R2": ec.SECT571R1(), } if key_type not in CERTIFICATE_KEY_TYPES: raise Exception( "Invalid key type: {key_type}. Supported key types: {choices}".format( key_type=key_type, choices=",".join(CERTIFICATE_KEY_TYPES) ) ) if "RSA" in key_type: key_size = int(key_type[3:]) return rsa.generate_private_key( public_exponent=65537, key_size=key_size, backend=default_backend() ) elif "ECC" in key_type: return ec.generate_private_key( _CURVE_TYPES[key_type], backend=default_backend() )
def verify_one_vector(vector): digest_algorithm = vector['digest_algorithm'] message = vector['message'] x = vector['x'] y = vector['y'] signature = encode_rfc6979_signature(vector['r'], vector['s']) numbers = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256K1()) key = numbers.public_key(default_backend()) verifier = key.verifier( signature, ec.ECDSA(CRYPTOGRAPHY_HASH_TYPES[digest_algorithm]())) verifier.update(message) return verifier.verify()
def is_signature_valid(signature, digest, public_key_bytes): signature = cdata_to_der(deserialize_compact(signature)) public_key = cPublicKey(public_key_bytes) is_valid = public_key.verify(signature, digest, None) if not is_valid: # try old way # ytsync signed claims don't seem to validate with coincurve try: pk = ec.EllipticCurvePublicKey.from_encoded_point( ec.SECP256K1(), public_key_bytes) pk.verify(signature, digest, ec.ECDSA(Prehashed(hashes.SHA256()))) return True except (ValueError, InvalidSignature): pass return is_valid
def encrypt(message, receiver_public_key): sender_private_key = ec.generate_private_key(ec.SECP256K1(), backend) shared_key = sender_private_key.exchange(ec.ECDH(), receiver_public_key) sender_public_key = sender_private_key.public_key() point = sender_public_key.public_numbers().encode_point() iv = '000000000000' xkdf = x963kdf.X963KDF(algorithm=hashes.SHA256(), length=32, sharedinfo='', backend=backend) key = xkdf.derive(shared_key) encryptor = Cipher(algorithms.AES(key), modes.GCM(iv), backend=backend).encryptor() ciphertext = encryptor.update(message) + encryptor.finalize() return point + encryptor.tag + ciphertext
def __new__(cls, private_key=None, public_key=None): if not public_key and not private_key: # generate keypair private_key = ec.generate_private_key(ec.SECP256K1(), backend=default_backend()) public_key = private_key.public_key() elif private_key: public_key = private_key.public_key() # address is SHA-256 of public key result = super().__new__( cls, BlcSha.sha256(public_key.public_numbers().encode_point())) result.private_key = private_key result.public_key = public_key return result
def verify_one_vector(vector): digest_algorithm = vector["digest_algorithm"] message = vector["message"] x = vector["x"] y = vector["y"] signature = encode_dss_signature(vector["r"], vector["s"]) numbers = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256K1()) key = numbers.public_key(default_backend()) verifier = key.verifier( signature, ec.ECDSA(CRYPTOGRAPHY_HASH_TYPES[digest_algorithm]())) verifier.update(message) verifier.verify()
def __init__(self, private_key=None, compressed=True): """ Takes in a private key/secret exponent. """ pk_i = None if private_key is None: pk_i = ec.generate_private_key( ec.SECP256K1(), default_backend()).private_numbers().private_value else: pk_i = keylib.key_formatting.encode_privkey(private_key, 'decimal') privkey_str = '{:064x}'.format(pk_i) assert len(privkey_str) == 64 self._ecdsa_private_key_string = privkey_str.decode('hex') self._compressed = compressed
def __init__(self, blockchain=None): self.blockchain = blockchain """ Initialize the private key, public key, starting balance and the sender's address. """ self.private_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) self.public_key = self.private_key.public_key( ) #obtain public key from private key #serialize the public key so as to easily convert the transaction class to a JSON self.public_key = self.serialize_public_key() self.address = str( uuid.uuid4() )[: 8] #first 8 characters is enough to get 3 trillion different results
def main(): from hathor.cli.util import create_parser from hathor.crypto.util import get_hash160, get_private_key_bytes, get_public_key_bytes_compressed parser = create_parser() parser.add_argument('filepath', help='Create a new private key in the given file') args = parser.parse_args() new_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) private_key_bytes = get_private_key_bytes(new_key) with open(args.filepath, 'w') as key_file: key_file.write(base64.b64encode(private_key_bytes).decode('utf-8')) print('key created!') public_key_bytes = get_public_key_bytes_compressed(new_key.public_key()) print('base64 pubkey hash:', base64.b64encode(get_hash160(public_key_bytes)).decode('utf-8'))
def test_trx_ecdh_key(self, app): # get ledger public key pack = app.apduMessage(0x02,0x00,0x00,f"05{app.getAccount(0)['path']}") data, status = app.exchange(pack) assert(data[0] == 65) pubKey = bytes(data[1:66]) # get pair key pack = app.apduMessage(0x0A,0x00,0x01,f"05{app.getAccount(0)['path']}04{app.getAccount(1)['publicKey'][2:]}") data, status = app.exchange(pack) assert(status == 0x9000) # check if pair key matchs pubKeyDH = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256K1(), pubKey) shared_key = app.getAccount(1)['dh'].exchange(ec.ECDH(), pubKeyDH) assert(shared_key.hex() == data[1:33].hex())
def generate_key(): ''' Generate a random public/private key ''' # default_backend() is in fact the only backend existing in cryptography library # see: https://cryptography.io/en/latest/hazmat/backends/ # so there is no risk of different default_backend() between users # We can choose here which elliptic curve is used # SECP384R1 is somewhat standard (supported in most browsers for example) # SECP256K1 is the curve used in Bitcoin network private_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) public_key = private_key.public_key() return public_key, private_key
def encrypt(message, receiver_public_key): sender_private_key = ec.generate_private_key(ec.SECP256K1(), backend) shared_key = sender_private_key.exchange(ec.ECDH(), receiver_public_key) sender_public_key = sender_private_key.public_key() point = sender_public_key.public_bytes( encoding=serialization.Encoding.X962, format=serialization.PublicFormat.UncompressedPoint) iv = '000000000000'.encode() xkdf = x963kdf.X963KDF(algorithm=hashes.SHA256(), length=32, sharedinfo=''.encode(), backend=backend) key = xkdf.derive(shared_key) encryptor = Cipher(algorithms.AES(key), modes.GCM(iv), backend=backend).encryptor() ciphertext = encryptor.update(message.encode()) + encryptor.finalize() return point + encryptor.tag + ciphertext
def test_serialize_point(self, vector, backend): curve = { b"SECP256R1": ec.SECP256R1(), b"SECP256K1": ec.SECP256K1(), }[vector["curve"]] point = binascii.unhexlify(vector["point"]) key = ec.EllipticCurvePublicKey.from_encoded_point(curve, point) key2 = ec.EllipticCurvePublicKey.from_encoded_point( curve, key.public_bytes(serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint)) assert key.public_bytes( serialization.Encoding.X962, serialization.PublicFormat.CompressedPoint) == point assert key2.public_bytes( serialization.Encoding.X962, serialization.PublicFormat.CompressedPoint) == point
def _point_multiply(priv, curve=ec.SECP256K1()): b = openssl.backend with b._tmp_bn_ctx() as ctx: curve_nid = b._elliptic_curve_to_nid(curve) ec_cdata = b._lib.EC_KEY_new_by_curve_name(curve_nid) ec_cdata = b._ffi.gc(ec_cdata, b._lib.EC_KEY_free) bn = b._int_to_bn(priv) b._lib.EC_KEY_set_private_key(ec_cdata, bn) pkey = b._lib.EC_KEY_new_by_curve_name(curve_nid) group = b._lib.EC_KEY_get0_group(pkey) pkey = b._lib.EC_POINT_new(group) pkey = b._ffi.gc(pkey, b._lib.EC_POINT_free) b._lib.EC_POINT_mul(group, pkey, bn, b._ffi.NULL, b._ffi.NULL, ctx) x = b._int_to_bn(0) y = b._int_to_bn(0) b._lib.EC_POINT_get_affine_coordinates_GFp(group, pkey, x, y, ctx) return b._bn_to_int(x), b._bn_to_int(y)
def is_valid(self): if self.sender == 'System': return True if self.signature is None or len(self.signature) == 0: print('ERROR: No signature found in the transaction') return False # generate a pub key obj from the sender info pub_key_obj = EllipticCurvePublicKey.from_encoded_point( ec.SECP256K1(), bytes.fromhex(self.sender)) data = self.get_data_bytes() try: pub_key_obj.verify(self.signature, data, ec.ECDSA(hashes.SHA256())) except cryptography.exceptions.InvalidSignature as exp: print(exp) return False return True
def test_pkcs12_format(self): """ PKCS12 형식으로 인증서/개인키 저장을 위한 코드 """ logging.debug("----- PKCS12 Test Start -----") # ECC 키 쌍 생성 pri_key = ec.generate_private_key(ec.SECP256K1(), default_backend()) pub_key = pri_key.public_key() logging.debug("Key_Type : %s", type(pri_key)) # 인증서 생성 cert = self._generate_cert(pub_key=pub_key, issuer_key=pri_key, subject_name="test") cert_pem = cert.public_bytes( encoding=serialization.Encoding.DER ) key_pem = pri_key.private_bytes( encoding=serialization.Encoding.DER, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() ) # 인증서/개인키를 OpenSSL Key로 변환 crypto = OpenSSL.crypto cert_ssl_key = crypto.load_certificate( type=crypto.FILETYPE_ASN1, buffer=cert_pem ) priv_ssl_key = crypto.load_privatekey( type=crypto.FILETYPE_ASN1, buffer=key_pem, passphrase=None ) logging.debug("Key_Type : %s", type(priv_ssl_key)) # 변환한 인증서개인키를 PKCS12형식으로 변환 p12 = OpenSSL.crypto.PKCS12() p12.set_privatekey(priv_ssl_key) p12.set_certificate(cert_ssl_key) pfx = p12.export() pfx_b64 = base64.b64encode(pfx, altchars=None) logging.debug("%s", pfx_b64)
def decrypt(message, receiver_private_key): point = message[0:65] tag = message[65:81] ciphertext = message[81:] sender_public_key = ec.EllipticCurvePublicKey.from_encoded_point( ec.SECP256K1(), point) shared_key = receiver_private_key.exchange(ec.ECDH(), sender_public_key) iv = '000000000000'.encode() xkdf = x963kdf.X963KDF(algorithm=hashes.SHA256(), length=32, sharedinfo=''.encode(), backend=backend) key = xkdf.derive(shared_key) decryptor = Cipher(algorithms.AES(key), modes.GCM(iv, tag), backend=backend).decryptor() message = decryptor.update(ciphertext) + decryptor.finalize() return message