sign function
Signs the hashed data in messageHash
using the given private key.
Implementation
MsgSignature sign(Uint8List messageHash, Uint8List privateKey) {
final digest = SHA256Digest();
final signer = ECDSASigner(null, HMac(digest, 64));
final key = ECPrivateKey(bytesToUnsignedInt(privateKey), params);
signer.init(true, PrivateKeyParameter(key));
var sig = signer.generateSignature(messageHash) as ECSignature;
/*
This is necessary because if a message can be signed by (r, s), it can also
be signed by (r, -s (mod N)) which N being the order of the elliptic function
used. In order to ensure transactions can't be tampered with (even though it
would be harmless), Ethereum only accepts the signature with the lower value
of s to make the signature for the message unique.
More details at
https://github.com/web3j/web3j/blob/master/crypto/src/main/java/org/web3j/crypto/ECDSASignature.java#L27
*/
if (sig.s.compareTo(_halfCurveOrder) > 0) {
final canonicalisedS = params.n - sig.s;
sig = ECSignature(sig.r, canonicalisedS);
}
final publicKey = bytesToUnsignedInt(privateKeyBytesToPublic(privateKey));
final recId = EC.secp256k1.calculateRecoveryId(publicKey, sig, messageHash);
if (recId == null) {
throw Exception(
'Could not construct a recoverable key. This should never happen',
);
}
return MsgSignature(sig.r, sig.s, recId + 27);
}