// Verify a DSA signature. public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { // Validate the parameters. if (rgbHash == null) { throw new ArgumentNullException("rgbHash"); } if (rgbSignature == null) { throw new ArgumentNullException("rgbSignature"); } // Make sure that we have sufficient parameters to verify. if (dsaParams.G == null) { throw new CryptographicException (_("Crypto_DSAParamsNotSet")); } // Unpack the signature blob to get R and S. ASN1Parser parser; parser = (new ASN1Parser(rgbSignature)).GetSequence(); byte[] R = parser.GetBigInt(); byte[] S = parser.GetBigInt(); parser.AtEnd(); // Compute W = (S^-1 mod Q) byte[] W = CryptoMethods.NumInv(S, dsaParams.Q); // Compute U1 = ((hash * W) mod Q) byte[] U1 = CryptoMethods.NumMul(rgbHash, W, dsaParams.Q); // Compute U2 = ((R * W) mod Q) byte[] U2 = CryptoMethods.NumMul(R, W, dsaParams.Q); // Compute V = (((G^U1 * Y^U2) mod P) mod Q) byte[] temp1 = CryptoMethods.NumPow (dsaParams.G, U1, dsaParams.P); byte[] temp2 = CryptoMethods.NumPow (dsaParams.Y, U2, dsaParams.P); byte[] temp3 = CryptoMethods.NumMul(temp1, temp2, dsaParams.P); byte[] V = CryptoMethods.NumMod(temp3, dsaParams.Q); // Determine if we have a signature match. bool result = CryptoMethods.NumEq(V, R); // Clear sensitive values. Array.Clear(R, 0, R.Length); Array.Clear(S, 0, S.Length); Array.Clear(W, 0, W.Length); Array.Clear(U1, 0, U1.Length); Array.Clear(U2, 0, U2.Length); Array.Clear(temp1, 0, temp1.Length); Array.Clear(temp2, 0, temp2.Length); Array.Clear(temp3, 0, temp3.Length); Array.Clear(V, 0, V.Length); // Done. return(result); }