public static Stream DecryptSingleFile(Stream encryptedStream, SecureString passphrase, out string filename, out DateTime fileDate) { SymmetricAlgorithm symmetricAlgorithm = null; foreach (var packet in OpenPgpPacketReader.ReadAllPackets(encryptedStream)) { var encryptedSessionKey = packet as SymmetricKeyEncryptedSessionKeyOpenPgpPacket; if (encryptedSessionKey != null) { symmetricAlgorithm = encryptedSessionKey.GetKeyedSymmetricAlgorithm(passphrase); } var encryptedIntegrityProtectedData = packet as SymmetricallyEncryptedIntegrityProtectedDataOpenPgpPacket; if (encryptedIntegrityProtectedData != null) { foreach (var decryptedPacket in encryptedIntegrityProtectedData.GetDecryptedPackets(symmetricAlgorithm)) { var compressedPacket = decryptedPacket as CompressedDataOpenPgpPacket; if (compressedPacket != null) { Stream literalStream = null; filename = null; fileDate = DateTime.MinValue; foreach (var decompressedPacket in OpenPgpPacketReader.ReadAllPackets(compressedPacket.DecompressedStream)) { var literalData = decompressedPacket as LiteralDataOpenPgpPacket; if (literalData != null) { filename = literalData.FileName; fileDate = literalData.FileDate; literalStream = literalData.LiteralStream; } } return(literalStream); } } } } throw new CryptographicException(); }
// Throw error if not valid public IEnumerable <OpenPgpPacket> GetDecryptedPackets(SymmetricAlgorithm keyedAlgorithm) { var transform = new OpenPgpCfbTransform(keyedAlgorithm, encrypt: false); var decryptor = new CryptoStream(EncryptedStream, transform, CryptoStreamMode.Read); var decrypted = new MemoryStream(); decryptor.CopyTo(decrypted); // Get rid of the modification detection code, but verify it var mdcStart = decrypted.Length - (1 + 1 + 20); decrypted.Position = mdcStart; var mdcStream = new MemoryStream(); decrypted.CopyTo(mdcStream); decrypted.Position = 0; decrypted.SetLength(mdcStart + 2); var hasher = SHA1.Create(); var hashIncludingHeaderAndLength = hasher.ComputeHash(transform.PrefixBytes.Concat(decrypted.ToArray()).ToArray()); decrypted.SetLength(decrypted.Length - 2); decrypted.Position = 0; // TODO: mdcStream.Position = 0; var mdc = OpenPgpPacketReader.ReadAllPackets(mdcStream).First() as ModificationDetectionCodeOpenPgpPacket; for (int i = 0; i < hashIncludingHeaderAndLength.Length; i++) { if (hashIncludingHeaderAndLength[i] != mdc.HashValue[i]) { throw new ModificationDetectedException(); } } return(OpenPgpPacketReader.ReadAllPackets(decrypted)); }