From 350784eb28f821a53303af31c49aefb56d29d534 Mon Sep 17 00:00:00 2001 From: mattosaurus Date: Tue, 27 Aug 2019 16:46:20 +0100 Subject: [PATCH 1/2] Update EncryptStream and EncryptFile methods to handle large files. --- PgpCore/PGP.cs | 107 ++++++++++++++++--------------------------------- 1 file changed, 35 insertions(+), 72 deletions(-) diff --git a/PgpCore/PGP.cs b/PgpCore/PGP.cs index 6f52999..bb7ecc1 100644 --- a/PgpCore/PGP.cs +++ b/PgpCore/PGP.cs @@ -146,50 +146,22 @@ public void EncryptFile( throw new FileNotFoundException(String.Format("Input file [{0}] does not exist.", publicKeyFilePath)); } - using (MemoryStream @out = new MemoryStream()) - { - if (CompressionAlgorithm != CompressionAlgorithmTag.Uncompressed) - { - PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(CompressionAlgorithm); - PgpUtilities.WriteFileToLiteralData(comData.Open(@out), FileTypeToChar(), new FileInfo(inputFilePath)); - comData.Close(); - } - else - PgpUtilities.WriteFileToLiteralData(@out, FileTypeToChar(), new FileInfo(inputFilePath)); + List publicKeyStreams = new List(); - PgpEncryptedDataGenerator pk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithm, withIntegrityCheck, new SecureRandom()); - - foreach (string publicKeyFilePath in publicKeys) + foreach (string publicKeyFilePath in publicKeyFilePaths) + { + MemoryStream memoryStream = new MemoryStream(); + using (Stream publicKeyStream = new FileStream(publicKeyFilePath, FileMode.Open)) { - using (Stream pkStream = File.OpenRead(publicKeyFilePath)) - { - pk.AddMethod(Utilities.ReadPublicKey(pkStream)); - } - } - - byte[] bytes = @out.ToArray(); - - using (Stream outStream = File.Create(outputFilePath)) - { - if (armor) - { - using (ArmoredOutputStream armoredStream = new ArmoredOutputStream(outStream)) - { - using (Stream armoredOutStream = pk.Open(armoredStream, bytes.Length)) - { - armoredOutStream.Write(bytes, 0, bytes.Length); - } - } - } - else - { - using (Stream plainStream = pk.Open(outStream, bytes.Length)) - { - plainStream.Write(bytes, 0, bytes.Length); - } - } + publicKeyStream.CopyTo(memoryStream); + memoryStream.Position = 0; + publicKeyStreams.Add(memoryStream); } } + + using (FileStream inputStream = new FileStream(inputFilePath, FileMode.Open)) + using (Stream outputStream = File.Create(outputFilePath)) + EncryptStream(inputStream, outputStream, publicKeyStreams, armor, withIntegrityCheck); } /// @@ -233,43 +205,34 @@ public void EncryptStream(Stream inputStream, Stream outputStream, IEnumerable Date: Wed, 28 Aug 2019 10:46:22 +0100 Subject: [PATCH 2/2] Add test for encrypting and decrypting large files. --- PgpCore.Tests/UnitTests.cs | 58 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/PgpCore.Tests/UnitTests.cs b/PgpCore.Tests/UnitTests.cs index b7916f8..4a74aec 100644 --- a/PgpCore.Tests/UnitTests.cs +++ b/PgpCore.Tests/UnitTests.cs @@ -158,6 +158,26 @@ public void DecryptFile_DecryptEncryptedFile(KeyType keyType) Teardown(); } + //[Theory] + //[InlineData(KeyType.Generated, FileType.GeneratedLarge)] + //public void DecryptLargeFile_DecryptEncryptedFile(KeyType keyType, FileType fileType) + //{ + // // Arrange + // Arrange(keyType, fileType); + // PGP pgp = new PGP(); + + // // Act + // pgp.EncryptFile(contentFilePath, encryptedContentFilePath, publicKeyFilePath1); + // pgp.DecryptFile(encryptedContentFilePath, decryptedContentFilePath1, privateKeyFilePath1, password1); + + // // Assert + // Assert.True(File.Exists(encryptedContentFilePath)); + // Assert.True(File.Exists(decryptedContentFilePath1)); + + // // Teardown + // Teardown(); + //} + [Theory] [InlineData(KeyType.Generated)] [InlineData(KeyType.Known)] @@ -826,7 +846,7 @@ public void Verify_DoNotVerifySignedStream(KeyType keyType) } #endregion Stream - private void Arrange(KeyType keyType) + private void Arrange(KeyType keyType, FileType fileType = FileType.Known) { Directory.CreateDirectory(keyDirectory); Directory.CreateDirectory(contentDirectory); @@ -884,9 +904,35 @@ private void Arrange(KeyType keyType) } // Create content file - using (StreamWriter streamWriter = File.CreateText(contentFilePath)) + if (fileType == FileType.Known) + { + using (StreamWriter streamWriter = File.CreateText(contentFilePath)) + { + streamWriter.WriteLine(content); + } + } + else if (fileType == FileType.GeneratedLarge) + { + CreateRandomFile(contentFilePath, 7000); + } + } + + private void CreateRandomFile(string filePath, int sizeInMb) + { + // Note: block size must be a factor of 1MB to avoid rounding errors + const int blockSize = 1024 * 8; + const int blocksPerMb = (1024 * 1024) / blockSize; + + byte[] data = new byte[blockSize]; + Random rng = new Random(); + using (FileStream stream = File.OpenWrite(filePath)) { - streamWriter.WriteLine(content); + // There + for (int i = 0; i < sizeInMb * blocksPerMb; i++) + { + rng.NextBytes(data); + stream.Write(data, 0, data.Length); + } } } @@ -957,6 +1003,12 @@ public enum KeyType KnownGpg } + public enum FileType + { + GeneratedLarge, + Known + } + // Content const string contentDirectory = "./Content/"; const string content = "The quick brown fox jumps over the lazy dog";