示例#1
0
def test_verify(testerchain, signature_verifier):
    message = os.urandom(100)

    # Generate Umbral key
    umbral_privkey = UmbralPrivateKey.gen_key()
    umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False)

    # Sign message using SHA-256 hash
    cryptography_priv_key = umbral_privkey.to_cryptography_privkey()
    signature_der_bytes = cryptography_priv_key.sign(message, ec.ECDSA(hashes.SHA256()))
    signature = Signature.from_bytes(signature_der_bytes, der_encoded=True)

    # Prepare message hash
    hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
    hash_ctx.update(message)
    message_hash = hash_ctx.finalize()

    # Get recovery id (v) before using contract
    # First try v = 0
    recoverable_signature = bytes(signature) + bytes([0])
    pubkey_bytes = coincurve.PublicKey.from_signature_and_message(recoverable_signature, message_hash, hasher=None) \
        .format(compressed=False)
    if pubkey_bytes != umbral_pubkey_bytes:
        # Extracted public key is not ours, that means v = 1
        recoverable_signature = bytes(signature) + bytes([1])

    # Verify signature
    assert signature_verifier.functions.\
        verify(message, recoverable_signature, umbral_pubkey_bytes[1:], ALGORITHM_SHA256).call()

    # Verify signature using wrong key
    umbral_privkey = UmbralPrivateKey.gen_key()
    umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False)
    assert not signature_verifier.functions.\
        verify(message, recoverable_signature, umbral_pubkey_bytes[1:], ALGORITHM_SHA256).call()
示例#2
0
class NotAPrivateKey:
    params = default_params()

    fake_signature = Signature.from_bytes(
        b'@\xbfS&\x97\xb3\x9e\x9e\xd3\\j\x9f\x0e\x8fY\x0c\xbeS\x08d\x0b%s\xf6\x17\xe2\xb6\xcd\x95u\xaapON\xd9E\xb3\x10M\xe1\xf4u\x0bL\x99q\xd6\r\x8e_\xe5I\x1e\xe5\xa2\xcf\xe5\x8be_\x077Gz'
    )

    def public_key(self):
        return NotAPublicKey()

    def get_pubkey(self, *args, **kwargs):
        return self.public_key()

    def to_cryptography_privkey(self, *args, **kwargs):
        return self

    def sign(self, *args, **kwargs):
        return b'0D\x02 @\xbfS&\x97\xb3\x9e\x9e\xd3\\j\x9f\x0e\x8fY\x0c\xbeS\x08d\x0b%s\xf6\x17\xe2\xb6\xcd\x95u\xaap\x02 ON\xd9E\xb3\x10M\xe1\xf4u\x0bL\x99q\xd6\r\x8e_\xe5I\x1e\xe5\xa2\xcf\xe5\x8be_\x077Gz'

    @classmethod
    def stamp(cls, *args, **kwargs):
        return cls.fake_signature

    @classmethod
    def signature_bytes(cls, *args, **kwargs):
        return b'@\xbfS&\x97\xb3\x9e\x9e\xd3\\j\x9f\x0e\x8fY\x0c\xbeS\x08d\x0b%s\xf6\x17\xe2\xb6\xcd\x95u\xaapON\xd9E\xb3\x10M\xe1\xf4u\x0bL\x99q\xd6\r\x8e_\xe5I\x1e\xe5\xa2\xcf\xe5\x8be_\x077Gz'
示例#3
0
 def _deserialize(self, value, attr, data, **kwargs):
     if isinstance(value, bytes):
         return value
     try:
         return Signature.from_bytes(b64decode(value))
     except InvalidNativeDataTypes as e:
         raise InvalidInputData(f"Could not parse {self.name}: {e}")
示例#4
0
    def sign(self, message: bytes) -> bytes:
        """
        Signs a hashed message and returns a signature.

        :param message: The message to sign

        :return: Signature in bytes
        """
        signature_der_bytes = API.ecdsa_sign(message, self._privkey)
        return Signature.from_bytes(signature_der_bytes, der_encoded=True)
示例#5
0
def test_recover(testerchain, signature_verifier):
    message = os.urandom(100)

    # Prepare message hash
    hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
    hash_ctx.update(message)
    message_hash = hash_ctx.finalize()

    # Generate Umbral key and extract "address" from the public key
    umbral_privkey = UmbralPrivateKey.gen_key()
    umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False)
    signer_address = bytearray(testerchain.interface.w3.solidityKeccak(['bytes32'], [umbral_pubkey_bytes[1:]]))
    signer_address = to_normalized_address(signer_address[12:])

    # Sign message using SHA-256 hash (because only 32 bytes hash can be used in the `ecrecover` method)
    cryptography_priv_key = umbral_privkey.to_cryptography_privkey()
    signature_der_bytes = cryptography_priv_key.sign(message, ec.ECDSA(hashes.SHA256()))
    signature = Signature.from_bytes(signature_der_bytes, der_encoded=True)

    # Get recovery id (v) before using contract
    # If we don't have recovery id while signing than we should try to recover public key with different v
    # Only the correct v will match the correct public key
    # First try v = 0
    recoverable_signature = bytes(signature) + bytes([0])
    pubkey_bytes = coincurve.PublicKey.from_signature_and_message(recoverable_signature, message_hash, hasher=None)\
        .format(compressed=False)
    if pubkey_bytes != umbral_pubkey_bytes:
        # Extracted public key is not ours, that means v = 1
        recoverable_signature = bytes(signature) + bytes([1])
        pubkey_bytes = coincurve.PublicKey.from_signature_and_message(recoverable_signature, message_hash, hasher=None)\
            .format(compressed=False)

    # Check that recovery was ok
    assert umbral_pubkey_bytes == pubkey_bytes
    # Check recovery method in the contract
    assert signer_address == to_normalized_address(
        signature_verifier.functions.recover(message_hash, recoverable_signature).call())

    # Also numbers 27 and 28 can be used for v
    recoverable_signature = recoverable_signature[0:-1] + bytes([recoverable_signature[-1] + 27])
    assert signer_address == to_normalized_address(
        signature_verifier.functions.recover(message_hash, recoverable_signature).call())

    # Only number 0,1,27,28 are supported for v
    recoverable_signature = bytes(signature) + bytes([2])
    with pytest.raises((TransactionFailed, ValueError)):
        signature_verifier.functions.recover(message_hash, recoverable_signature).call()

    # Signature must include r, s and v
    recoverable_signature = bytes(signature)
    with pytest.raises((TransactionFailed, ValueError)):
        signature_verifier.functions.recover(message_hash, recoverable_signature).call()
示例#6
0
def test_sign_serialize_and_verify(execution_number):
    sk = SecretKey.random()
    pk = sk.public_key()
    signer = Signer(sk)

    message = b"peace at dawn" + str(execution_number).encode()

    signature = signer.sign(message)

    signature_bytes = bytes(signature)
    signature_restored = Signature.from_bytes(signature_bytes)

    assert signature_restored.verify(pk, message)
def sign_data(data, umbral_privkey):
    umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False)

    # Prepare hash of the data
    hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
    hash_ctx.update(data)
    data_hash = hash_ctx.finalize()

    # Sign data and calculate recoverable signature
    cryptography_priv_key = umbral_privkey.to_cryptography_privkey()
    signature_der_bytes = cryptography_priv_key.sign(data, ec.ECDSA(hashes.SHA256()))
    signature = Signature.from_bytes(signature_der_bytes, der_encoded=True)
    recoverable_signature = make_recoverable_signature(data_hash, signature, umbral_pubkey_bytes)
    return recoverable_signature
示例#8
0
def test_verification_fail():
    sk = SecretKey.random()
    pk = sk.public_key()
    signer = Signer(sk)

    message = b"peace at dawn"
    signature = signer.sign(message)

    # wrong message
    wrong_message = b"no peace at dawn"
    assert not signature.verify(pk, wrong_message)

    # bad signature
    signature_bytes = bytes(signature)
    signature_bytes = b'\x00' + signature_bytes[1:]
    signature_restored = Signature.from_bytes(signature_bytes)

    assert not signature_restored.verify(pk, message)
示例#9
0
def test_sign_and_verify(execution_number):
    privkey = UmbralPrivateKey.gen_key()
    pubkey = privkey.get_pubkey()
    signer = Signer(private_key=privkey)
    message = b"peace at dawn"
    signature = signer(message=message)

    # Basic signature verification
    assert signature.verify(message, pubkey)
    assert not signature.verify(b"another message", pubkey)
    another_pubkey = UmbralPrivateKey.gen_key().pubkey
    assert not signature.verify(message, another_pubkey)

    # Signature serialization
    sig_bytes = bytes(signature)
    assert len(sig_bytes) == Signature.expected_bytes_length()
    restored_signature = Signature.from_bytes(sig_bytes)
    assert restored_signature == signature
    assert restored_signature.verify(message, pubkey)
示例#10
0
    def sign_data(data, umbral_privkey):
        umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(
            is_compressed=False)

        # Prepare hash of the data
        hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
        hash_ctx.update(data)
        data_hash = hash_ctx.finalize()

        # Sign data and calculate recoverable signature
        cryptography_priv_key = umbral_privkey.to_cryptography_privkey()
        signature_der_bytes = cryptography_priv_key.sign(
            data, ec.ECDSA(hashes.SHA256()))
        signature = Signature.from_bytes(signature_der_bytes, der_encoded=True)
        recoverable_signature = bytes(signature) + bytes([0])
        pubkey_bytes = coincurve.PublicKey.from_signature_and_message(recoverable_signature, data_hash, hasher=None) \
            .format(compressed=False)
        if pubkey_bytes != umbral_pubkey_bytes:
            recoverable_signature = bytes(signature) + bytes([1])
        return recoverable_signature
示例#11
0
def test_signature_is_hashable():
    sk = SecretKey.random()
    pk = sk.public_key()
    signer = Signer(sk)

    message = b'peace at dawn'
    message2 = b'no peace at dawn'

    signature = signer.sign(message)
    signature2 = signer.sign(message2)

    assert hash(signature) != hash(signature2)

    signature_restored = Signature.from_bytes(bytes(signature))
    assert signature == signature_restored
    assert hash(signature) == hash(signature_restored)

    # Different hash, since signing involves some randomness
    signature3 = signer.sign(message)
    assert hash(signature) != hash(signature3)
示例#12
0
 def _validate(self, value):
     try:
         Signature.from_bytes(value)
     except InvalidNativeDataTypes as e:
         raise InvalidInputData(f"Could not parse {self.name}: {e}")