/// <summary> /// Performs the scalar multiplication of <paramref name="N"/>*<paramref name="P"/>. /// </summary> /// <param name="N">Scalar, in binary, little-endian form.</param> /// <param name="P">Point</param> /// <param name="Normalize">If normalized output is expected.</param> /// <returns><paramref name="N"/>*<paramref name="P"/></returns> public override PointOnCurve ScalarMultiplication(byte[] N, PointOnCurve P, bool Normalize) { PointOnCurve Result = base.ScalarMultiplication(N, P, Normalize); if (Normalize) { Result.Normalize(this); } return(Result); }
/// <summary> /// Verifies a signature of <paramref name="Data"/> made by the EdDSA algorithm. /// </summary> /// <param name="Data">Payload to sign.</param> /// <param name="PublicKey">Public Key of the entity that generated the signature.</param> /// <param name="HashFunction">Hash function to use.</param> /// <param name="Curve">Elliptic curve</param> /// <param name="Signature">Signature</param> /// <returns>If the signature is valid.</returns> public static bool Verify(Stream Data, byte[] PublicKey, HashFunctionStream HashFunction, EdwardsCurveBase Curve, byte[] Signature) { try { int ScalarBytes = Signature.Length; if ((ScalarBytes & 1) != 0) { return(false); } ScalarBytes >>= 1; byte[] R = new byte[ScalarBytes]; Array.Copy(Signature, 0, R, 0, ScalarBytes); PointOnCurve r = Decode(R, Curve); byte[] S = new byte[ScalarBytes]; Array.Copy(Signature, ScalarBytes, S, 0, ScalarBytes); BigInteger s = EllipticCurve.ToInt(S); byte[] h; if (s >= Curve.Order) { return(false); } using (TemporaryStream TempFile = new TemporaryStream()) // dom2(F, C) = blank string { TempFile.Write(R, 0, ScalarBytes); TempFile.Write(PublicKey, 0, ScalarBytes); Data.Position = 0; Data.CopyTo(TempFile); // PH(M)=M TempFile.Position = 0; h = HashFunction(TempFile); } BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order); PointOnCurve P1 = Curve.ScalarMultiplication(s, Curve.BasePoint, false); PointOnCurve P2 = Curve.ScalarMultiplication(k, Curve.Decode(PublicKey), false); Curve.AddTo(ref P2, r); P1.Normalize(Curve); P2.Normalize(Curve); return(P1.Equals(P2)); } catch (ArgumentException) { return(false); } }
/// <summary> /// Verifies a signature of <paramref name="Data"/> made by the ECDSA algorithm. /// </summary> /// <param name="Data">Payload to sign.</param> /// <param name="PublicKey">Public Key of the entity that generated the signature.</param> /// <param name="HashFunction">Hash function to use.</param> /// <param name="Curve">Elliptic curve</param> /// <param name="ScalarBytes">Number of bytes to use for scalars.</param> /// <param name="MsbMask">Mask for most significant byte.</param> /// <param name="Signature">Signature</param> /// <returns>If the signature is valid.</returns> public static bool Verify(byte[] Data, byte[] PublicKey, HashFunction HashFunction, int ScalarBytes, byte MsbMask, PrimeFieldCurve Curve, byte[] Signature) { int c = Signature.Length; if (c != ScalarBytes << 1) { return(false); } c >>= 1; byte[] Bin = new byte[c]; Array.Copy(Signature, 0, Bin, 0, c); BigInteger r = EllipticCurve.ToInt(Bin); Bin = new byte[c]; Array.Copy(Signature, c, Bin, 0, c); BigInteger s = EllipticCurve.ToInt(Bin); PointOnCurve PublicKeyPoint = Curve.Decode(PublicKey); if (!PublicKeyPoint.NonZero || r.IsZero || s.IsZero || r >= Curve.Order || s >= Curve.Order) { return(false); } BigInteger e = CalcE(Data, HashFunction, ScalarBytes, MsbMask); BigInteger w = Curve.ModulusN.Invert(s); BigInteger u1 = Curve.ModulusN.Multiply(e, w); BigInteger u2 = Curve.ModulusN.Multiply(r, w); PointOnCurve P2 = Curve.ScalarMultiplication(u1, Curve.BasePoint, true); PointOnCurve P3 = Curve.ScalarMultiplication(u2, PublicKeyPoint, true); Curve.AddTo(ref P2, P3); if (!P2.NonZero) { return(false); } P2.Normalize(Curve); BigInteger Compare = BigInteger.Remainder(P2.X, Curve.Order); if (Compare.Sign < 0) { Compare += Curve.Order; } return(Compare == r); }
/// <summary> /// Verifies a signature of <paramref name="Data"/> made by the EdDSA algorithm. /// </summary> /// <param name="Data">Payload to sign.</param> /// <param name="PublicKey">Public Key of the entity that generated the signature.</param> /// <param name="HashFunction">Hash function to use.</param> /// <param name="Curve">Elliptic curve</param> /// <param name="Signature">Signature</param> /// <returns>If the signature is valid.</returns> public static bool Verify(byte[] Data, byte[] PublicKey, HashFunctionArray HashFunction, EdwardsCurveBase Curve, byte[] Signature) { try { int ScalarBytes = Signature.Length; if ((ScalarBytes & 1) != 0) { return(false); } ScalarBytes >>= 1; byte[] R = new byte[ScalarBytes]; Array.Copy(Signature, 0, R, 0, ScalarBytes); PointOnCurve r = Decode(R, Curve); byte[] S = new byte[ScalarBytes]; Array.Copy(Signature, ScalarBytes, S, 0, ScalarBytes); BigInteger s = EllipticCurve.ToInt(S); if (s >= Curve.Order) { return(false); } int c = Data.Length; byte[] Bin = new byte[(ScalarBytes << 1) + c]; // dom2(F, C) = blank string Array.Copy(R, 0, Bin, 0, ScalarBytes); Array.Copy(PublicKey, 0, Bin, ScalarBytes, ScalarBytes); Array.Copy(Data, 0, Bin, ScalarBytes << 1, c); // PH(M)=M byte[] h = HashFunction(Bin); BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order); PointOnCurve P1 = Curve.ScalarMultiplication(s, Curve.BasePoint, false); PointOnCurve P2 = Curve.ScalarMultiplication(k, Curve.Decode(PublicKey), false); Curve.AddTo(ref P2, r); P1.Normalize(Curve); P2.Normalize(Curve); return(P1.Equals(P2)); } catch (ArgumentException) { return(false); } }