示例#1
0
        internal static bool?VerifySignatureCng(byte[] pkParameters, byte[] pkKey, byte[] hash, byte[] signature)
        {
            EllipticCurve curve       = null;
            var           ecsngHeader = new byte[8] {
                (byte)'E', (byte)'C', (byte)'S', 0, 0, 0, 0, 0
            };

            curve = GetCurveFromParameters(pkParameters);
            if (curve == null)
            {
                return(null);
            }

            if (curve == EllipticCurve.P256)
            {
                ecsngHeader[3] = (byte)'1';
            }
            else if (curve == EllipticCurve.P384)
            {
                ecsngHeader[3] = (byte)'3';
            }
            else // P512
            {
                ecsngHeader[3] = (byte)'5';
            }

            ecsngHeader[4] = (byte)curve.curveByteLen;

            var pubKeyBlob = new byte[8 + curve.curveByteLen * 2];

            Buffer.BlockCopy(ecsngHeader, 0, pubKeyBlob, 0, 8);
            Buffer.BlockCopy(pkKey, 1, pubKeyBlob, 8, curve.curveByteLen * 2);
            var ecdsa = new ECDsaCng(CngKey.Import(pubKeyBlob, CngKeyBlobFormat.EccPublicBlob));

            // We must decode the signature from DER format to raw format (to coordinates on the curve)
            var decodedSignature = Utils.DecodeDERSignature(signature, 0, signature.Length, curve.curveByteLen);

            bool ok = ecdsa.VerifyHash(hash, decodedSignature);

            return(ok);
        }
示例#2
0
        internal static bool?VerifySignature(byte[] pkParameters, byte[] pkKey, byte[] hash, byte[] signature)
        {
            EllipticCurve curve = GetCurveFromParameters(pkParameters);

            if (curve == null)
            {
                return(null);
            }

            // We must decode the signature from DER format to raw format (to coordinates on the curve)
            int offset = 1;                            // Skip tag 0x30

            Utils.GetASNLength(signature, ref offset); // P521 requires 2 bytes to specify the length
            offset += 1;                               // 0x02
            int len1 = Utils.GetASNLength(signature, ref offset);

            var rBytes = new byte[len1];

            for (var i = 0; i < len1; i++)
            {
                rBytes[i] = signature[offset + len1 - 1 - i];
            }

            offset += len1;
            offset += 1; // 0x02
            int len2 = Utils.GetASNLength(signature, ref offset);

            var sBytes = new byte[len2];

            for (var i = 0; i < len2; i++)
            {
                sBytes[i] = signature[offset + len2 - 1 - i];
            }

            var r = new BigInteger(rBytes);
            var s = new BigInteger(sBytes);

            // Verify that r, s are in [1, q - 1] and Qa lies on the curve

            if (r == 0 || s == 0)
            {
                return(false);
            }
            if (r >= curve.q || s >= curve.q)
            {
                return(false);
            }

            BigInt     Qax = new BigInt(pkKey, 1, curve.curveByteLen), Qay = new BigInt(pkKey, 1 + curve.curveByteLen, curve.curveByteLen);
            BigInteger QaxBi = Qax.ExportToBigInteger(), QayBi = Qay.ExportToBigInteger();

            var pBi = curve.p.ExportToBigInteger();

            if (QaxBi >= pBi || QayBi >= pBi)
            {
                return(false);
            }
            if ((QaxBi * QaxBi * QaxBi - 3 * QaxBi + curve.b + pBi * 3) % pBi != QayBi * QayBi % pBi)
            {
                return(false);
            }

            // Data points are ok, now start verify the signature

            var hashLen = hash.Length;

            byte[] hash2 = null;
            if (hash[0] >= 128)
            {
                hash2 = new byte[hash.Length + 1];
                hash2[hash.Length] = 0;
                for (var i = 0; i < hash.Length; i++)
                {
                    hash2[i] = hash[hash.Length - 1 - i];
                }
            }
            else
            {
                Array.Reverse(hash);
                hash2 = hash;
            }
            var z = new BigInteger(hash2);

            if (hashLen * 8 > curve.curveLen) // Should be compared to order length, but p length is the same for NIST curves
            {
                var excessBits = hashLen * 8 - curve.curveLen;
                z >>= excessBits;
            }
            var w  = BigInteger.ModPow(s, curve.q - 2, curve.q);
            var u1 = z * w % curve.q;
            var u2 = r * w % curve.q;

            var mul = curve.EcTwinMult(new BigInt(u1, (curve.curveByteLen + 3) / 4), new Projective()
            {
                x = curve.xg, y = curve.yg, z = new BigInt(1, (curve.curveByteLen + 3) / 4)
            },
                                       new BigInt(u2, (curve.curveByteLen + 3) / 4), new Projective()
            {
                x = Qax, y = Qay, z = new BigInt(1, (curve.curveByteLen + 3) / 4)
            });
            var res = curve.EcAffinify(mul).x.ExportToBigInteger();

            if (res >= curve.q)
            {
                res -= curve.q;
            }

            bool ok = res == r;

            return(ok);
        }