Author

Topic: Why does bitcoin manipulate the signature beyond ECDSA_do_sign? (Read 1167 times)

donator
Activity: 1218
Merit: 1079
Gerald Davis
There are two possible signatures for a given message and k value (nonce).  This is due to the s value being a value over a finite field.  The two values will have symmetry around a line drawn at half the domain order.  If you have one an s value you can compute its reciprocal.  One s value is always greater than half the domain order (hi) and the other is always less (lo).  Since the signature is public knowledge and relayed from peer to peer any peer can mutate the txn by replacing the s value with its reciprocal.

To reduce malleability, the bitcoin protocol now considers only lo s values (those smaller than half the order parameter) as canonical signatures.  Canonical signatures are relayed normally.  Non-canonical signatures are still valid for now however most newer nodes however will not relay them, they will not be added to the memory pool, and miners (unless running custom software) will not include them in blocks.  Non canonical signatures are still valid so if included in a block the block and txn will be accepted by the network.
full member
Activity: 136
Merit: 100
I am looking at how Bitcoin signs transactions in the src/key.cpp file, in particular the RAII wrapper around the OpenSSL implementation of ECDSA.  

In the function
Code:
bool CECKey::Sign(const uint256 &hash, std::vector& vchSig)

I see the regular call to ECDA which returns the signature in sig
Code:
ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
However, after that there are some additional manipulations of the signature

 
Code:
        BN_CTX *ctx = BN_CTX_new();
        BN_CTX_start(ctx);
        const EC_GROUP *group = EC_KEY_get0_group(pkey);
        BIGNUM *order = BN_CTX_get(ctx);
        BIGNUM *halforder = BN_CTX_get(ctx);
        EC_GROUP_get_order(group, order, ctx);
        BN_rshift1(halforder, order);
        if (BN_cmp(sig->s, halforder) > 0) {
            // enforce low S values, by negating the value (modulo the order) if above order/2.
            BN_sub(sig->s, order, sig->s);
        }
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);

What purpose do these manipulations serve? If one were to remove that code snippet, would that invalidate the signature? Or would that leak information about the private key?
Jump to: