Skip to content

Commit

Permalink
Merge pull request #97 from mattosaurus/development
Browse files Browse the repository at this point in the history
Refactor
  • Loading branch information
mattosaurus authored Oct 16, 2020
2 parents 3d7b7eb + 2fdec6a commit 8d9f0bd
Show file tree
Hide file tree
Showing 15 changed files with 817 additions and 480 deletions.
12 changes: 12 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2.1

orbs:
win: circleci/[email protected]

jobs:
build:
executor: win/default

steps:
- checkout
- run: dotnet build
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -258,4 +258,5 @@ paket-files/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
*.pyc
.vscode/
2 changes: 1 addition & 1 deletion PgpCore.Tests/PgpCore.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>

<IsPackable>false</IsPackable>
</PropertyGroup>
Expand Down
11 changes: 11 additions & 0 deletions PgpCore.Tests/UnitTests/UnitTestsAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ namespace PgpCore.Tests
{
public class UnitTestsAsync
{
private static class File
{
public static FileStream Create(string path) => System.IO.File.Create(path);
public static bool Exists(string path) => System.IO.File.Exists(path);
#if NETFRAMEWORK
public static Task<string> ReadAllTextAsync(string path) => Task.FromResult(System.IO.File.ReadAllText(path));
#else
public static Task<string> ReadAllTextAsync(string path) => System.IO.File.ReadAllTextAsync(path);
#endif
}

[Fact]
public async Task GenerateKeyAsync_CreatePublicPrivateKeyFiles()
{
Expand Down
26 changes: 26 additions & 0 deletions PgpCore.Tests/UnitTests/UnitTestsSync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Xunit;
Expand Down Expand Up @@ -673,6 +674,31 @@ public void SignStream_CreateSignedFile(KeyType keyType)
testFactory.Teardown();
}

[Theory]
[InlineData(KeyType.Generated)]
[InlineData(KeyType.Known)]
[InlineData(KeyType.KnownGpg)]
public void SignStream_CreateSigned_File_From_String(KeyType keyType)
{
// Arrange
TestFactory testFactory = new TestFactory();
testFactory.Arrange(keyType);
PGP pgp = new PGP();

// Act
byte[] byteArray = Encoding.ASCII.GetBytes("The quick brown fox jumps over the lazy dog");
using (Stream inputFileStream = new MemoryStream(byteArray))
using (Stream outputFileStream = File.Create(testFactory.EncryptedContentFilePath))
using (Stream privateKeyStream = new FileStream(testFactory.PrivateKeyFilePath, FileMode.Open))
pgp.SignStream(inputFileStream, outputFileStream, privateKeyStream, testFactory.Password);

// Assert
Assert.True(File.Exists(testFactory.EncryptedContentFilePath));

// Teardown
testFactory.Teardown();
}

[Theory]
[InlineData(KeyType.Generated)]
[InlineData(KeyType.Known)]
Expand Down
125 changes: 105 additions & 20 deletions PgpCore/EncryptionKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,28 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;

namespace PgpCore
{
internal sealed class EncryptionKeys
public class EncryptionKeys : IEncryptionKeys
{
#region Instance Members (Public)

public PgpPublicKey PublicKey { get; private set; }
public PgpPublicKey PublicKey => PublicKeys.FirstOrDefault();
public IEnumerable<PgpPublicKey> PublicKeys { get; private set; }
public PgpPrivateKey PrivateKey { get; private set; }
public PgpSecretKey SecretKey { get; private set; }
public PgpSecretKeyRingBundle SecretKeys { get; private set; }

#endregion Instance Members (Public)

#region Instance Members (Private)
private readonly string _passPhrase;

#endregion Instance Members (Private)

#region Constructors

/// <summary>
Expand All @@ -44,23 +50,24 @@ public EncryptionKeys(string publicKeyFilePath, string privateKeyFilePath, strin
if (!File.Exists(privateKeyFilePath))
throw new FileNotFoundException(String.Format("Private Key file [{0}] does not exist.", privateKeyFilePath));

PublicKey = Utilities.ReadPublicKey(publicKeyFilePath);
PublicKeys = new List<PgpPublicKey>() { Utilities.ReadPublicKey(publicKeyFilePath) };
SecretKey = ReadSecretKey(privateKeyFilePath);
PrivateKey = ReadPrivateKey(passPhrase);
_passPhrase = 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.
/// Two or more keys are required to encrypt and sign data. Your private key and the recipients public key(s).
/// The data is encrypted with the recipients public key(s) and signed with your private key.
/// </summary>
/// <param name="publicKeyFilePath">The key used to encrypt the data</param>
/// <param name="publicKeyFilePaths">The key(s) 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'
// Avoid multiple enumerations of 'publicKeyFilePaths'
string[] publicKeys = publicKeyFilePaths.ToArray();

if (String.IsNullOrEmpty(privateKeyFilePath))
Expand All @@ -82,6 +89,7 @@ public EncryptionKeys(IEnumerable<string> publicKeyFilePaths, string privateKeyF
PublicKeys = publicKeys.Select(x => Utilities.ReadPublicKey(x)).ToList();
SecretKey = ReadSecretKey(privateKeyFilePath);
PrivateKey = ReadPrivateKey(passPhrase);
_passPhrase = passPhrase;
}

public EncryptionKeys(string privateKeyFilePath, string passPhrase)
Expand All @@ -97,6 +105,7 @@ public EncryptionKeys(string privateKeyFilePath, string passPhrase)
PublicKeys = null;
SecretKey = ReadSecretKey(privateKeyFilePath);
PrivateKey = ReadPrivateKey(passPhrase);
_passPhrase = passPhrase;
}

public EncryptionKeys(Stream publicKeyStream, Stream privateKeyStream, string passPhrase)
Expand All @@ -108,9 +117,10 @@ public EncryptionKeys(Stream publicKeyStream, Stream privateKeyStream, string pa
if (passPhrase == null)
throw new ArgumentNullException("Invalid Pass Phrase.");

PublicKey = Utilities.ReadPublicKey(publicKeyStream);
PublicKeys = new List<PgpPublicKey>() { Utilities.ReadPublicKey(publicKeyStream) };
SecretKey = ReadSecretKey(privateKeyStream);
PrivateKey = ReadPrivateKey(passPhrase);
_passPhrase = passPhrase;
}

public EncryptionKeys(Stream privateKeyStream, string passPhrase)
Expand All @@ -120,14 +130,14 @@ public EncryptionKeys(Stream privateKeyStream, string passPhrase)
if (passPhrase == null)
throw new ArgumentNullException("Invalid Pass Phrase.");

PublicKey = null;
SecretKey = ReadSecretKey(privateKeyStream);
PrivateKey = ReadPrivateKey(passPhrase);
_passPhrase = passPhrase;
}

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

if (privateKeyStream == null)
Expand All @@ -143,23 +153,98 @@ public EncryptionKeys(IEnumerable<Stream> publicKeyStreams, Stream privateKeyStr
PublicKeys = publicKeys.Select(x => Utilities.ReadPublicKey(x)).ToList();
SecretKey = ReadSecretKey(privateKeyStream);
PrivateKey = ReadPrivateKey(passPhrase);
_passPhrase = 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>
/// <exception cref="ArgumentException">Public key not found. Private key not found. Missing password</exception>
public EncryptionKeys(string publicKeyFilePath)
{
if (String.IsNullOrEmpty(publicKeyFilePath))
throw new ArgumentException("PublicKeyFilePath");

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

PublicKeys = new List<PgpPublicKey>() { Utilities.ReadPublicKey(publicKeyFilePath) };
}

/// <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>
/// <exception cref="ArgumentException">Public key not found. Private key not found. Missing password</exception>
public EncryptionKeys(IEnumerable<string> publicKeyFilePaths)
{
// Avoid multiple enumerations of 'publicKeyFilePaths'
string[] publicKeys = publicKeyFilePaths.ToArray();

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();
}

public EncryptionKeys(Stream publicKeyStream)
{
if (publicKeyStream == null)
throw new ArgumentException("PublicKeyStream");

PublicKeys = new List<PgpPublicKey>() { Utilities.ReadPublicKey(publicKeyStream) };
}

public EncryptionKeys(IEnumerable<Stream> publicKeyStreams)
{
Stream[] publicKeys = publicKeyStreams.ToArray();

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

PublicKeys = publicKeys.Select(x => Utilities.ReadPublicKey(x)).ToList();
}

#endregion Constructors

#region Public Methods

public PgpPrivateKey FindSecretKey(long keyId)
{
PgpSecretKey pgpSecKey = SecretKeys.GetSecretKey(keyId);

if (pgpSecKey == null)
return null;

return pgpSecKey.ExtractPrivateKey(_passPhrase.ToCharArray());
}

#endregion Public Methods

#region Secret Key

private PgpSecretKey ReadSecretKey(string privateKeyPath)
{
using (Stream sr = File.OpenRead(privateKeyPath))
using (Stream inputStream = PgpUtilities.GetDecoderStream(sr))
{
using (Stream inputStream = PgpUtilities.GetDecoderStream(sr))
{
PgpSecretKeyRingBundle secretKeyRingBundle = new PgpSecretKeyRingBundle(inputStream);
PgpSecretKey foundKey = GetFirstSecretKey(secretKeyRingBundle);
if (foundKey != null)
return foundKey;
}
SecretKeys = new PgpSecretKeyRingBundle(inputStream);
PgpSecretKey foundKey = GetFirstSecretKey(SecretKeys);
if (foundKey != null)
return foundKey;
}
throw new ArgumentException("Can't find signing key in key ring.");
}
Expand All @@ -168,8 +253,8 @@ private PgpSecretKey ReadSecretKey(Stream privateKeyStream)
{
using (Stream inputStream = PgpUtilities.GetDecoderStream(privateKeyStream))
{
PgpSecretKeyRingBundle secretKeyRingBundle = new PgpSecretKeyRingBundle(inputStream);
PgpSecretKey foundKey = GetFirstSecretKey(secretKeyRingBundle);
SecretKeys = new PgpSecretKeyRingBundle(inputStream);
PgpSecretKey foundKey = GetFirstSecretKey(SecretKeys);
if (foundKey != null)
return foundKey;
}
Expand Down
22 changes: 22 additions & 0 deletions PgpCore/IEncryptionKeys.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using Org.BouncyCastle.Bcpg.OpenPgp;

namespace PgpCore
{
/// <summary>
/// Encryption Keys
///
/// You can supply any or all of these, however, if PrivateKeys
/// are required Secret keys should also be supplied
/// </summary>
public interface IEncryptionKeys
{
PgpPublicKey PublicKey { get; }
IEnumerable<PgpPublicKey> PublicKeys { get; }
PgpPrivateKey PrivateKey { get; }
PgpSecretKey SecretKey { get; }
PgpSecretKeyRingBundle SecretKeys { get; }

PgpPrivateKey FindSecretKey(long keyId);
}
}
20 changes: 20 additions & 0 deletions PgpCore/IPGPEncrypt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace PgpCore
{
public interface IPGPEncrypt : IDisposable
{
void EncryptFile(string inputFilePath, string outputFilePath, string publicKeyFilePath, bool armor, bool withIntegrityCheck, string name);

void EncryptFile(string inputFilePath, string outputFilePath, IEnumerable<string> publicKeyFilePaths, bool armor, bool withIntegrityCheck, string name);

void EncryptStream(Stream inputStream, Stream outputStream, Stream publicKeyStream, bool armor, bool withIntegrityCheck, string name);

void EncryptStream(Stream inputStream, Stream outputStream, IEnumerable<Stream> publicKeyStreams, bool armor, bool withIntegrityCheck, string name);

void Dispose();
}
}
21 changes: 21 additions & 0 deletions PgpCore/IPGPEncryptAsync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace PgpCore
{
public interface IPGPEncryptAsync : IDisposable
{
Task EncryptFileAsync(string inputFilePath, string outputFilePath, string publicKeyFilePath,
bool armor, bool withIntegrityCheck, string name);

Task EncryptStreamAsync(Stream inputStream, Stream outputStream, Stream publicKeyStream,
bool armor, bool withIntegrityCheck, string name);

Task EncryptStreamAsync(Stream inputStream, Stream outputStream, IEnumerable<Stream> publicKeyStreams,
bool armor, bool withIntegrityCheck, string name);

void Dispose();
}
}
Loading

0 comments on commit 8d9f0bd

Please sign in to comment.