def test_ilp_keys(self, sk_ilp, vk_ilp): sk = SigningKey(sk_ilp['b58']) assert sk.encode(encoding='base64') == sk_ilp['b64'] assert binascii.hexlify( sk.encode(encoding='bytes')[:32]) == sk_ilp['hex'] vk = VerifyingKey(vk_ilp['b58']) assert vk.encode(encoding='base64') == vk_ilp['b64'] assert binascii.hexlify(vk.encode(encoding='bytes')) == vk_ilp['hex']
def test_to_bytes(self, sk_ilp, vk_ilp): sk = SigningKey(sk_ilp['b58']) assert sk.encode(encoding='base58') == sk_ilp['b58'] assert sk.encode(encoding='base64') == sk_ilp['b64'] vk = VerifyingKey(vk_ilp['b58']) assert vk.encode(encoding='base58') == vk_ilp['b58'] assert vk.encode(encoding='base64') == vk_ilp['b64']
def test_valid_condition_invalid_signature_ilp(self, vk_ilp, signature): vk = VerifyingKey( VerifyingKey.encode( base64_add_padding(vk_ilp[2]['b64']))) msg = base64.b64decode(signature['msg']) assert vk.verify(msg, signature['msg'], encoding='base64') is False assert vk.verify(msg, binascii.hexlify(base64.b64decode(signature['msg'])), encoding='hex') is False assert vk.verify(msg, base64.b64decode(signature['msg']), encoding=None) is False
def test_sign_verify(self, sk_ilp, vk_ilp): message = 'Hello World!' sk = SigningKey(sk_ilp['b58']) vk = VerifyingKey(vk_ilp['b58']) assert vk.verify(message, sk.sign(message)) is True assert vk.verify(message, sk.sign(message + 'dummy')) is False assert vk.verify(message + 'dummy', sk.sign(message)) is False vk = VerifyingKey( VerifyingKey.encode( base64_add_padding(vk_ilp[2]['b64']))) assert vk.verify(message, sk.sign(message)) is False
def test_generate_sign_verify(self, vk_ilp): sk_b58, vk_b58 = ed25519_generate_key_pair() sk = SigningKey(sk_b58) vk = VerifyingKey(vk_b58) message = 'Hello World!' assert vk.verify(message, sk.sign(message)) is True assert vk.verify(message, sk.sign(message + 'dummy')) is False assert vk.verify(message + 'dummy', sk.sign(message)) is False vk = VerifyingKey( VerifyingKey.encode( base64_add_padding(vk_ilp[2]['b64']))) assert vk.verify(message, sk.sign(message)) is False
def test_get_verifying_key(self, sk_ilp, vk_ilp): sk = SigningKey(sk_ilp['b58']) vk = VerifyingKey(vk_ilp['b58']) vk_from_sk = sk.get_verifying_key() assert vk.encode(encoding='bytes') == vk_from_sk.encode(encoding='bytes')
def test_verifying_key_decode(self, vk_ilp): vk = VerifyingKey(vk_ilp['b58']) public_value = vk.encode(encoding='base64') assert public_value == vk_ilp['b64']
def test_verifying_key_init(self, vk_ilp): vk = VerifyingKey(vk_ilp['b58']) assert vk.encode(encoding='base64') == vk_ilp['b64'] assert vk.encode(encoding='bytes') == vk_ilp['byt']
class Ed25519Fulfillment(Fulfillment): """ """ TYPE_ID = 4 FEATURE_BITMASK = 0x20 PUBKEY_LENGTH = 32 SIGNATURE_LENGTH = 64 FULFILLMENT_LENGTH = PUBKEY_LENGTH + SIGNATURE_LENGTH def __init__(self, public_key=None): """ ED25519: Ed25519 signature condition. This condition implements Ed25519 signatures. ED25519 is assigned the type ID 4. It relies only on the ED25519 feature suite which corresponds to a bitmask of 0x20. Args: public_key (VerifyingKey): Ed25519 publicKey """ if public_key and isinstance(public_key, (str, bytes)): public_key = VerifyingKey(public_key) if public_key and not isinstance(public_key, VerifyingKey): raise TypeError self.public_key = public_key self.signature = None def write_common_header(self, writer): """ Write static header fields. Some fields are common between the hash and the fulfillment payload. This method writes those field to anything implementing the Writer interface. It is used internally when generating the hash of the condition, when generating the fulfillment payload and when calculating the maximum fulfillment size. Args: writer (Writer, Hasher, Predictor): Target for outputting the header. """ writer.write_var_octet_string(self.public_key) def sign(self, message, private_key): """ Sign the message. This method will take the currently configured values for the message prefix and suffix and create a signature using the provided Ed25519 private key. Args: message (bytes): message to be signed private_key (:obj:`Ed25519SigningKey`) Ed25519 private key """ sk = private_key vk = sk.get_verifying_key() self.public_key = vk # This would be the Ed25519ph version (JavaScript ES7): # const message = crypto.createHash('sha512') # .update(Buffer.concat([this.messagePrefix, this.message])) # .digest() self.signature = sk.sign(message, encoding='bytes') def generate_hash(self): """ Generate the condition hash. Since the public key is the same size as the hash we'd be putting out here, we just return the public key. """ if not self.public_key: raise ValueError('Requires a public publicKey') return self.public_key.encode(encoding='bytes') def parse_payload(self, reader, *args): """ Parse the payload of an Ed25519 fulfillment. Read a fulfillment payload from a Reader and populate this object with that fulfillment. Args: reader (Reader): Source to read the fulfillment payload from. """ self.public_key = VerifyingKey( base58.b58encode( reader.read_octet_string(Ed25519Fulfillment.PUBKEY_LENGTH))) self.signature = reader.read_octet_string( Ed25519Fulfillment.SIGNATURE_LENGTH) def write_payload(self, writer): """ Generate the fulfillment payload. This writes the fulfillment payload to a Writer. FULFILLMENT_PAYLOAD = VARBYTES PUBLIC_KEY VARBYTES SIGNATURE Args: writer (Writer): Subject for writing the fulfillment payload. """ writer.write_octet_string(self.public_key.encode(encoding='bytes'), Ed25519Fulfillment.PUBKEY_LENGTH) writer.write_octet_string(self.signature, Ed25519Fulfillment.SIGNATURE_LENGTH) return writer def calculate_max_fulfillment_length(self): return Ed25519Fulfillment.FULFILLMENT_LENGTH def to_dict(self): """ Generate a dict of the fulfillment Returns: dict: representing the fulfillment """ return { 'type': 'fulfillment', 'type_id': self.TYPE_ID, 'bitmask': self.bitmask, 'public_key': self.public_key.encode(encoding='base58').decode(), 'signature': base58.b58encode(self.signature) if self.signature else None } def parse_dict(self, data): """ Generate fulfillment payload from a dict Args: data (dict): description of the fulfillment Returns: Fulfillment """ self.public_key = VerifyingKey(data['public_key']) self.signature = base58.b58decode( data['signature']) if data['signature'] else None def validate(self, message=None, **kwargs): """ Verify the signature of this Ed25519 fulfillment. The signature of this Ed25519 fulfillment is verified against the provided message and public key. Args: message (str): Message to validate against. Return: boolean: Whether this fulfillment is valid. """ if not (message and self.signature): return False return self.public_key.verify(message, self.signature, encoding='bytes')
def test_get_verifying_key(self, sk_ilp, vk_ilp): sk = SigningKey(sk_ilp['b58']) vk = VerifyingKey(vk_ilp['b58']) vk_from_sk = sk.get_verifying_key() assert vk.encode(encoding='bytes') == vk_from_sk.encode( encoding='bytes')
def test_generate_key_pair(self): sk_b58, vk_b58 = ed25519_generate_key_pair() assert len(base58.b58decode(sk_b58)) == 32 assert len(base58.b58decode(vk_b58)) == 32 assert SigningKey.encode(SigningKey.decode(sk_b58)) == sk_b58 assert VerifyingKey.encode(VerifyingKey.decode(vk_b58)) == vk_b58
def test_verifying_key_encode(self, vk_ilp): public_value_base58 = VerifyingKey.encode(base64_add_padding(vk_ilp['b64'])) assert public_value_base58 == vk_ilp['b58']