Exemplo n.º 1
0
def der_signature_to_compact(der_sig):
    '''Returns 64 bytes representing r and s as concatenated 32-byte big-endian numbers.'''
    cdata_sig = _der_signature_to_cdata(der_sig)
    compact_sig = ffi.new('unsigned char [64]')
    lib.secp256k1_ecdsa_signature_serialize_compact(CONTEXT, compact_sig,
                                                    cdata_sig)
    return bytes(ffi.buffer(compact_sig))
Exemplo n.º 2
0
def _cdata_signature_to_der(signature):
    '''Return a DER-serialized signature; bytes of length at most 72.'''
    size = ffi.new('size_t *', MAX_SIG_LENGTH)
    data = ffi.new(f'unsigned char [{MAX_SIG_LENGTH}]')
    result = lib.secp256k1_ecdsa_signature_serialize_der(CONTEXT, data, size, signature)
    # Failure should never happen - MAX_SIG_LENGTH bytes is always enough
    assert result
    return bytes(ffi.buffer(data, size[0]))
Exemplo n.º 3
0
    def to_bytes(self, *, compressed=None):
        '''Serialize a PublicKey to bytes.'''
        if (self._compressed if compressed is None else compressed):
            length, flag = 33, EC_COMPRESSED
        else:
            length, flag = 65, EC_UNCOMPRESSED
        result = ffi.new(f'unsigned char [{length}]')
        rlength = ffi.new('size_t *', length)

        lib.secp256k1_ec_pubkey_serialize(CONTEXT, result, rlength, self._public_key, flag)
        return bytes(ffi.buffer(result, length))
Exemplo n.º 4
0
def sign_recoverable(msg_hash, secret):
    '''Sign a message hash and return a 65-byte recoverable signature.  This is a 64-byte
    compact signature with a recovery ID byte appended; and from which the public key can
    be immediately recovered.
    '''
    rec_signature = ffi.new('secp256k1_ecdsa_recoverable_signature *')
    if not lib.secp256k1_ecdsa_sign_recoverable(
            CONTEXT, rec_signature, msg_hash, secret, ffi.NULL, ffi.NULL):
        raise ValueError('invalid private key')

    # Serialize its as a 65-byte compact recoverable signature
    output = ffi.new(f'unsigned char [{CDATA_SIG_LENGTH}]')
    recid = ffi.new('int *')

    lib.secp256k1_ecdsa_recoverable_signature_serialize_compact(
        CONTEXT, output, recid, rec_signature)

    # recid is 0, 1, 2 or 3.
    return bytes(ffi.buffer(output, CDATA_SIG_LENGTH)) + bytes([recid[0]])
Exemplo n.º 5
0
    def __init__(self, secret, compressed=True, coin=None):
        '''Construct a PrivateKey from 32 big-endian bytes.

        compressed is passed on to the PublicKey constructor to indicate whether the
        public key should return an compressed serialization.

        A private key exists independently of any coin.  However it is useful to have a
        default coin for certain methods, such as to_WIF().  A PrivateKey may be created
        with an implicit coin (e.g. if created from WIF), so in such cases we remember it.
        If there is no implicit coin and client code does specify one, Bitcoin is used.
        '''
        if isinstance(secret, bytes):
            if len(secret) != KEY_SIZE:
                raise ValueError('private key must be 32 bytes')
            if not lib.secp256k1_ec_seckey_verify(CONTEXT, secret):
                raise ValueError('private key out of range')
            self._secret = secret
        elif repr(secret).startswith("<cdata 'unsigned char[32]'"):
            self._secret = bytes(ffi.buffer(secret))
        else:
            raise TypeError('private key must be bytes')
        self._compressed = compressed
        self._coin = coin or Bitcoin