/// <summary> /// Decrypt a stream using the private key stream. /// </summary> /// <param name="inputStream"> /// The stream of the encrypted file. /// </param> /// <param name="privateKeyStream"> /// The stream of the private key file. /// </param> /// <param name="passPhrase"> /// The pass phrase protecting the secret key. /// </param> /// <param name="outputFile"> /// The file path to write the decrypted output to. /// </param> /// <returns> /// The <see cref="bool"/> flag indicating decryption success; false states /// decryption failed because of a data integrity check error. /// </returns> public static bool DecryptFileStream( Stream inputStream, Stream privateKeyStream, string passPhrase, string outputFile) { PgpPrivateKey privateKey = null; var valid = true; try { PgpEncryptedDataList encryptedDataList; PgpPublicKeyEncryptedData encryptedData = null; var objectFactory = new PgpObjectFactory(PgpUtilities.GetDecoderStream(inputStream)); var secretKeyRing = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(privateKeyStream)); var @object = objectFactory.NextPgpObject(); if (@object is PgpEncryptedDataList) { encryptedDataList = (PgpEncryptedDataList)@object; } else { encryptedDataList = (PgpEncryptedDataList)objectFactory.NextPgpObject(); } foreach (PgpPublicKeyEncryptedData pked in encryptedDataList.GetEncryptedDataObjects()) { privateKey = PgpKeyHelper.FindSecretKey(secretKeyRing, pked.KeyId, passPhrase.ToCharArray()); if (privateKey == null) { continue; } encryptedData = pked; break; } if (privateKey == null) { throw new ArgumentException("Secret key for message not found."); } PgpObjectFactory plainFact; using (var clear = encryptedData.GetDataStream(privateKey)) { plainFact = new PgpObjectFactory(clear); } var message = plainFact.NextPgpObject(); if (message is PgpCompressedData) { var data = (PgpCompressedData)message; PgpObjectFactory of; using (var compDataIn = data.GetDataStream()) { of = new PgpObjectFactory(compDataIn); } message = of.NextPgpObject(); if (message is PgpOnePassSignatureList) { message = of.NextPgpObject(); var literalData = (PgpLiteralData)message; using (Stream output = File.Create(outputFile)) { var unc = literalData.GetInputStream(); Streams.PipeAll(unc, output); } } else { var literalData = (PgpLiteralData)message; using (Stream output = File.Create(outputFile)) { Stream unc = literalData.GetInputStream(); Streams.PipeAll(unc, output); } } } else if (message is PgpLiteralData) { PgpLiteralData literalData = (PgpLiteralData)message; string unused = literalData.FileName; using (Stream outputStream = File.Create(outputFile)) { Stream unc = literalData.GetInputStream(); Streams.PipeAll(unc, outputStream); } } else if (message is PgpOnePassSignatureList) { throw new PgpException("Encrypted message contains a signed message - not literal data."); } else { throw new PgpException("Message is not a simple encrypted file - type unknown."); } if (encryptedData.IsIntegrityProtected()) { if (!encryptedData.Verify()) { Console.Error.WriteLine("Message failed integrity check"); valid = false; } else { Console.Error.WriteLine("Message integrity check passed"); } } } catch (PgpException exception) { PgpCommon.DumpException(exception); throw; } return(valid); }
/// <summary> /// Encrypt a file as specified by the input file path. /// </summary> /// <param name="inputFile"> /// The file to encrypt. /// </param> /// <param name="outputFile"> /// The file to write the encrypted content to. /// </param> /// <param name="publicKeyFile"> /// The path to the public key file to use for encryption. /// </param> /// <param name="symmetricKeyAlgorithm"> /// Encryption algorithm. /// </param> /// <param name="armor"> /// Should the encrypted file be written using ASCII armor? /// </param> /// <param name="withIntegrityCheck"> /// Should the integrity be verified? /// </param> /// <param name="compressionAlgorithm"> /// Compression algorithm to use. /// </param> public static void EncryptFile( string inputFile, string outputFile, string publicKeyFile, SymmetricKeyAlgorithmTag symmetricKeyAlgorithm = SymmetricKeyAlgorithmTag.Aes256, bool armor = true, bool withIntegrityCheck = true, CompressionAlgorithmTag compressionAlgorithm = CompressionAlgorithmTag.Zip) { try { using (Stream publicKeyStream = File.OpenRead(publicKeyFile)) { PgpPublicKey encKey = PgpKeyHelper.ReadPublicKey(publicKeyStream); using (var memoryStream = new MemoryStream()) { var compressedDataGenerator = new PgpCompressedDataGenerator(compressionAlgorithm); WriteFileToLiteralData( compressedDataGenerator.Open(memoryStream), PgpLiteralData.Binary, new FileInfo(inputFile)); compressedDataGenerator.Close(); var encryptedDataGenerator = new PgpEncryptedDataGenerator( symmetricKeyAlgorithm, withIntegrityCheck, new SecureRandom()); encryptedDataGenerator.AddMethod(encKey); var bytes = memoryStream.ToArray(); using (Stream outputStream = File.Create(outputFile)) { if (armor) { using (var armoredStream = new ArmoredOutputStream(outputStream)) using (var encryptedStream = encryptedDataGenerator.Open(armoredStream, bytes.Length)) { encryptedStream.Write(bytes, 0, bytes.Length); } } else { using ( Stream encryptedOutputStream = encryptedDataGenerator.Open( outputStream, bytes.Length)) { encryptedOutputStream.Write(bytes, 0, bytes.Length); } } } } } } catch (PgpException exception) { PgpCommon.DumpException(exception); throw; } }