/// <summary> /// Verifies that a digital signature is valid by determining the hash value /// in the signature using the provided public key and comparing it to the hash /// value of the provided data. /// </summary> /// <param name="inputStream">The data that was signed.</param> /// <param name="signature">The signature data to be verified.</param> /// <param name="rsaProvider">The RSA crypto service provider.</param> /// <param name="hashAlgorithm">The hash algorithm to use to create the hash value.</param> /// <returns>True if the signature is valid; otherwise, false.</returns> public bool VerifyData(Stream inputStream, byte[] signature, RSACryptoServiceProvider rsaProvider, Nequeo.Cryptography.HashcodeType hashAlgorithm = HashcodeType.SHA512) { Stream signatureInput = null; try { // Export the signer public key parameters. RSAParameters rsaPublicKeySignerParam = rsaProvider.ExportParameters(false); Key.Crypto.Parameters.RsaKeyParameters rsaPublicKeySigner = new Key.Crypto.Parameters.RsaKeyParameters( false, new Key.Math.BigInteger(1, rsaPublicKeySignerParam.Modulus), new Key.Math.BigInteger(1, rsaPublicKeySignerParam.Exponent) ); signatureInput = new MemoryStream(signature); signatureInput = Key.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(signatureInput); // Get the public key. Key.Bcpg.OpenPgp.PgpPublicKey publicKey = new Key.Bcpg.OpenPgp.PgpPublicKey(Key.Bcpg.PublicKeyAlgorithmTag.RsaGeneral, rsaPublicKeySigner, DateTime.UtcNow); Key.Bcpg.OpenPgp.PgpObjectFactory pgpFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(signatureInput); Key.Bcpg.OpenPgp.PgpSignatureList signatureList = null; Key.Bcpg.OpenPgp.PgpObject pgpObject = pgpFact.NextPgpObject(); // If the message is compressed. if (pgpObject is Key.Bcpg.OpenPgp.PgpCompressedData) { // Get the compression object. Key.Bcpg.OpenPgp.PgpCompressedData compressedData = (Key.Bcpg.OpenPgp.PgpCompressedData)pgpObject; pgpFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(compressedData.GetDataStream()); signatureList = (Key.Bcpg.OpenPgp.PgpSignatureList)pgpFact.NextPgpObject(); } else { // Get the message list. signatureList = (Key.Bcpg.OpenPgp.PgpSignatureList)pgpObject; } // Load the public key into the pgp signer. Key.Bcpg.OpenPgp.PgpSignature pgpSignature = signatureList[0]; pgpSignature.InitVerify(publicKey); int ch; while ((ch = inputStream.ReadByte()) >= 0) { // Update the generator. pgpSignature.Update((byte)ch); } // Verify the signature. if (pgpSignature.Verify()) { // signature verified. return(true); } else { // signature verification failed. return(false); } } catch (Exception) { throw; } finally { if (signatureInput != null) { signatureInput.Close(); } } }
/// <summary> /// Computes the hash value of the specified input stream using the specified /// hash algorithm, and signs the resulting hash value. /// </summary> /// <param name="inputStream">The input data for which to compute the hash.</param> /// <param name="rsaProvider">The RSA crypto service provider.</param> /// <param name="keyID">The unique key id of the public secret key pair.</param> /// <param name="hashAlgorithm">The hash algorithm to use to create the hash value.</param> /// <returns>The signature for the specified data.</returns> public byte[] SignData(Stream inputStream, RSACryptoServiceProvider rsaProvider, long keyID, Nequeo.Cryptography.HashcodeType hashAlgorithm = HashcodeType.SHA512) { MemoryStream output = null; Key.Bcpg.BcpgOutputStream pgpOutput = null; try { int ch; output = new MemoryStream(); // Export the signer private key parameters. RSAParameters rsaPrivateKeySignerParam = rsaProvider.ExportParameters(true); Key.Crypto.Parameters.RsaPrivateCrtKeyParameters rsaPrivateKeySigner = new Key.Crypto.Parameters.RsaPrivateCrtKeyParameters( new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.Modulus), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.Exponent), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.D), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.P), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.Q), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.DP), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.DQ), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.InverseQ) ); // Get the private key. Key.Bcpg.OpenPgp.PgpPrivateKey privateKey = new Key.Bcpg.OpenPgp.PgpPrivateKey(rsaPrivateKeySigner, keyID); // Create a signature generator. Key.Bcpg.OpenPgp.PgpSignatureGenerator signatureGenerator = new Key.Bcpg.OpenPgp.PgpSignatureGenerator(Key.Bcpg.PublicKeyAlgorithmTag.RsaGeneral, GetHashAlgorithm(hashAlgorithm)); signatureGenerator.InitSign(Key.Bcpg.OpenPgp.PgpSignature.BinaryDocument, privateKey); // Create the output stream. pgpOutput = new Key.Bcpg.BcpgOutputStream(output); // Read the input stream. while ((ch = inputStream.ReadByte()) >= 0) { // Update the generator. signatureGenerator.Update((byte)ch); } // Write the hash to the output stream. Key.Bcpg.OpenPgp.PgpSignature signature = signatureGenerator.Generate(); signature.Encode(pgpOutput); // Return the signed value. return(output.ToArray()); } catch (Exception) { throw; } finally { if (output != null) { output.Close(); } if (pgpOutput != null) { pgpOutput.Close(); } } }