def verify_ed25519(pub_key: Ed25519PublicKey, sig_ptrs: SignaturePtrs) -> bool: c = b''.join(bytes(blk) for blk in sig_ptrs.signature_covered_part) try: pub_key.verify(bytes(sig_ptrs.signature_value_buf), c) return True except InvalidSignature: return False
def set_passwd(self, sign, xchg, password: bytes): """ Set or replace the password by encrypting the private keys and storing the results. :param sign: The signature key. :param xchg: The encryption key. :param password: The password for encrypting the keys. """ # Verify key if key has been set if self.sign_priv: try: Ed25519PublicKey.from_public_bytes(self.sign).verify( self.sign_sig, sign) Ed25519PublicKey.from_public_bytes(self.sign).verify( self.xchg_sig, xchg) except cryptography.exceptions.InvalidSignature as e: raise SignatureMismatch(self.xchg_sig) from e # Do the actual encryption session = _gen_login_key(password, self.identity) self.sign_iv = urandom(16) context = Cipher(algorithms.ChaCha20(session, self.sign_iv), None, default_backend()).encryptor() self.sign_priv = context.update(sign) + context.finalize() self.xchg_iv = urandom(16) context = Cipher(algorithms.ChaCha20(session, self.xchg_iv), None, default_backend()).encryptor( ) # Nonce reuse is considered bad practice self.xchg_priv = context.update(xchg) + context.finalize()
def validate_recipient_signature(self, cmd: PaymentCommand, public_key: Ed25519PublicKey) -> None: msg = cmd.travel_rule_metadata_signature_message(self.hrp) try: public_key.verify(bytes.fromhex(cmd.payment.recipient_signature), msg) except (ValueError, InvalidSignature) as e: raise command_error(ErrorCode.invalid_recipient_signature, str(e), "command.payment.recipient_signature") from e
def validate(self, descriptor): """ Validate our descriptor content matches its ed25519 signature. Supported descriptor types include... * :class:`~stem.descriptor.server_descriptor.RelayDescriptor` * :class:`~stem.descriptor.hidden_service.HiddenServiceDescriptorV3` :param stem.descriptor.__init__.Descriptor descriptor: descriptor to validate :raises: * **ValueError** if signing key or descriptor are invalid * **TypeError** if descriptor type is unsupported * **ImportError** if cryptography module with ed25519 support is unavailable """ import stem.descriptor.server_descriptor try: from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey from cryptography.exceptions import InvalidSignature except ImportError: raise ImportError('Certificate validation requires cryptography 2.6 or later') if isinstance(descriptor, stem.descriptor.server_descriptor.RelayDescriptor): signed_content = hashlib.sha256(Ed25519CertificateV1._signed_content(descriptor)).digest() signature = stem.util.str_tools._decode_b64(descriptor.ed25519_signature) # verify that we're created from this descriptor's signing key if descriptor.ed25519_master_key: signing_key = base64.b64decode(stem.util.str_tools._to_bytes(descriptor.ed25519_master_key) + b'=') else: signing_key = self.signing_key() if not signing_key: raise ValueError('Server descriptor missing an ed25519 signing key') try: key = Ed25519PublicKey.from_public_bytes(signing_key) key.verify(self.signature, base64.b64decode(stem.util.str_tools._to_bytes(self.to_base64()))[:-ED25519_SIGNATURE_LENGTH]) except InvalidSignature: raise ValueError('Ed25519KeyCertificate signing key is invalid (signature forged or corrupt)') elif isinstance(descriptor, stem.descriptor.hidden_service.HiddenServiceDescriptorV3): signed_content = Ed25519CertificateV1._signed_content(descriptor) signature = stem.util.str_tools._decode_b64(descriptor.signature) else: raise TypeError('Certificate validation only supported for server and hidden service descriptors, not %s' % type(descriptor).__name__) try: key = Ed25519PublicKey.from_public_bytes(self.key) key.verify(signature, signed_content) except InvalidSignature: raise ValueError('Descriptor Ed25519 certificate signature invalid (signature forged or corrupt)')
def test_ed25519_unsupported(backend): with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): Ed25519PublicKey.from_public_bytes(b"0" * 32) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): Ed25519PrivateKey.from_private_bytes(b"0" * 32) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM): Ed25519PrivateKey.generate()
def test_ed25519_unsupported(backend): with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): Ed25519PublicKey.from_public_bytes(b"0" * 32) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): Ed25519PrivateKey.from_private_bytes(b"0" * 32) with raises_unsupported_algorithm( _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): Ed25519PrivateKey.generate()
def pk_to_curve25519(ed: ed25519.Ed25519PublicKey) -> x25519.X25519PublicKey: raw = ed.public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw, ) # This is libsodium's crypto_sign_ed25519_pk_to_curve25519 translated into # the Pyton module ge25519. from ge25519 import ge25519, ge25519_p3 from fe25519 import fe25519 if ge25519.has_small_order(raw) != 0: raise RuntimeError("Doesn' thave small order") # frombytes in libsodium appears to be the same as # frombytes_negate_vartime; as ge25519 only implements the from_bytes # version, we have to do the root check manually. A = ge25519_p3.from_bytes(raw) if A.root_check: raise RuntimeError("Root check failed") if not A.is_on_main_subgroup(): raise RuntimeError("It's on the main subgroup") one_minus_y = fe25519.one() - A.Y x = A.Y + fe25519.one() x = x * one_minus_y.invert() return x25519.X25519PublicKey.from_public_bytes(bytes(x.to_bytes()))
def _validate_server_desc_signing_key(self, descriptor): from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey from cryptography.exceptions import InvalidSignature if descriptor.ed25519_master_key: signing_key = base64.b64decode( stem.util.str_tools._to_bytes(descriptor.ed25519_master_key) + b'=') else: signing_key = self.signing_key() if not signing_key: raise ValueError( 'Server descriptor missing an ed25519 signing key') try: key = Ed25519PublicKey.from_public_bytes(signing_key) key.verify( self.signature, base64.b64decode(stem.util.str_tools._to_bytes( self.encoded))[:-ED25519_SIGNATURE_LENGTH]) except InvalidSignature: raise ValueError( 'Ed25519KeyCertificate signing key is invalid (signature forged or corrupt)' )
def from_jwk(jwk): try: if isinstance(jwk, str): obj = json.loads(jwk) elif isinstance(jwk, dict): obj = jwk else: raise ValueError except ValueError: raise InvalidKeyError("Key is not valid JSON") if obj.get("kty") != "OKP": raise InvalidKeyError("Not an Octet Key Pair") curve = obj.get("crv") if curve != "Ed25519": raise InvalidKeyError(f"Invalid curve: {curve}") if "x" not in obj: raise InvalidKeyError('OKP should have "x" parameter') x = base64url_decode(obj.get("x")) try: if "d" not in obj: return Ed25519PublicKey.from_public_bytes(x) d = base64url_decode(obj.get("d")) return Ed25519PrivateKey.from_private_bytes(d) except ValueError as err: raise InvalidKeyError("Invalid key parameter") from err
def test_load_public_bytes(self, backend): public_key = Ed25519PrivateKey.generate().public_key() public_bytes = public_key.public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw) public_key2 = Ed25519PublicKey.from_public_bytes(public_bytes) assert public_bytes == public_key2.public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw)
def verify(self, to_be_verified: bytes, signature: bytes, alg: Optional[CoseAlgorithms] = None, curve: Optional[CoseEllipticCurves] = None) -> bool: """ Verifies the digital signature over 'to_be_verified'. The parameter 'alg' and 'curve' parameters are optional in case they are already provided by the key object self. :param to_be_verified: Data that was signed. :param signature: Signature to verify. :param alg: An optional algorithm parameter. :param curve: An optional curve :return: True when the signature is valid and False if the signature is invalid. """ self._check_key_conf(algorithm=alg, key_operation=KeyOps.VERIFY, curve=curve) if self.crv == CoseEllipticCurves.ED25519: vk = Ed25519PublicKey.from_public_bytes(self.x) elif self._crv == CoseEllipticCurves.ED448: vk = Ed448PublicKey.from_public_bytes(self.x) else: raise CoseIllegalCurve( f"Illegal curve for OKP singing: {self.crv}") try: vk.verify(signature, to_be_verified) return True except InvalidSignature: return False
def test_new_auth_key_from_public_key(): key_bytes = bytes.fromhex("447fc3be296803c2303951c7816624c7566730a5cc6860a4a1bd3c04731569f5") public_key = Ed25519PublicKey.from_public_bytes(key_bytes) auth_key = AuthKey.from_public_key(public_key) assert auth_key.hex() == "459c77a38803bd53f3adee52703810e3a74fd7c46952c497e75afb0a7932586d" assert auth_key.prefix().hex() == "459c77a38803bd53f3adee52703810e3" assert auth_key.account_address().to_hex() == "a74fd7c46952c497e75afb0a7932586d"
def cryptography_okp_public_key( credential_public_key: OKPCredentialPublicKey) -> OKPPublicKey: """Convert an `OKPCredentialPublicKey` into a cryptography `OKPPublicKey`. Args: credential_public_key (EC2CredentialPublicKey): The key to convert. Returns: A cryptography `EC2PublicKey`. Raises: UnimplementedError: If the conversion logic for the given type of CredentialPublicKey has not been implemented. PublicKeyConversionError: If the provided key could not be converted into a valid cryptography `EC2PublicKey`. """ try: if credential_public_key.crv.name == 'ED25519': return Ed25519PublicKey.from_public_bytes(credential_public_key.x) elif credential_public_key.crv.name == 'ED448': return Ed448PublicKey.from_public_bytes(credential_public_key.x) else: raise UnimplementedError( 'Unsupported cryptography OKP curve {}'.format( credential_public_key.crv.name)) except ValueError: raise PublicKeyConversionError('Invalid OKP public key')
def verify(public_key: Ed25519PublicKey, signature: bytes, data: bytes) -> bool: """ Verifies that the passed public key was used to create the signature for passed data. Args: public_key (Ed25519PublicKey): Public key to use for verification. signature (bytes): Signature to verify data (bytes): Signed data. Returns: bool: True if signature is correct. """ try: public_key.verify(signature, data) except: return False return True
def checkSignature(message, signature, public_key_bytes): public_key = Ed25519PublicKey.from_public_bytes(public_key_bytes) try: public_key.verify(signature, message) except InvalidSignature: return False finally: return True
def encode_public( self, public_key: ed25519.Ed25519PublicKey, f_pub: _FragList ) -> None: """Write Ed25519 public key""" raw_public_key = public_key.public_bytes( Encoding.Raw, PublicFormat.Raw ) f_pub.put_sshstr(raw_public_key)
def test_decode_example_jws(): example = "eyJhbGciOiJFZERTQSJ9.U2FtcGxlIHNpZ25lZCBwYXlsb2FkLg.dZvbycl2Jkl3H7NmQzL6P0_lDEW42s9FrZ8z-hXkLqYyxNq8yOlDjlP9wh3wyop5MU2sIOYvay-laBmpdW6OBQ" public_key = "bd47e3e7afb94debbd82e10ab7d410a885b589db49138628562ac2ec85726129" key = Ed25519PublicKey.from_public_bytes(bytes.fromhex(public_key)) headers, body = jws.decode(example.encode("utf-8"), key.verify) assert body == "Sample signed payload." assert headers == {"alg": "EdDSA"}
def test_load_public_bytes(self, backend): public_key = Ed25519PrivateKey.generate().public_key() public_bytes = public_key.public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw ) public_key2 = Ed25519PublicKey.from_public_bytes(public_bytes) assert public_bytes == public_key2.public_bytes( serialization.Encoding.Raw, serialization.PublicFormat.Raw )
def valid_signature_raw(sig, pub, text): public_key = Ed25519PublicKey.from_public_bytes( bytearray.fromhex(pub).decode()) try: public_key.verify(bytearray.fromhex( sig).decode(), text.encode('utf-8')) return True except: return False
def loadKey(self, data): self.private_key = Ed25519PrivateKey.from_private_bytes( bytes.fromhex(data['private_key'])) self.public_key_bytes = bytes.fromhex(data['public_key']) self.public_key = Ed25519PublicKey.from_public_bytes( self.public_key_bytes) self.nid = bytes.fromhex(data['myNID']) self.rsa_private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
def test_deserialize_example_jws(): example = "eyJhbGciOiJFZERTQSJ9.U2FtcGxlIHNpZ25lZCBwYXlsb2FkLg.dZvbycl2Jkl3H7NmQzL6P0_lDEW42s9FrZ8z-hXkLqYyxNq8yOlDjlP9wh3wyop5MU2sIOYvay-laBmpdW6OBQ" public_key = "bd47e3e7afb94debbd82e10ab7d410a885b589db49138628562ac2ec85726129" body, sig, msg = offchain.jws.deserialize_string(example.encode("utf-8")) assert body == "Sample signed payload." key = Ed25519PublicKey.from_public_bytes(bytes.fromhex(public_key)) key.verify(sig, msg)
def cryptography_okp_public_key( credential_public_key: OKPCredentialPublicKey) -> PublicKey: if credential_public_key.crv.name == 'ED25519': return Ed25519PublicKey.from_public_bytes(credential_public_key.x) elif credential_public_key.crv.name == 'ED448': return Ed448PublicKey.from_public_bytes(credential_public_key.x) else: raise UnimplementedError( 'Unsupported cryptography OKP curve {}'.format( credential_public_key.crv.name))
def load_peer(self, peer_pub_bytes, peer_sig_pub_bytes): self.peer_pub_bytes = peer_pub_bytes self.peer_pub = X25519PublicKey.from_public_bytes(self.peer_pub_bytes) self.peer_sig_pub_bytes = peer_sig_pub_bytes self.peer_sig_pub = Ed25519PublicKey.from_public_bytes( self.peer_sig_pub_bytes) if not hasattr(self.peer_pub, "curve"): self.peer_pub.curve = Link.CURVE
def pk_to_curve25519(ed: ed25519.Ed25519PublicKey) -> x25519.X25519PublicKey: raw = ed.public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw, ) ed_nacl = nacl.signing.VerifyKey(key=raw, ) x_nacl = ed_nacl.to_curve25519_public_key() return x25519.X25519PublicKey.from_public_bytes(x_nacl.encode())
def public_key_to_bytes(public_key: Ed25519PublicKey) -> bytes: """Returns the raw hex encoded bytes of a Ed25519PublicKey. Args: public_key (Ed25519PublicKey): Public key to encode. Returns: bytes: Byte encoding. """ return public_key.public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw)
def verifying_key_from_string(public_key_bytes): """ Load a verifying key from a string of bytes (which includes the PUBLIC_KEY_PREFIX) :returns: a public_key """ if not isinstance(public_key_bytes, six.binary_type): raise ValueError('public_key_bytes must be bytes') return Ed25519PublicKey.from_public_bytes( a2b(remove_prefix(public_key_bytes, PUBLIC_KEY_PREFIX)))
def loadKey(data): private_bytes = data['private'] private_key = Ed25519PrivateKey.from_private_bytes( bytes.fromhex(data['private'])) public_bytes = data['public'] public_key = Ed25519PublicKey.from_public_bytes( bytes.fromhex(data['public'])) nid = data['nid'] print('私钥', private_bytes) print('公钥', public_bytes) print('nid ', nid) return private_key, public_key, nid
def valid_sig(self): if (self.sender == 'coinbase'): return True else: # all nicknames end with .coof, if the sender ends with .coof then we need to get the pubkey from the db if (self.sender.endswith('.coof')): read = get(key=self.sender, collection_name='nicknames.db') if (read == None): return False else: public_key = Ed25519PublicKey.from_public_bytes( bytearray.fromhex(read).decode()) else: public_key = Ed25519PublicKey.from_public_bytes( bytearray.fromhex(self.sender).decode()) try: public_key.verify(bytearray.fromhex( self.signature).decode(), self.hash.encode('utf-8')) return True except: return False
def verify(cls, key: 'OKP', data: bytes, signature: bytes) -> bool: if key.crv.fullname == 'ED25519': vk = Ed25519PublicKey.from_public_bytes(key.x) elif key.crv.fullname == 'ED448': vk = Ed448PublicKey.from_public_bytes(key.x) else: raise CoseException(f"Illegal curve for OKP singing: {key.crv}") try: vk.verify(signature, data) return True except InvalidSignature: return False
def ed25519_public_key_from_string(string): """Create an ed25519 public key from ``string``, which is a seed. Args: string (str): the string to use as a seed. Returns: Ed25519PublicKey: the public key """ try: return Ed25519PublicKey.from_public_bytes(base64.b64decode(string)) except (UnsupportedAlgorithm, Base64Error) as exc: raise ScriptWorkerEd25519Error("Can't create Ed25519PublicKey: {}!".format(str(exc)))
def decoded_public_key_to_cryptography( public_key: Union[DecodedOKPPublicKey, DecodedEC2PublicKey, DecodedRSAPublicKey] ) -> Union[Ed25519PublicKey, EllipticCurvePublicKey, RSAPublicKey]: """Convert raw decoded public key parameters (crv, x, y, n, e, etc...) into public keys using primitives from the cryptography.io library """ if isinstance(public_key, DecodedEC2PublicKey): """ alg is -7 (ES256), where kty is 2 (with uncompressed points) and crv is 1 (P-256). https://www.w3.org/TR/webauthn-2/#sctn-public-key-easy """ x = int(codecs.encode(public_key.x, "hex"), 16) y = int(codecs.encode(public_key.y, "hex"), 16) curve = get_ec2_curve(public_key.crv) ecc_pub_key = EllipticCurvePublicNumbers(x, y, curve).public_key( default_backend()) return ecc_pub_key elif isinstance(public_key, DecodedRSAPublicKey): """ alg is -257 (RS256) https://www.w3.org/TR/webauthn-2/#sctn-public-key-easy """ e = int(codecs.encode(public_key.e, "hex"), 16) n = int(codecs.encode(public_key.n, "hex"), 16) rsa_pub_key = RSAPublicNumbers(e, n).public_key(default_backend()) return rsa_pub_key elif isinstance(public_key, DecodedOKPPublicKey): """ -8 (EdDSA), where crv is 6 (Ed25519). https://www.w3.org/TR/webauthn-2/#sctn-public-key-easy """ if (public_key.alg != COSEAlgorithmIdentifier.EDDSA or public_key.crv != COSECRV.ED25519): raise UnsupportedPublicKey( f"OKP public key with alg {public_key.alg} and crv {public_key.crv} is not supported" ) okp_pub_key = Ed25519PublicKey.from_public_bytes(public_key.x) return okp_pub_key else: raise UnsupportedPublicKey( f"Unrecognized decoded public key: {public_key}")
def validate(self, descriptor): """ Validate our descriptor content matches its ed25519 signature. Supported descriptor types include... * :class:`~stem.descriptor.server_descriptor.RelayDescriptor` * :class:`~stem.descriptor.hidden_service.HiddenServiceDescriptorV3` :param stem.descriptor.__init__.Descriptor descriptor: descriptor to validate :raises: * **ValueError** if signing key or descriptor are invalid * **TypeError** if descriptor type is unsupported * **ImportError** if cryptography module or ed25519 support unavailable """ if not stem.prereq.is_crypto_available(ed25519=True): raise ImportError( 'Certificate validation requires the cryptography module and ed25519 support' ) if isinstance(descriptor, stem.descriptor.server_descriptor.RelayDescriptor): signed_content = hashlib.sha256( Ed25519CertificateV1._signed_content(descriptor)).digest() signature = stem.util.str_tools._decode_b64( descriptor.ed25519_signature) self._validate_server_desc_signing_key(descriptor) elif isinstance( descriptor, stem.descriptor.hidden_service.HiddenServiceDescriptorV3): signed_content = Ed25519CertificateV1._signed_content(descriptor) signature = stem.util.str_tools._decode_b64(descriptor.signature) else: raise TypeError( 'Certificate validation only supported for server and hidden service descriptors, not %s' % type(descriptor).__name__) from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey from cryptography.exceptions import InvalidSignature try: key = Ed25519PublicKey.from_public_bytes(self.key) key.verify(signature, signed_content) except InvalidSignature: raise ValueError( 'Descriptor Ed25519 certificate signature invalid (signature forged or corrupt)' )
def ed25519_public_key_from_string(string): """Create an ed25519 public key from ``string``, which is a seed. Args: string (str): the string to use as a seed. Returns: Ed25519PublicKey: the public key """ try: return Ed25519PublicKey.from_public_bytes( base64.b64decode(string) ) except (UnsupportedAlgorithm, Base64Error) as exc: raise ScriptWorkerEd25519Error("Can't create Ed25519PublicKey: {}!".format(str(exc)))
def test_ed25519_signature(backend, wycheproof): # We want to fail if/when wycheproof adds more edwards curve tests # so we can add them as well. assert wycheproof.testgroup["key"]["curve"] == "edwards25519" key = Ed25519PublicKey.from_public_bytes( binascii.unhexlify(wycheproof.testgroup["key"]["pk"]) ) if wycheproof.valid or wycheproof.acceptable: key.verify( binascii.unhexlify(wycheproof.testcase["sig"]), binascii.unhexlify(wycheproof.testcase["msg"]), ) else: with pytest.raises(InvalidSignature): key.verify( binascii.unhexlify(wycheproof.testcase["sig"]), binascii.unhexlify(wycheproof.testcase["msg"]), )
def public_key_from_string(key_str): """Create an Ed25519PublicKey from a base64-encoded string.""" return Ed25519PublicKey.from_public_bytes( base64.b64decode(key_str) )
def test_invalid_type_public_bytes(self, backend): with pytest.raises(TypeError): Ed25519PublicKey.from_public_bytes(object())
def test_invalid_length_from_public_bytes(self, backend): with pytest.raises(ValueError): Ed25519PublicKey.from_public_bytes(b"a" * 31) with pytest.raises(ValueError): Ed25519PublicKey.from_public_bytes(b"a" * 33)