signToSignature static method
Implementation
static ECDSASignature signToSignature(
Uint8List message, Uint8List privateKey) {
final digest = SHA256Digest();
final signer = ECDSASigner(null, HMac(digest, 64));
final key = ECPrivateKey(decodeBigInt(privateKey), _params);
signer.init(true, PrivateKeyParameter(key));
var sig = signer.generateSignature(message) 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);
}
// Now we have to work backwards to figure out the recId needed to recover the signature.
//https://github.com/web3j/web3j/blob/master/crypto/src/main/java/org/web3j/crypto/Sign.java
final publicKey = privateKeyToPublicKey(privateKey);
int recoveryId = -1;
for (var i = 0; i < 2; i++) {
final k = _recoverPublicKeyFromSignature(i, sig.r, sig.s, message);
if (ListEquality().equals(k, publicKey)) {
recoveryId = i;
break;
}
}
if (recoveryId == -1) {
throw Exception(
'Could not construct a recoverable key. This should never happen');
}
return ECDSASignature(
sig.r,
sig.s,
recoveryId + 27,
);
}