Ejemplo n.º 1
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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
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)
Ejemplo n.º 4
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)