/// <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> /// Decrypt the stream. /// </summary> /// <param name="decrypted">The stream containing the decrypted data.</param> /// <param name="input">The data to decrypt.</param> /// <param name="secretKey">The secret key used for decryption.</param> /// <param name="password">The password used to protect the secret key.</param> /// <returns>Returns null if no integrity packet exists; false if message failed integrity check; true if message integrity check passed.</returns> public bool?Decrypt(System.IO.Stream decrypted, System.IO.Stream input, System.IO.Stream secretKey, string password) { // Get decorder stream. input = Key.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(input); System.IO.Stream clear = null; System.IO.Stream unc = null; try { // Load the encrypted input stream. Key.Bcpg.OpenPgp.PgpEncryptedDataList encryptedDataList = null; Key.Bcpg.OpenPgp.PgpObjectFactory objectFactory = new Key.Bcpg.OpenPgp.PgpObjectFactory(input); Key.Bcpg.OpenPgp.PgpObject o = objectFactory.NextPgpObject(); // The first object might be a PGP marker packet. if (o is Key.Bcpg.OpenPgp.PgpEncryptedDataList) { // Get the data list. encryptedDataList = (Key.Bcpg.OpenPgp.PgpEncryptedDataList)o; } else { // Get the next object. encryptedDataList = (Key.Bcpg.OpenPgp.PgpEncryptedDataList)objectFactory.NextPgpObject(); } // Find the secret key Key.Bcpg.OpenPgp.PgpPrivateKey privateKey = null; Key.Bcpg.OpenPgp.PgpPublicKeyEncryptedData publicKeyEncryptedData = null; Key.Bcpg.OpenPgp.PgpSecretKeyRingBundle secretKeyRingBundle = new Key.Bcpg.OpenPgp.PgpSecretKeyRingBundle(Key.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(secretKey)); // For each object find the secret key. foreach (Key.Bcpg.OpenPgp.PgpPublicKeyEncryptedData pked in encryptedDataList.GetEncryptedDataObjects()) { // Find the private key (secret key). privateKey = FindSecretKey(secretKeyRingBundle, pked.KeyId, password.ToArray()); // If the private key exists. if (privateKey != null) { // This is the private key. publicKeyEncryptedData = pked; break; } } // If a private key was not found. if (privateKey == null) { throw new ArgumentException("secret key for message not found."); } // Get the data stream. clear = publicKeyEncryptedData.GetDataStream(privateKey); // Get the key message. Key.Bcpg.OpenPgp.PgpObjectFactory plainFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(clear); Key.Bcpg.OpenPgp.PgpObject message = plainFact.NextPgpObject(); // If message is compressed. if (message is Key.Bcpg.OpenPgp.PgpCompressedData) { // Decompress the message. Key.Bcpg.OpenPgp.PgpCompressedData cData = (Key.Bcpg.OpenPgp.PgpCompressedData)message; Key.Bcpg.OpenPgp.PgpObjectFactory pgpFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(cData.GetDataStream()); message = pgpFact.NextPgpObject(); } // If the message is literal data. if (message is Key.Bcpg.OpenPgp.PgpLiteralData) { Key.Bcpg.OpenPgp.PgpLiteralData ld = (Key.Bcpg.OpenPgp.PgpLiteralData)message; // Get the file name of the embedded encrypted file. string outFileName = ld.FileName; // Write the ecrypted data file to the decrypted stream. unc = ld.GetInputStream(); Key.Utilities.IO.Streams.PipeAll(unc, decrypted); } else if (message is Key.Bcpg.OpenPgp.PgpOnePassSignatureList) { throw new Exception("encrypted message contains a signed message - not literal data."); } else { throw new Exception("message is not a simple encrypted file - type unknown."); } // If the ecrypted file contains an integrity packet associated with it. if (publicKeyEncryptedData.IsIntegrityProtected()) { // If it has been verified. if (!publicKeyEncryptedData.Verify()) { // Message failed integrity check. return(false); } else { // Message integrity check passed. return(true); } } // No integrity packet exists. return(null); } catch (Exception) { throw; } finally { if (clear != null) { clear.Close(); } if (unc != null) { unc.Close(); } } }
/// <summary> /// Decrypt the stream. /// </summary> /// <param name="decrypted">The stream containing the decrypted data.</param> /// <param name="input">The data to decrypt.</param> /// <param name="password">The password used for decryption.</param> /// <returns>Returns null if no integrity packet exists; false if message failed integrity check; true if message integrity check passed.</returns> public bool?Decrypt(System.IO.Stream decrypted, System.IO.Stream input, string password) { // Get decorder stream. input = Key.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(input); System.IO.Stream clear = null; System.IO.Stream unc = null; try { // Load the encrypted input stream. Key.Bcpg.OpenPgp.PgpEncryptedDataList encryptedDataList = null; Key.Bcpg.OpenPgp.PgpObjectFactory objectFactory = new Key.Bcpg.OpenPgp.PgpObjectFactory(input); Key.Bcpg.OpenPgp.PgpObject o = objectFactory.NextPgpObject(); // The first object might be a PGP marker packet. if (o is Key.Bcpg.OpenPgp.PgpEncryptedDataList) { // Get the data list. encryptedDataList = (Key.Bcpg.OpenPgp.PgpEncryptedDataList)o; } else { // Get the next object. encryptedDataList = (Key.Bcpg.OpenPgp.PgpEncryptedDataList)objectFactory.NextPgpObject(); } // Load the password. Key.Bcpg.OpenPgp.PgpPbeEncryptedData pbe = (Key.Bcpg.OpenPgp.PgpPbeEncryptedData)encryptedDataList[0]; clear = pbe.GetDataStream(password.ToArray()); Key.Bcpg.OpenPgp.PgpObjectFactory plainFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(clear); Key.Bcpg.OpenPgp.PgpObject message = plainFact.NextPgpObject(); // If message is compressed. if (message is Key.Bcpg.OpenPgp.PgpCompressedData) { // Decompress the message. Key.Bcpg.OpenPgp.PgpCompressedData cData = (Key.Bcpg.OpenPgp.PgpCompressedData)message; Key.Bcpg.OpenPgp.PgpObjectFactory pgpFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(cData.GetDataStream()); message = pgpFact.NextPgpObject(); } // If the message is literal data. if (message is Key.Bcpg.OpenPgp.PgpLiteralData) { Key.Bcpg.OpenPgp.PgpLiteralData ld = (Key.Bcpg.OpenPgp.PgpLiteralData)message; // Get the file name of the embedded encrypted file. string outFileName = ld.FileName; // Write the ecrypted data file to the decrypted stream. unc = ld.GetInputStream(); Key.Utilities.IO.Streams.PipeAll(unc, decrypted); } else if (message is Key.Bcpg.OpenPgp.PgpOnePassSignatureList) { throw new Exception("encrypted message contains a signed message - not literal data."); } else { throw new Exception("message is not a simple encrypted file - type unknown."); } // If the ecrypted file contains an integrity packet associated with it. if (pbe.IsIntegrityProtected()) { // If it has been verified. if (!pbe.Verify()) { // Message failed integrity check. return(false); } else { // Message integrity check passed. return(true); } } // No integrity packet exists. return(null); } catch (Exception) { throw; } finally { if (clear != null) { clear.Close(); } if (unc != null) { unc.Close(); } } }