public byte[] SignHashed(byte[] messageHash, byte[] privateKey, bool useNewChainId) { if (privateKey.Length != 32) { throw new ArgumentException(nameof(privateKey)); } if (messageHash.Length != 32) { throw new ArgumentException(nameof(messageHash)); } return(EcSign.Benchmark(() => { var sig = new byte[65]; if (!Secp256K1.SignRecoverable(sig, messageHash, privateKey)) { throw new Exception("secp256k1.sign_recoverable failed"); } var serialized = new byte[64]; if (!Secp256K1.RecoverableSignatureSerializeCompact(serialized, out var recId, sig)) { throw new Exception("Cannot serialize recoverable signature: how did it happen?"); } recId = TransactionUtils.ChainId(useNewChainId) * 2 + 35 + recId; var recIdBytes = new byte[useNewChainId ? 2 : 1]; var fullBin = recId.ToBytes().ToArray(); if (useNewChainId) { recIdBytes[0] = fullBin[1]; recIdBytes[1] = fullBin[0]; } else { recIdBytes[0] = fullBin[0]; } return serialized.Concat(recIdBytes).ToArray(); })); }
public byte[] RecoverSignatureHashed(byte[] messageHash, byte[] signature, bool useNewChainId) { if (messageHash.Length != 32) { throw new ArgumentException(nameof(messageHash)); } if (signature.Length != SignatureSize(useNewChainId)) { throw new ArgumentException(nameof(signature)); } return(EcRecover.Benchmark(() => { var parsedSig = new byte[65]; var pk = new byte[64]; var encodedRecId = RestoreEncodedRecIdFromSignatureBuffer(signature); var recId = (encodedRecId - 36) / 2 / TransactionUtils.ChainId(useNewChainId); if (recId < 0 || recId > 3) { throw new Exception($"Invalid recId={recId}: : recId >= 0 && recId <= 3 "); } if (!Secp256K1.RecoverableSignatureParseCompact(parsedSig, signature.Take(64).ToArray(), recId)) { throw new ArgumentException(nameof(signature)); } if (!Secp256K1.Recover(pk, parsedSig, messageHash)) { throw new ArgumentException("Bad signature"); } var result = new byte[33]; if (!Secp256K1.PublicKeySerialize(result, pk, Flags.SECP256K1_EC_COMPRESSED)) { throw new Exception("Cannot serialize recovered public key: how did it happen?"); } return result; })); }
public bool VerifySignatureHashed(byte[] messageHash, byte[] signature, byte[] publicKey, bool useNewChainId) { if (messageHash.Length != 32 || signature.Length != SignatureSize(useNewChainId)) { return(false); } return(EcVerify.Benchmark(() => { var pk = new byte[64]; if (!Secp256K1.PublicKeyParse(pk, publicKey)) { return false; } var publicKeySerialized = new byte[33]; if (!Secp256K1.PublicKeySerialize(publicKeySerialized, pk, Flags.SECP256K1_EC_COMPRESSED)) { throw new Exception("Cannot serialize parsed key: how did it happen?"); } var parsedSig = new byte[65]; var recId = (RestoreEncodedRecIdFromSignatureBuffer(signature) - 36) / 2 / TransactionUtils.ChainId(useNewChainId); if (recId < 0 || recId > 3) { throw new Exception($"Invalid recId={recId}: : recId >= 0 && recId <= 3 "); } if (!Secp256K1.RecoverableSignatureParseCompact(parsedSig, signature.Take(64).ToArray(), recId)) { return false; } return Secp256K1.Verify(parsedSig.Take(64).ToArray(), messageHash, pk); })); }