I need to use ECDSA as the signing algorithm and SHA256 for hashing the message. I'm running into troubles verifying the signature calculated on two different platform (one is BouncyCastle, another one a C library for a microprocessor).
I figured out that BouncyCastle, in its ECDSASigner class, reduces the input message (which is supposed to be already the hash), in both, generateSignature()
and verifySignature()
using a helper function called calculateE()
. In essence, this functions truncates the input message/hash to the bitlength of the curve's order $N$.
protected BigInteger calculateE(BigInteger n, byte[] message)
{
int log2n = n.bitLength();
int messageBitLength = message.length * 8;
BigInteger e = new BigInteger(1, message);
if (log2n < messageBitLength)
{
e = e.shiftRight(messageBitLength - log2n);
}
return e;
}
This reduction results from the fact that a SHA256 hash has 32 Bytes, whereas the size of $N$ is (for secp192r1) 192/8 = 24
Bytes.
What I don't understand:
- Do I have to use a curve with greater size of
bitlength(N)
for SHA256 hashes to be signed (e.g., secp256r1 or secp521r1)? - Is the implementation in BouncyCastle wrong/imcomplete, or only applies to SHA-1 (
160 b = 20 B <= 24 B
)? - Where is it documented/specified, how to “reduce” a hash of greater bitlength than that of the curve domain?