PublicKey RecoverPublicKey(byte[] bufferSha256) { var e = BigInteger.FromBuffer(bufferSha256); var q = ECDSA.RecoverPublicKey(Curve.SecP256k1, e, new ECSignature(r, s), ( byte )((i - 27) & 3)); return(PublicKey.FromPoint(q)); }
static Signature SignBufferSha256(byte[] bufferSha256, PrivateKey privateKey) { if (bufferSha256.Length != 32) { throw new ArgumentException("bufferSha256: 32 byte buffer requred"); } var nonce = uint.MinValue; var e = BigInteger.FromBuffer(bufferSha256); ECSignature ecSignature = null; var i = byte.MinValue; while (true) { ecSignature = ECDSA.Sign(Curve.SecP256k1, bufferSha256, privateKey.D, nonce++); var der = ecSignature.ToDER(); var lengthR = der[3]; var lengthS = der[5 + lengthR]; if (lengthR == 32 && lengthS == 32) { i = ECDSA.CalculatePublicKeyRecoveryParameter(Curve.SecP256k1, e, ecSignature, privateKey.ToPublicKey().Q); i += 4; // compressed i += 27; // compact // 24 or 27 :( forcing odd-y 2nd key candidate) break; } if (nonce % 10 == 0) { Unity.Console.Warning(nonce, "attempts to find canonical signature"); } } return(new Signature(ecSignature.R, ecSignature.S, i)); }
bool VerifyHash(byte[] hash, PublicKey publicKey) { if (hash.Length != 32) { Unity.Console.DebugWarning("A sha256 hash should be 32 bytes long, instead got ", hash.Length); } return(ECDSA.Verify(Curve.SecP256k1, hash, new ECSignature(r, s), publicKey.Q)); }