Skip to content

Commit

Permalink
Merge pull request #19 from mattosaurus/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
mattosaurus authored Feb 20, 2019
2 parents 472a261 + 392adc4 commit c956e81
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 20 deletions.
56 changes: 56 additions & 0 deletions PgpCore/EncryptionKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal sealed class EncryptionKeys
#region Instance Members (Public)

public PgpPublicKey PublicKey { get; private set; }
public IEnumerable<PgpPublicKey> PublicKeys { get; private set; }
public PgpPrivateKey PrivateKey { get; private set; }
public PgpSecretKey SecretKey { get; private set; }

Expand Down Expand Up @@ -48,6 +49,41 @@ public EncryptionKeys(string publicKeyFilePath, string privateKeyFilePath, strin
PrivateKey = ReadPrivateKey(passPhrase);
}

/// <summary>
/// Initializes a new instance of the EncryptionKeys class.
/// Two keys are required to encrypt and sign data. Your private key and the recipients public key.
/// The data is encrypted with the recipients public key and signed with your private key.
/// </summary>
/// <param name="publicKeyFilePath">The key used to encrypt the data</param>
/// <param name="privateKeyFilePath">The key used to sign the data.</param>
/// <param name="passPhrase">The password required to access the private key</param>
/// <exception cref="ArgumentException">Public key not found. Private key not found. Missing password</exception>
public EncryptionKeys(IEnumerable<string> publicKeyFilePaths, string privateKeyFilePath, string passPhrase)
{
//Avoid multiple enumerations of 'publicKeyFilePaths'
string[] publicKeys = publicKeyFilePaths.ToArray();

if (String.IsNullOrEmpty(privateKeyFilePath))
throw new ArgumentException("PrivateKeyFilePath");
if (passPhrase == null)
throw new ArgumentNullException("Invalid Pass Phrase.");

if (!File.Exists(privateKeyFilePath))
throw new FileNotFoundException(String.Format("Private Key file [{0}] does not exist.", privateKeyFilePath));

foreach (string publicKeyFilePath in publicKeys)
{
if (String.IsNullOrEmpty(publicKeyFilePath))
throw new ArgumentException(nameof(publicKeyFilePath));
if (!File.Exists(publicKeyFilePath))
throw new FileNotFoundException(String.Format("Input file [{0}] does not exist.", publicKeyFilePath));
}

PublicKeys = publicKeys.Select(x => Utilities.ReadPublicKey(x)).ToList();
SecretKey = ReadSecretKey(privateKeyFilePath);
PrivateKey = ReadPrivateKey(passPhrase);
}

public EncryptionKeys(Stream publicKeyStream, Stream privateKeyStream, string passPhrase)
{
if (publicKeyStream == null)
Expand All @@ -62,6 +98,26 @@ public EncryptionKeys(Stream publicKeyStream, Stream privateKeyStream, string pa
PrivateKey = ReadPrivateKey(passPhrase);
}

public EncryptionKeys(IEnumerable<Stream> publicKeyStreams, Stream privateKeyStream, string passPhrase)
{
//Avoid multiple enumerations of 'publicKeyFilePaths'
Stream[] publicKeys = publicKeyStreams.ToArray();

if (privateKeyStream == null)
throw new ArgumentException("PrivateKeyStream");
if (passPhrase == null)
throw new ArgumentNullException("Invalid Pass Phrase.");
foreach (Stream publicKey in publicKeys)
{
if (publicKey == null)
throw new ArgumentException("PublicKeyStream");
}

PublicKeys = publicKeys.Select(x => Utilities.ReadPublicKey(x)).ToList();
SecretKey = ReadSecretKey(privateKeyStream);
PrivateKey = ReadPrivateKey(passPhrase);
}

#endregion Constructors

#region Secret Key
Expand Down
137 changes: 120 additions & 17 deletions PgpCore/PGP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,24 @@ public async Task EncryptFileAsync(string inputFilePath, string outputFilePath,
await Task.Run(() => EncryptFile(inputFilePath, outputFilePath, publicKeyFilePath, armor, withIntegrityCheck));
}

public async Task EncryptFileAsync(string inputFilePath, string outputFilePath, IEnumerable<string> publicKeyFilePaths,
bool armor = true, bool withIntegrityCheck = true)
{
await Task.Run(() => EncryptFile(inputFilePath, outputFilePath, publicKeyFilePaths, armor, withIntegrityCheck));
}

public async Task EncryptStreamAsync(Stream inputStream, Stream outputStream, Stream publicKeyStream,
bool armor = true, bool withIntegrityCheck = true)
{
await Task.Run(() => EncryptStream(inputStream, outputStream, publicKeyStream, armor, withIntegrityCheck));
}

public async Task EncryptStreamAsync(Stream inputStream, Stream outputStream, IEnumerable<Stream> publicKeyStreams,
bool armor = true, bool withIntegrityCheck = true)
{
await Task.Run(() => EncryptStream(inputStream, outputStream, publicKeyStreams, armor, withIntegrityCheck));
}

/// <summary>
/// PGP Encrypt the file.
/// </summary>
Expand Down Expand Up @@ -180,23 +192,46 @@ public void EncryptFile(
}
}

/// <summary>
/// PGP Encrypt the stream.
/// </summary>
/// <param name="inputFilePath"></param>
/// <param name="outputFilePath"></param>
/// <param name="publicKeyFilePath"></param>
/// <param name="armor"></param>
/// <param name="withIntegrityCheck"></param>
public void EncryptStream(
Stream inputStream,
Stream outputStream,
Stream publicKeyStream,
bool armor = true,
bool withIntegrityCheck = true)
{
EncryptStream(inputStream, outputStream, new[] { publicKeyStream }, armor, withIntegrityCheck);
}

/// <summary>
/// PGP Encrypt the stream.
/// </summary>
/// <param name="inputStream"></param>
/// <param name="outputStream"></param>
/// <param name="publicKeyFilePath"></param>
/// <param name="publicKeyFilePaths"></param>
/// <param name="armor"></param>
/// <param name="withIntegrityCheck"></param>
public void EncryptStream(Stream inputStream, Stream outputStream, Stream publicKeyStream, bool armor = true, bool withIntegrityCheck = true)
public void EncryptStream(Stream inputStream, Stream outputStream, IEnumerable<Stream> publicKeyStreams, bool armor = true, bool withIntegrityCheck = true)
{
//Avoid multiple enumerations of 'publicKeyFilePaths'
Stream[] publicKeys = publicKeyStreams.ToArray();

if (inputStream == null)
throw new ArgumentException("InputStream");
if (outputStream == null)
throw new ArgumentException("OutputStream");
if (publicKeyStream == null)
throw new ArgumentException("PublicKeyStream");

foreach (Stream publicKey in publicKeys)
{
if (publicKey == null)
throw new ArgumentException("PublicKeyStream");
}

using (MemoryStream @out = new MemoryStream())
{
Expand All @@ -210,7 +245,11 @@ public void EncryptStream(Stream inputStream, Stream outputStream, Stream public
Utilities.WriteStreamToLiteralData(@out, FileTypeToChar(), inputStream, "name");

PgpEncryptedDataGenerator pk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithm, withIntegrityCheck, new SecureRandom());
pk.AddMethod(Utilities.ReadPublicKey(publicKeyStream));

foreach (Stream publicKey in publicKeys)
{
pk.AddMethod(Utilities.ReadPublicKey(publicKey));
}

byte[] bytes = @out.ToArray();

Expand Down Expand Up @@ -244,11 +283,22 @@ public async Task EncryptFileAndSignAsync(string inputFilePath, string outputFil
await Task.Run(() => EncryptFileAndSign(inputFilePath, outputFilePath, publicKeyFilePath, privateKeyFilePath, passPhrase, armor, withIntegrityCheck));
}

public async Task EncryptFileAndSignAsync(string inputFilePath, string outputFilePath, IEnumerable<string> publicKeyFilePaths, string privateKeyFilePath,
string passPhrase, bool armor = true, bool withIntegrityCheck = true)
{
await Task.Run(() => EncryptFileAndSign(inputFilePath, outputFilePath, publicKeyFilePaths, privateKeyFilePath, passPhrase, armor, withIntegrityCheck));
}

public async Task EncryptStreamAndSignAsync(Stream inputStream, Stream outputStream, Stream publicKeyStream, Stream privateKeyStream, string passPhrase, bool armor = true, bool withIntegrityCheck = true)
{
await Task.Run(() => EncryptStreamAndSign(inputStream, outputStream, publicKeyStream, privateKeyStream, passPhrase, armor, withIntegrityCheck));
}

public async Task EncryptStreamAndSignAsync(Stream inputStream, Stream outputStream, IEnumerable<Stream> publicKeyStreams, Stream privateKeyStream, string passPhrase, bool armor = true, bool withIntegrityCheck = true)
{
await Task.Run(() => EncryptStreamAndSign(inputStream, outputStream, publicKeyStreams, privateKeyStream, passPhrase, armor, withIntegrityCheck));
}

/// <summary>
/// Encrypt and sign the file pointed to by unencryptedFileInfo and
/// </summary>
Expand All @@ -261,25 +311,47 @@ public async Task EncryptStreamAndSignAsync(Stream inputStream, Stream outputStr
public void EncryptFileAndSign(string inputFilePath, string outputFilePath, string publicKeyFilePath,
string privateKeyFilePath, string passPhrase, bool armor = true, bool withIntegrityCheck = true)
{
EncryptFileAndSign(inputFilePath, outputFilePath, new[] { publicKeyFilePath }, privateKeyFilePath, passPhrase, armor, withIntegrityCheck);
}

/// <summary>
/// Encrypt and sign the file pointed to by unencryptedFileInfo and
/// </summary>
/// <param name="inputFilePath"></param>
/// <param name="outputFilePath"></param>
/// <param name="publicKeyFilePath"></param>
/// <param name="privateKeyFilePath"></param>
/// <param name="passPhrase"></param>
/// <param name="armor"></param>
public void EncryptFileAndSign(string inputFilePath, string outputFilePath, IEnumerable<string> publicKeyFilePaths,
string privateKeyFilePath, string passPhrase, bool armor = true, bool withIntegrityCheck = true)
{
//Avoid multiple enumerations of 'publicKeyFilePaths'
string[] publicKeys = publicKeyFilePaths.ToArray();

if (String.IsNullOrEmpty(inputFilePath))
throw new ArgumentException("InputFilePath");
if (String.IsNullOrEmpty(outputFilePath))
throw new ArgumentException("OutputFilePath");
if (String.IsNullOrEmpty(publicKeyFilePath))
throw new ArgumentException("PublicKeyFilePath");
if (String.IsNullOrEmpty(privateKeyFilePath))
throw new ArgumentException("PrivateKeyFilePath");
if (passPhrase == null)
passPhrase = String.Empty;

if (!File.Exists(inputFilePath))
throw new FileNotFoundException(String.Format("Input file [{0}] does not exist.", inputFilePath));
if (!File.Exists(publicKeyFilePath))
throw new FileNotFoundException(String.Format("Public Key file [{0}] does not exist.", publicKeyFilePath));
if (!File.Exists(privateKeyFilePath))
throw new FileNotFoundException(String.Format("Private Key file [{0}] does not exist.", privateKeyFilePath));

EncryptionKeys encryptionKeys = new EncryptionKeys(publicKeyFilePath, privateKeyFilePath, passPhrase);
foreach (string publicKeyFilePath in publicKeys)
{
if (String.IsNullOrEmpty(publicKeyFilePath))
throw new ArgumentException(nameof(publicKeyFilePath));
if (!File.Exists(publicKeyFilePath))
throw new FileNotFoundException(String.Format("Input file [{0}] does not exist.", publicKeyFilePath));
}

EncryptionKeys encryptionKeys = new EncryptionKeys(publicKeyFilePaths, privateKeyFilePath, passPhrase);

if (encryptionKeys == null)
throw new ArgumentNullException("Encryption Key not found.");
Expand All @@ -303,25 +375,44 @@ public void EncryptFileAndSign(string inputFilePath, string outputFilePath, stri
/// </summary>
/// <param name="inputStream"></param>
/// <param name="outputStream"></param>
/// <param name="publicKeyFilePath"></param>
/// <param name="privateKeyFilePath"></param>
/// <param name="publicKeyStream"></param>
/// <param name="privateKeyStream"></param>
/// <param name="passPhrase"></param>
/// <param name="armor"></param>
public void EncryptStreamAndSign(Stream inputStream, Stream outputStream, Stream publicKeyStream,
Stream privateKeyStream, string passPhrase, bool armor = true, bool withIntegrityCheck = true)
{
EncryptStreamAndSign(inputStream, outputStream, new[] { publicKeyStream }, privateKeyStream, passPhrase, armor, withIntegrityCheck);
}

/// <summary>
/// Encrypt and sign the stream pointed to by unencryptedFileInfo and
/// </summary>
/// <param name="inputStream"></param>
/// <param name="outputStream"></param>
/// <param name="publicKeyStream"></param>
/// <param name="privateKeyStream"></param>
/// <param name="passPhrase"></param>
/// <param name="armor"></param>
public void EncryptStreamAndSign(Stream inputStream, Stream outputStream, IEnumerable<Stream> publicKeyStreams,
Stream privateKeyStream, string passPhrase, bool armor = true, bool withIntegrityCheck = true)
{
if (inputStream == null)
throw new ArgumentException("InputStream");
if (outputStream == null)
throw new ArgumentException("OutputStream");
if (publicKeyStream == null)
throw new ArgumentException("PublicKeyStream");
if (privateKeyStream == null)
throw new ArgumentException("PrivateKeyStream");
if (passPhrase == null)
passPhrase = String.Empty;

EncryptionKeys encryptionKeys = new EncryptionKeys(publicKeyStream, privateKeyStream, passPhrase);
foreach (Stream publicKey in publicKeyStreams)
{
if (publicKey == null)
throw new ArgumentException("PublicKeyStream");
}

EncryptionKeys encryptionKeys = new EncryptionKeys(publicKeyStreams, privateKeyStream, passPhrase);

if (encryptionKeys == null)
throw new ArgumentNullException("Encryption Key not found.");
Expand Down Expand Up @@ -401,7 +492,19 @@ private Stream ChainEncryptedOut(Stream outputStream, EncryptionKeys encryptionK
{
PgpEncryptedDataGenerator encryptedDataGenerator;
encryptedDataGenerator = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithm, withIntegrityCheck, new SecureRandom());
encryptedDataGenerator.AddMethod(encryptionKeys.PublicKey);

if (encryptionKeys.PublicKey != null)
{
encryptedDataGenerator.AddMethod(encryptionKeys.PublicKey);
}
else if (encryptionKeys.PublicKeys != null)
{
foreach (PgpPublicKey publicKey in encryptionKeys.PublicKeys)
{
encryptedDataGenerator.AddMethod(publicKey);
}
}

return encryptedDataGenerator.Open(outputStream, new byte[BufferSize]);
}

Expand Down
6 changes: 3 additions & 3 deletions PgpCore/PgpCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
<RepositoryUrl>https://github.com/mattosaurus/PgpCore</RepositoryUrl>
<PackageTags>PGP .NET Core</PackageTags>
<Version>1.3.1</Version>
<AssemblyVersion>1.3.1.0</AssemblyVersion>
<FileVersion>1.3.1.0</FileVersion>
<PackageReleaseNotes>ReadPublicKey moved to Utilities</PackageReleaseNotes>
<AssemblyVersion>1.4.0.0</AssemblyVersion>
<FileVersion>1.4.0.0</FileVersion>
<PackageReleaseNotes>Allow encrypt and sign with multiple keys</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
Expand Down
26 changes: 26 additions & 0 deletions PgpCoreTest/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using PgpCore;
using System;
using System.IO;
using System.Text;

namespace PgpCoreTest
{
Expand All @@ -20,13 +21,18 @@ static void Main(string[] args)
pgp.EncryptFile(@"C:\TEMP\keys\content.txt", @"C:\TEMP\keys\content__encrypted_multiple.pgp", publicKeys, true, true);
// Encrypt and sign file
pgp.EncryptFileAndSign(@"C:\TEMP\keys\content.txt", @"C:\TEMP\keys\content__encrypted_signed.pgp", @"C:\TEMP\keys\public.asc", @"C:\TEMP\keys\private.asc", "password", true, true);
// Encrypt and sign multiple file
pgp.EncryptFileAndSign(@"C:\TEMP\keys\content.txt", @"C:\TEMP\keys\content__encrypted_signed_multiple.pgp", publicKeys, @"C:\TEMP\keys\private.asc", "password", true, true);
// Decrypt file
pgp.DecryptFile(@"C:\TEMP\keys\content__encrypted.pgp", @"C:\TEMP\keys\content__decrypted.txt", @"C:\TEMP\keys\private.asc", "password");
// Decrypt multiple file
pgp.DecryptFile(@"C:\TEMP\keys\content__encrypted_multiple.pgp", @"C:\TEMP\keys\content__decrypted_multiple.txt", @"C:\TEMP\keys\private.asc", "password");
pgp.DecryptFile(@"C:\TEMP\keys\content__encrypted_multiple.pgp", @"C:\TEMP\keys\content__decrypted_multiple2.txt", @"C:\TEMP\keys\private2.asc", "password2");
// Decrypt signed file
pgp.DecryptFile(@"C:\TEMP\keys\content__encrypted_signed.pgp", @"C:\TEMP\keys\content__decrypted_signed.txt", @"C:\TEMP\keys\private.asc", "password");
// Decrypt signed multiple file
pgp.DecryptFile(@"C:\TEMP\keys\content__encrypted_signed_multiple.pgp", @"C:\TEMP\keys\content__decrypted_signed_multiple.txt", @"C:\TEMP\keys\private.asc", "password");
pgp.DecryptFile(@"C:\TEMP\keys\content__encrypted_signed_multiple.pgp", @"C:\TEMP\keys\content__decrypted_signed_multiple2.txt", @"C:\TEMP\keys\private2.asc", "password2");

// Encrypt stream
using (FileStream inputFileStream = new FileStream(@"C:\TEMP\keys\content.txt", FileMode.Open))
Expand Down Expand Up @@ -73,6 +79,26 @@ static void Main(string[] args)
}
}
}

// Encrypt key and sign stream
using (Stream inputFileStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("Streaming signed test message")))
{
using (Stream publicKeyStream = new FileStream(@"C:\TEMP\keys\public.asc", FileMode.Open))
{
using (Stream privateKeyStream = new FileStream(@"C:\TEMP\keys\private.asc", FileMode.Open))
{
using (Stream encryptedMemoryStream = new MemoryStream())
{
pgp.EncryptStreamAndSign(inputFileStream, encryptedMemoryStream, publicKeyStream, privateKeyStream, "password");
// Reset stream to beginning
encryptedMemoryStream.Seek(0, SeekOrigin.Begin);
StreamReader encryptedReader = new StreamReader(encryptedMemoryStream);
string encryptedText = encryptedReader.ReadToEnd();
Console.WriteLine(encryptedText);
}
}
}
}
}
}
}
Expand Down

0 comments on commit c956e81

Please sign in to comment.