예제 #1
0
def ec_pubkey_tweak_add(ctx, pubkey, tweak):
    ''' Tweak a public key by adding tweak times the generator to it.
    Args:
        ctx     (secp256k1_context*):   pointer to a context object (cannot be
                                        NULL)
        pubkey  (secp256k1_pubkey*):    pointer to a public key object
        tweak   (bytes):                pointer to a 32-byte tweak
    Returns:
        (int, secp256k1_pubkey*):       (0 if the tweak was out of range
                                        (change of around 1 in 2^128 for
                                        uniformly random 32-byte arrays),
                                        or if the resulting public key
                                        would be invalid (only when the
                                        tweak is the complement of the
                                        corresponding private key). 1
                                        otherwise,
                                        a pointer to a secp256k1_pubkey
                                        containing tweaked public key)
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate public key
    utils.validate_public_key(pubkey)

    # Validate tweak
    utils.validate_tweak_ser(tweak)

    return (lib.secp256k1_ec_pubkey_tweak_add(ctx, pubkey, tweak), pubkey)
예제 #2
0
def ec_pubkey_create(ctx, seckey):
    '''Compute the public key for a secret key.
    Args:
        ctx     (secp256k1_context*):   a secp256k1 context object, initialized
                                        for signing (cannot be NULL)
        seckey  (bytes):                pointer to a 32-byte private key
                                        (cannot be NULL)
    Returns:
        (int, secp256k1_pubkey):        (1 if secret was valid, public key
                                        stores, 0 if secret was invalid, try
                                        again,
                                        pointer to the created public key
                                        (cannot be NULL))
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate secret key
    utils.validate_secret_key_ser(seckey)

    # Pointer to the created public key
    pubkey = ffi.new('secp256k1_pubkey *')

    # Compute the public key for a secret key
    return (lib.secp256k1_ec_pubkey_create(ctx, pubkey, seckey), pubkey)
예제 #3
0
def context_randomize(ctx, seed32):
    '''Updates the context randomization to protect against side-channel leakage.

    While secp256k1 code is written to be constant-time no matter what secret
    values are, it's possible that a future compiler may output code which
    isn't, and also that the CPU may not emit the same radio frequencies or
    draw the same amount power for all values.

    This function provides a seed which is combined into the blinding value:
    that blinding value is added before each multiplication (and removed
    afterwards) so that it does not affect function results, but shields
    against attacks which rely on any input-dependent behaviour.

    You should call this after secp256k1_context_create or
    secp256k1_context_clone, and may call this repeatedly afterwards.

    Args:
        ctx     (secp256k1_context*):   pointer to a context object (cannot be
                                        NULL)
        seed32  (bytes):                pointer to a 32-byte random seed (NULL
                                        resets to initial state)
    Returns:
        (int):                          1 if randomization successfully updated
                                        0 if error
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate seed32
    utils.validate_bytes_type(seed32, [32],
                              'Invalid seed32. Must be 32-bytes.')

    return lib.secp256k1_context_randomize(ctx, seed32)
예제 #4
0
def ec_pubkey_tweak_mul(ctx, pubkey, tweak):
    '''Tweak a public key by multiplying it by a tweak value.
    Args:
        ctx     (secp256k1_context*):   pointer to a context object
                                        initialized for validation (cannot be
                                        NULL)
        pubkey  (secp2561_pubkey*):     pointer to a public key object
        tweak   (bytes):                pointer to a 32-byte tweak
    Returns:
        (int, secp256k1_pubkey*):       (0 if the tweak was out of range
                                        (chance of around 1 in 2^128 for
                                        uniformly random 32-byte arrays, or
                                        equal to zero. 1 otherwise,
                                        pointer to a public key object)
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate public key
    utils.validate_public_key(pubkey)

    # Validate tweak
    utils.validate_tweak_ser(tweak)

    return (lib.secp256k1_ec_pubkey_tweak_mul(ctx, pubkey, tweak), pubkey)
예제 #5
0
def ec_pubkey_combine(ctx, pubkeys):
    '''Add a number of public keys together.
    Args:
        ctx	(secp256k1_context*):   pointer to a context object
        pubkeys	(list):			list of pubkeys to add together
    Returns:
        (int, secp256k1_pubkey*):   	(1: the sum of the public keys is valid
                                        0: the sum of the public keys is not
                                        valid,
                                        pointer to a public key object for
                                        placing the resulting public key
                                        (cannot be NULL))
    '''
    # Validate context
    utils.validate_context(ctx)

    # Number of public keys to add together
    n = len(pubkeys)

    # Pointer to array of pointers to public keys (cannot be null)
    ins = ffi.new('secp256k1_pubkey[]', n)
    ins = ffi.new('secp256k1_pubkey*[]',
                  [pk.as_cffi_pointer() for pk in pubkeys])

    # Pointer to a public key object for placing the resulting public key
    out = ffi.new('secp256k1_pubkey *')

    return (lib.secp256k1_ec_pubkey_combine(ctx, out, ins, n), out)
예제 #6
0
def ecdsa_signature_parse_der(ctx, ser_sig):
    '''Parse a DER ECDSA signature.

    This function will accept any valid DER encoded signature, even if the
    encoded numbers are out of range.

    After the call, sig will always be initialized. If parsing failed or the
    encoded numbers are out of range, signature validation with it is
    guaranteed to fail for every message and public key.

    Args:
        ctx     (secp256k1_context*):       a secp256k1 context object
        ser_sig   (bytes):                    a pointer to the signature to be
                                            parsed
    Returns:
        (int, secp256k1_ecdsa_signature*):  (1 when the signature could be
                                            parsed, 0 otherwise,
                                            a pointer to a signature object)
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate signature
    utils.validate_signature_ser(ser_sig)

    # Length of the array pointed to be input
    inputlen = len(ser_sig)

    # Pointer to a signature object
    sig = ffi.new('secp256k1_ecdsa_signature *')

    # Parse a DER ECDSA signature
    return (lib.secp256k1_ecdsa_signature_parse_der(ctx, sig, ser_sig,
                                                    inputlen), sig)
예제 #7
0
def ecdsa_signature_parse_compact(ctx, input64):
    '''Parse an ECDSA signature in compact (64 bytes) format.

    The signature must consist of a 32-byte big endian R value, followed by a
    32-byte big endian S value. If R or S fall outside of [0..order-1], the
    encoding is invalid. R and S with value 0 are allowed in the encoding.

    After the call, sig will always be initialized. If parsing failed or R or
    S are zero, the resulting sig value is guaranteed to fail validation for
    any message and public key.

    Args:
        ctx     (secp256k1_context*):       a secp256k1 context object
        input64 (bytes):                    a pointer to the 64-byte array to
                                            parse
    Returns:
        (int, secp256k1_ecdsa_signature*):  (1 when the signature could be
                                            parsed, 0 otherwise,
                                            a pointer to a signature object)
    '''
    # Validate context
    utils.validate_context(ctx)

    # Pointer to a signature object
    sig = ffi.new('secp256k1_ecdsa_signature *')

    # Parse an ECDSA signature in compact (64 bytes) format
    return (lib.secp256k1_ecdsa_signature_parse_compact(ctx, sig,
                                                        input64), sig)
예제 #8
0
def ec_pubkey_parse(ctx, ser_pub):
    '''Parse a variable-length public key into the pubkey object.
    This function supports parsing compressed (33 bytes, header byte 0x02 or
    0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes,
    header byte 0x06 or 0x07) format public keys.
    Args:
        ctx     (secp256k1_context*):   secp256k1 context object
        ser_pub   (bytes):                pointer to a serialized public key
    Returns:
        (int, secp256k1_pubkey*):       (1 if the public key was fully
                                        valid. 0 if the public key could
                                        not be parsed or is invalid,
                                        pointer to a secp256k1_pubkey
                                        containing an initialized public
                                        key)
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate input
    utils.validate_public_key_ser(ser_pub)

    # Length of the array pointed to by input
    inputlen = len(ser_pub)

    # Pointer to a pubkey object. If 1 is returned, it is set to a parsed
    # version of input. If not, its value is undefined.
    pubkey = ffi.new('secp256k1_pubkey *')

    return (lib.secp256k1_ec_pubkey_parse(ctx, pubkey, ser_pub,
                                          inputlen), pubkey)
예제 #9
0
def context_destroy(ctx):
    '''Destroy a secp256k1 context object.
    This context pointer may not be used afterwards.
    Args:
        ctx     (secp256k1_context*):   an existing conect to destroy (cannot
                                        be NULL)
    '''
    # Validate context
    utils.validate_context(ctx)

    # Destroy context
    lib.secp256k1_context_destroy(ctx)
예제 #10
0
def context_clone(ctx):
    '''Copies a secp256k1 context object.
    Args:
        ctx     (secp256k1_context*):   an existing context to copy (cannot be
                                        NULL)
    Returns:
        ctx     (secp256k1_context*):   a newly created context object
    '''
    # Validate context
    utils.validate_context(ctx)

    # Clone context
    return lib.secp256k1_context_clone(ctx)
예제 #11
0
def ec_pubkey_serialize(ctx, pubkey, flags):
    '''Serialize a pubkey object into a serialized byte sequence.
    Args:
        ctx     (secp256k1_context*):       a secp256k1 context object
        pubkey  (secp256k1_pubkey*):        a pointer to a secp256k1_pubkey
                                            containing an initialized public
                                            key
        flags   (int):                      SECP256K1_EC_COMPRESSED if
                                            serialization should be in
                                            compressed format, otherwise
                                            SECP256K1_EC_UNCOMPRESSED
    Returns:
        (int, ctype 'char[33]', size_t*):   (1,
                                            a pointer to a 65-byte (if
                                            compressed==0) or 33-byte (if
                                            compressed==1) byte array to place
                                            the serialized key in,
                                            Pointer to an integer which is
                                            initially set to the size of the
                                            output, and is overwritten with the
                                            written size)
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate public key
    utils.validate_public_key(pubkey)

    # Validate flags
    if flags == lib.SECP256K1_EC_COMPRESSED:
        publen = 33
    elif flags == lib.SECP256K1_EC_UNCOMPRESSED:
        publen = 65
    else:
        raise ValueError('Invalid serialized compression format flag.')

    # Pointer to a 33- or 65-byte array to place the serialized key in
    output = ffi.new('char[]', publen)

    # Pointer to an integer which is initially set to the size of the output,
    # and is overwritten with the written size
    outputlen = ffi.new('size_t *', publen)
    output_length = int(ffi.cast('uint32_t', outputlen[0]))

    return (lib.secp256k1_ec_pubkey_serialize(ctx, output, outputlen, pubkey,
                                              flags), output[0:output_length],
            outputlen)
예제 #12
0
def ecdsa_sign(ctx, msg32, seckey, noncefp=ffi.NULL, ndata=ffi.NULL):
    '''Create an ECDSA signature.
    The created signature is always in lower-S form. See
    secp256k1_ecdsa_signature_normalize for more details.
    Args:
        ctx     (secp256k1_context*):       a secp256k1 context object,
                                            initialized for signing
        msg32   (bytes):                    the 32-byte message hash being
                                            signed (cannot be NULL)
        seckey  (bytes):                    pointer to a 32-byte secret key
                                            (cannot be NULL)
        noncefp (secp256k1_nonce_function): pointer to a nonce generation
                                            function. If NULL,
                                            secp256k1_nonce_function_default
                                            is used
        ndata   (void*):                    pointer to arbitrary data used by
                                            the nonce generation function (can
                                            be NULL)
    Returns:
        (int, secp256k1_ecdsa_signature*):  (1: signature created, 0: the nonce
                                            generation function failed, or the
                                            private key was invalid,
                                            pointer to an array where the
                                            signature will be placed (cannot be
                                            NULL))
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate msg32
    utils.validate_msg32_ser(msg32)

    # Validate secret key
    utils.validate_secret_key_ser(seckey)

    # Validate noncefp
    utils.validate_noncefp(noncefp)

    # Validate ndata
    utils.validate_ndata(ndata)

    sig = ffi.new('secp256k1_ecdsa_signature *')

    return (lib.secp256k1_ecdsa_sign(ctx, sig, msg32, seckey, noncefp,
                                     ndata), sig)
예제 #13
0
def ec_seckey_verify(ctx, seckey):
    '''Verify an ECDSA secret key.
    Args:
        ctx     (secp256k1_context*):   a secp256k1 context object (cannot be
                                        NULL)
        seckey  (bytes):                pointer to a 32-byte secret key (cannot
                                        NULL)
    Returns:
        (int):                          1 if secret key is valid, 0 if secret
                                        key is invalid
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate secret key
    utils.validate_secret_key_ser(seckey)

    return lib.secp256k1_ec_seckey_verify(ctx, seckey)
예제 #14
0
def ec_pubkey_negate(ctx, pubkey):
    '''Negates a public key in place.
    Args:
        ctx     (secp256k1_context*):   a secp256k1 context object
        pubkey  (secp256k1_pubkey*):    pointer to the public key to be negated
                                        (cannot be NULL)
    Returns:
        (int, secp256k1_pubkey*):       (1 always,
                                        pointer to the public key to be negated
                                        (cannot be NULL))
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate public key
    utils.validate_public_key(pubkey)

    return (lib.secp256k1_ec_pubkey_negate(ctx, pubkey), pubkey)
예제 #15
0
def ec_privkey_negate(ctx, seckey):
    '''Negates a private key in place.
    Args:
        ctx     (secp256k1_context*):   a secp256k1 context object
        seckey  (bytes):                pointer to a 32-byte private key to be
                                        negated (cannot be NULL)
    Returns:
        (int, bytes):                   (1 always,
                                        pointer to the 32-byte private key to
                                        be negated (cannot be NULL))
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate secret key
    utils.validate_secret_key_ser(seckey)

    # Negate a private key in place
    return (lib.secp256k1_ec_privkey_negate(ctx, seckey), seckey)
예제 #16
0
def ecdsa_signature_serialize_compact(ctx, sig):
    '''Serialize an ECDSA signature in compact (64 byte) format.
    See secp256k1_ecdsa_signature_parse_compact for details about the encoding.
    Args:
        ctx (secp256k1_context*):           a secp256k1 context object
        sig (secp256k1_ecdsa_signature*):   a pointer to an initialized
                                            signature object
    Returns:
        (int, unsigned char):               (1,
                                            a pointer to a 64-byte array to
                                            store the compact serialization)
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate signature
    utils.validate_signature(sig)

    # Pointer to a 64-byte array to store the compact serialization
    output64 = ffi.new('unsigned char[]', 64)

    return (lib.secp256k1_ecdsa_signature_serialize_compact(
        ctx, output64, sig), output64)
예제 #17
0
def ecdsa_signature_serialize_der(ctx, sig, outputlen=74):
    '''Serialize an ECDSA signature in DER format.
    Args:
        ctx         (secp256k1_context*):           a secp256k1 context object
        sig         (secp256k1_ecdsa_signature*):   a pointer to an initialized
                                                    signature object
        outputlen   (int):                          pointer to a length of
                                                    output
    Returns:
        (int, unsigned char[], size_t*):            (1 if enough space was
                                                    available to serialize, 0
                                                    otherwise, a pointer to an
                                                    array to store the DER
                                                    serialization, a pointer to
                                                    a length of the
                                                    serialization (even if 0
                                                    was returned))
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate signature
    utils.validate_signature(sig)

    # Pointer to an array to store the DER serialization
    output = ffi.new('unsigned char[]', outputlen)

    # Pointer to a length integer
    outputlen = ffi.new('size_t *', outputlen)

    res = lib.secp256k1_ecdsa_signature_serialize_der(ctx, output, outputlen,
                                                      sig)

    output_length = int(ffi.cast('uint32_t', outputlen[0]))

    # Serialize an ECDSA signature in DER format
    return (res, output[0:output_length], outputlen)
예제 #18
0
def ecdsa_verify(ctx, sig, msg32, pubkey):
    '''Verify an ECDSA signature.
    To avoid accepting malleable signatures, only ECDSA signatures in lower-S
    form are accepted.
    If you need to accept ECDSA signatures from sources that do not obey this
    rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to
    validation, but be aware that doing so results in malleable signatures.
    For details, see the comments for that function.
    Args:
        ctx     (secp256k1_context*):           a secp256k1 context object,
                                                initialized for verification
        sig     (secp256k1_ecdsa_signature*):   the signature being verified
                                                (cannot be NULL)
        msg32   (bytes):                        the 32-byte message hash being
                                                verified (cannot be NULL)
        pubkey  (secp256k1_pubkey*):            pointer to an initialized
                                                public key to verify with
                                                (cannot be NULL)
    Returns:
                (int):                          1: correct signature
                                                0: incorrect or unparseable
                                                signature
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate pubkey
    utils.validate_public_key(pubkey)

    # Validate sig
    utils.validate_signature(sig)

    # Validate msg32
    utils.validate_msg32_ser(msg32)

    return lib.secp256k1_ecdsa_verify(ctx, sig, msg32, pubkey)
예제 #19
0
def ec_privkey_tweak_mul(ctx, seckey, tweak):
    '''Tweak a private key by multiplying it by a tweak.
    Args:
        ctx     (secp256k1_context*):   pointer to a context object (cannot be
                                        NULL)
        seckey  (bytes):                pointer to a 32-byte private key
        tweak   (bytes):                pointer to a 32-byte tweak
    Returns:
        (int, seckey):                  (0 if the tweak was out of range
                                        (chance of around 1 in 2^128 for
                                        uniformly random 32-byte arrays, or
                                        equal to zero. 1 otherwise,
                                        pointer to a 32-byte private key)
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate secret key
    utils.validate_secret_key_ser(seckey)

    # Validate tweak
    utils.validate_tweak_ser(tweak)

    return (lib.secp256k1_ec_privkey_tweak_mul(ctx, seckey, tweak), seckey)
예제 #20
0
def ecdsa_signature_normalize(ctx, sigout, sigin):
    '''Convert a signature to a normalized lower-S form.

    With ECDSA a third-party can forge a second distinct signature of the same
    message, given a single initial signature, but without knowing the key.
    This is done by negating the S value modulo the order of the curve,
    'flipping' the sign of the random point R which is not included in the
    signature.

    Forgery of the same message isn't universally problematic, but in systems
    where message malleability or uniqueness of signatures is important this
    can cause issues. This forgery can be blocked by all verifiers forcing
    signers to use a normalized form.

    The lower-S form reduces the size of signatures slightly on average when
    variable length encodings (such as DER) are used and is cheap to verify,
    making it a good choice. Security of always using lower-S is assured
    because anyone can trivially modify a signature after the fact to enforce
    this property anyway.

    The lower S value is always between 0x1 and
    0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
    inclusive.

    No other forms of ECDSA malleability are known and none seem likely, but
    there is no formal proof that ECDSA, even with this additional restriction,
    is free of other malleability. Commonly used serialization schemes will
    also accept various non-unique encodings, so care should be taken when this
    property is required for an application.

    The secp256k1_ecdsa_sign function will by default create signatures in the
    lower-S form, and secp256k1_ecdsa_verify will not accept others. In case
    signatures come from a system that cannot enforce this property,
    secp256k1_ecdsa_signature_normalize must be called before verification.

    Args:
        ctx     (secp256k1_context*):           a secp256k1 context object
        sigin   (secp256k1_ecdsa_signature*):   a pointer to a signature to
                                                check/normalize (cannot be
                                                NULL, can be identical to
                                                sigout)
    Returns:
        (int, secp256k1_ecdsa_signature*):      (1 if sigin was not normalized,
                                                0 if it already was,
                                                a pointer to a signature to
                                                fill with the normalized form,
                                                or copy if the input was
                                                already normalized. (can be
                                                NULL if you're only interested
                                                in whether the input was
                                                already normalized).
    '''
    # Validate context
    utils.validate_context(ctx)

    # Validate sig
    utils.validate_signature(sigin)

    # Pointer to a signature to fill witht he normalized form, or copy if the
    # input was already normalized
    sigout = ffi.new('secp256k1_ecdsa_signature *')

    return (lib.secp256k1_ecdsa_signature_normalize(ctx, sigout,
                                                    sigin), sigout)