signToSignature static method

ECDSASignature signToSignature(
  1. Uint8List message,
  2. Uint8List privateKey
)

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,
  );
}