/// <summary> /// 使用私钥对消息进行签名 /// </summary> /// <param name="privateKey"></param> /// <param name="message"></param> /// <returns></returns> unsafe public static Signature Sign(ReadOnlySpan <byte> privateKey, ReadOnlySpan <byte> message) { if (privateKey.Length != 32) { throw new InvalidPrivateKeyException("私钥长度必须是32字节"); } if (message.Length != 32) { throw new InvalidMessageException("消息长度必须是32字节"); } var dA = new U256N(privateKey); var msg = new U256N(message); Span <byte> tempPrivateKey = stackalloc byte[32]; CreatePrivateKey(tempPrivateKey); var k = new U256N(tempPrivateKey); var p = (Point)EllipticCurve.MulG(k); U256N R = p.X.Value; U256N S = (msg + dA * R) / k; if (p.Y.Value.v0 % 2 != 0) { S = -S; } return(new Signature(R, S)); }
/// <summary> /// 使用公钥验证消息的签名是否正确 /// </summary> /// <param name="publicKey"></param> /// <param name="message"></param> /// <param name="signature"></param> /// <returns></returns> public static bool Verify(PublicKey publicKey, ReadOnlySpan <byte> message, Signature signature) { if (message.Length != 32) { throw new InvalidMessageException("消息长度必须是32字节"); } var msg = new U256N(message); var S_inv = ~(U256N)signature.S; var u1 = S_inv * msg; var u2 = S_inv * signature.R; var P = EllipticCurve.MulG(u1) + new JacobianPoint(publicKey.X, publicKey.Y) * u2; return(P.X == signature.R * (P.Z ^ 2)); }
/// <summary> /// 从(消息,签名)恢复公钥 /// </summary> /// <param name="message"></param> /// <param name="signature"></param> /// <returns></returns> unsafe public static PublicKey RecoverPublicKey(ReadOnlySpan <byte> message, Signature signature) { if (message.Length != 32) { throw new InvalidMessageException("消息长度必须是32字节"); } U256N s = signature.S; var m = new U256N(message); var rY = EllipticCurve.GetY(signature.R); if (rY.Value.v0 % 2 != 0) { s = -s; } var rP = new JacobianPoint(signature.R, rY); var r_inv = ~new U256N(signature.R); var u1 = EllipticCurve.MulG(-m * r_inv); var u2 = s * r_inv; var p = (Point)(rP * u2 + u1); return(new PublicKey(p.X, p.Y)); }