This repository has been archived by the owner on Mar 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add Initial project Motivations ---- Create an initial project for an easy to use and maintain Cryptography library Modifications ---- * Initial Cryptography related services for dependency injection, encryption, decryption, signing, and verifying signatures * Initial Security Keys: * Rsa * Aes * Unit Tests * github workflows Result ---- Open source Cryptography library with easy to use interfaces and Security keys and maintainability * workflow adjustmemts * more * more * Update publishPackage * concurrency * Typos.. * Remove unnecessary test
- Loading branch information
1 parent
0ba6836
commit 00cc736
Showing
47 changed files
with
2,080 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: .NET CD Automation | ||
|
||
on: | ||
push: | ||
branches: [ main ] | ||
pull_request: | ||
branches: [ main ] | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
|
||
build: | ||
runs-on: windows-latest | ||
strategy: | ||
matrix: | ||
dotnet-version: [ '6.0.x' ] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Setup .NET Core SDK ${{ matrix.dotnet-version }} | ||
uses: actions/[email protected] | ||
with: | ||
dotnet-version: ${{ matrix.dotnet-version }} | ||
- name: Restore dependencies | ||
run: >- | ||
dotnet restore ./src/${{ github.event.repository.name }}.sln | ||
- name: Build | ||
run: dotnet build --no-restore ./src/${{ github.event.repository.name }}.sln | ||
- name: Test | ||
run: dotnet test --no-build --verbosity normal ./src/${{ github.event.repository.name }}.sln |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: Upload dotnet package | ||
|
||
on: | ||
workflow_dispatch: | ||
release: | ||
types: [created] | ||
|
||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
packages: write | ||
contents: read | ||
steps: | ||
- name: Get the version | ||
id: get_version | ||
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-dotnet@v1 | ||
with: | ||
dotnet-version: '6.0.x' # SDK Version to use. | ||
env: | ||
NUGET_AUTH_TOKEN: ${{secrets.NUGET_TOKEN}} | ||
- run: dotnet build --configuration Release ./src /p:Version=${{ steps.get_version.outputs.VERSION }} | ||
- name: Create the package | ||
run: dotnet pack --configuration Release ./src -o . /p:Version=${{ steps.get_version.outputs.VERSION }} | ||
- name: Publish the package to GPR | ||
run: dotnet nuget push ./*.nupkg --api-key ${{secrets.NUGET_TOKEN}} --source https://api.nuget.org/v3/index.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,35 @@ | ||
# Common.Security.Cryptography | ||
Easy to use Cryptography | ||
----- | ||
Cryptography should be easy to use and access and provide this capability in a way that is extensible and updatable. Rather than needing to handle and manage resources around the various cryptography implementations, this library provides an alternative to the normal patterns for using cryptographic functions and allows the use of the async/await and dependency injection patterns. | ||
|
||
# Security Keys | ||
----- | ||
A `security key` is an entity that is able to provide the requirements of encyption, decryption, signing, and validating signatures. These are backed by strong cryptographic functions such as AES, RSA, and others. | ||
|
||
The security key domain is made up of subdomains of many types of security key. Each subdomain will include the following objects and entities: | ||
|
||
`Models`: | ||
* KeyGenerationParameters | ||
* KeyExchangeInformation | ||
* KeyInformation | ||
|
||
`Services`: | ||
* SecurityKeyGenerator | ||
* SecurityKey | ||
|
||
`Dependency Injection`: | ||
* SecurityKeyDescriptor | ||
|
||
The model objects are used by the `SecurityKeyDescriptor`, `ISecurityKeyProvider`, and `SecurityKeyGenerator` to create the security through the points of entry into the library. They act as the gatway to the subdomain and allows the subdomain to be implemented as needed without adding major complexity to the base library. Additionally, generator and allows for clear separation of any necessary initialization tasks from the underlying security key itself. | ||
|
||
`KeyInformation` is the central data component that allows the security key to operate, containing the necessary data to construct the key. `KeyExchangeInformation` is the publicly transmittable data that can be sent across the network and then used to reconstruct the required security key on the partner's connection. This provides the ease of use for a consumer of the library by not needing to know what data can/can not be transmitted for secure data transmission. | ||
|
||
Additionally, this design should allow the ease of creating and experimenting with new cryptographic algorithms by allowing a simple set of core interfaces and parent models to integrate new security keys into the library for other projects, without needing updates to the main repository -- though updates to strong cryptographic functions or security enhancements to the library in general are welcome! | ||
|
||
# Cryptography | ||
---- | ||
The main point of entry into the APIs is via the `ICryptographyService`. In this way, the usage of a broad number of different cryptographic algorithms and related hash functions can be consolidated to one place, providing ease of access. Simply providing the necessary model parameters will generate a usable key for cryptographic purposes. All that should be required to construct the desired security key is simply the parameters desired for the function to operate. | ||
|
||
# Contributions | ||
---- | ||
Cryptography and data security are important for network and other data management. Feel free to create issues and updates to the library to help it grow and gain access to further security keys. |
22 changes: 22 additions & 0 deletions
22
src/Common.Security.Cryptography.UnitTests/Common.Security.Cryptography.UnitTests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.1" /> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" /> | ||
<PackageReference Include="xunit" Version="2.4.2" /> | ||
<PackageReference Include="Moq" Version="4.18.4" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> | ||
<PrivateAssets>all</PrivateAssets> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Common.Security.Cryptography\Common.Security.Cryptography.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
47 changes: 47 additions & 0 deletions
47
src/Common.Security.Cryptography.UnitTests/IntegrationTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
using Common.Security.Cryptography.Keys.Rsa.Models; | ||
using Common.Security.Cryptography.Ports; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System.Linq; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
namespace Common.Security.Cryptography.UnitTests | ||
{ | ||
public class IntegrationTests | ||
{ | ||
#region End to End | ||
|
||
[Fact] | ||
public async Task EndToEnd_Testing() | ||
{ | ||
var serviceCollection = new ServiceCollection(); | ||
serviceCollection.AddCryptography(); | ||
var serviceProvider = serviceCollection.BuildServiceProvider(); | ||
|
||
var cryptographyService = serviceProvider.GetRequiredService<ICryptographyService>(); | ||
var personalKey = cryptographyService.CreateKey(1024, new RsaKeyGenerationParameters()); | ||
var otherKey = cryptographyService.CreateKey(1024, new RsaKeyGenerationParameters()); | ||
|
||
var personalExchangeKeyInformation = personalKey.KeyInformation.GetKeyExhangeInformation() as RsaKeyExchangeInformation; | ||
var otherExchangeKeyInformation = otherKey.KeyInformation.GetKeyExhangeInformation() as RsaKeyExchangeInformation; | ||
|
||
var personalExchangeKey = cryptographyService.CreateKey(personalKey.KeyInformation.RawKey, otherExchangeKeyInformation); | ||
var otherExchangeKey = cryptographyService.CreateKey(otherKey.KeyInformation.RawKey, personalExchangeKeyInformation); | ||
|
||
var text = "Hello world, to a new wonderful day!"; | ||
var bytes = Encoding.UTF8.GetBytes(text); | ||
var message = await cryptographyService.SignAndEncryptMessageAsync(bytes, personalExchangeKey, HashAlgorithmName.SHA1); | ||
|
||
Assert.False(bytes.SequenceEqual(message.EncryptedData)); | ||
|
||
var decrypted = await cryptographyService.ValidateAndDecryptMessageAsync(message, otherExchangeKey, HashAlgorithmName.SHA1); | ||
var decryptedText = Encoding.UTF8.GetString(decrypted); | ||
|
||
Assert.Equal(text, decryptedText); | ||
} | ||
|
||
#endregion | ||
} | ||
} |
195 changes: 195 additions & 0 deletions
195
src/Common.Security.Cryptography.UnitTests/Internal/Services/CryptographyServiceTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
using Common.Security.Cryptography.Exceptions; | ||
using Common.Security.Cryptography.Internal.Services; | ||
using Common.Security.Cryptography.Model; | ||
using Common.Security.Cryptography.Ports; | ||
using Common.Security.Cryptography.UnitTests.TestData; | ||
using Moq; | ||
using System; | ||
using System.Linq; | ||
using System.Security.Cryptography; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
namespace Common.Security.Cryptography.UnitTests.Internal.Services | ||
{ | ||
public class CryptographyServiceTests | ||
{ | ||
#region Variables | ||
|
||
private readonly Mock<ISecurityKeyProvider> _mockSecurityKeyProvider; | ||
|
||
private readonly CryptographyService _cryptographyService; | ||
|
||
#endregion | ||
|
||
#region Constructors | ||
|
||
public CryptographyServiceTests() | ||
{ | ||
_mockSecurityKeyProvider = new Mock<ISecurityKeyProvider>(); | ||
|
||
_cryptographyService = new CryptographyService(_mockSecurityKeyProvider.Object); | ||
} | ||
|
||
#endregion | ||
|
||
#region CreateKey (int, KeyGenerationParameters) | ||
|
||
[Fact] | ||
public void Create_KeyGenerationParameters_ReturnsSecurityKey() | ||
{ | ||
// Arrange | ||
var mockKey = new Mock<ISecurityKey>(); | ||
_mockSecurityKeyProvider.Setup(m => m.GetNew(It.IsAny<int>(), It.IsAny<SecurityKeyGenerationParameters>())) | ||
.Returns(mockKey.Object); | ||
|
||
// Act | ||
var key = _cryptographyService.CreateKey(1, new TestGenerationParameters()); | ||
|
||
// Assert | ||
Assert.Equal(mockKey.Object, key); | ||
} | ||
|
||
#endregion | ||
|
||
#region CreateKey (byte[], SecurityKeyExchangeInformation) | ||
|
||
[Fact] | ||
public void Create_KeyExchangeInformation_ReturnsSecurityKey() | ||
{ | ||
// Arrange | ||
var mockKey = new Mock<ISecurityKey>(); | ||
_mockSecurityKeyProvider.Setup(m => m.GetFrom(It.IsAny<byte[]>(), It.IsAny<SecurityKeyExchangeInformation>())) | ||
.Returns(mockKey.Object); | ||
|
||
// Act | ||
var key = _cryptographyService.CreateKey(new byte[0], new TestKeyExchangeInformation()); | ||
|
||
// Assert | ||
Assert.Equal(mockKey.Object, key); | ||
} | ||
|
||
#endregion | ||
|
||
#region CreateKey (KeyInformation) | ||
|
||
[Fact] | ||
public void Create_KeyInformation_ReturnsSecurityKey() | ||
{ | ||
// Arrange | ||
var mockKey = new Mock<ISecurityKey>(); | ||
_mockSecurityKeyProvider.Setup(m => m.GetFrom(It.IsAny<SecurityKeyInformation>())) | ||
.Returns(mockKey.Object); | ||
|
||
// Act | ||
var key = _cryptographyService.CreateKey(new TestKeyInformation()); | ||
|
||
// Assert | ||
Assert.Equal(mockKey.Object, key); | ||
} | ||
|
||
#endregion | ||
|
||
#region SignAndEncryptMessageAsync | ||
|
||
[Fact] | ||
public async Task SignAndEncryptMessageAsync_NullData_ThrowsArgumentNullException() | ||
{ | ||
// Arrange/Act/Assert | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => _cryptographyService.SignAndEncryptMessageAsync(null, new Mock<ISecurityKey>().Object, HashAlgorithmName.MD5)); | ||
} | ||
|
||
[Fact] | ||
public async Task SignAndEncryptMessageAsync_NullSecurityKey_ThrowsArgumentNullException() | ||
{ | ||
// Arrange/Act/Assert | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => _cryptographyService.SignAndEncryptMessageAsync(new byte[0], null, HashAlgorithmName.MD5)); | ||
} | ||
|
||
[Fact] | ||
public async Task SignAndEncryptMessageAsync_Valid_ReturnsSuccessfully() | ||
{ | ||
// Arrange | ||
var expectedData = new byte[] | ||
{ | ||
0, 1, 0, 1, 1, 1, 0 | ||
}; | ||
var expectedSignature = new byte[] | ||
{ | ||
1, 1, 0, 0, 1, 0, 1 | ||
}; | ||
|
||
var mockSecurityKey = new Mock<ISecurityKey>(); | ||
mockSecurityKey.Setup(m => m.EncryptAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>())) | ||
.ReturnsAsync(expectedData); | ||
mockSecurityKey.Setup(m => m.SignAsync(It.IsAny<byte[]>(), It.IsAny<HashAlgorithmName>(), It.IsAny<CancellationToken>())) | ||
.ReturnsAsync(expectedSignature); | ||
|
||
// Act | ||
var result = await _cryptographyService.SignAndEncryptMessageAsync(new byte[0], mockSecurityKey.Object, HashAlgorithmName.SHA256); | ||
|
||
// Assert | ||
Assert.True(expectedData.SequenceEqual(result.EncryptedData)); | ||
Assert.True(expectedSignature.SequenceEqual(result.Signature)); | ||
} | ||
|
||
#endregion | ||
|
||
#region ValidateAndDecryptMessageAsync | ||
|
||
[Fact] | ||
public async Task ValidateAndDecryptMessageAsync_NullData_ThrowsArgumentNullException() | ||
{ | ||
// Arrange/Act/Assert | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => _cryptographyService.ValidateAndDecryptMessageAsync(null, new Mock<ISecurityKey>().Object, HashAlgorithmName.MD5)); | ||
} | ||
|
||
[Fact] | ||
public async Task ValidateAndDecryptMessageAsync_NullSecurityKey_ThrowsArgumentNullException() | ||
{ | ||
// Arrange/Act/Assert | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => _cryptographyService.ValidateAndDecryptMessageAsync(new SignedMessage(), null, HashAlgorithmName.MD5)); | ||
} | ||
|
||
[Fact] | ||
public async Task ValidateAndDecryptMessageAsync_InvalidSignature_ThrowsSignedMessageValidationException() | ||
{ | ||
// Arrange | ||
var mockSecurityKey = new Mock<ISecurityKey>(); | ||
mockSecurityKey.Setup(m => m.ValidateSignatureAsync(It.IsAny<byte[]>(), It.IsAny<byte[]>(), | ||
It.IsAny<HashAlgorithmName>(), It.IsAny<CancellationToken>())) | ||
.ReturnsAsync(false); | ||
|
||
// Act/Assert | ||
await Assert.ThrowsAsync<SignedMessageValidationException>(() => _cryptographyService.ValidateAndDecryptMessageAsync(new SignedMessage(), mockSecurityKey.Object,HashAlgorithmName.MD5)); | ||
} | ||
|
||
[Fact] | ||
public async Task ValidateAndDecryptMessageAsync_ValidSignature_ReturnsSuccessfully() | ||
{ | ||
// Arrange | ||
var expectedData = new byte[] | ||
{ | ||
0, 1, 1, 0, 0, 1, 0 | ||
}; | ||
|
||
var mockSecurityKey = new Mock<ISecurityKey>(); | ||
mockSecurityKey.Setup(m => m.ValidateSignatureAsync(It.IsAny<byte[]>(), It.IsAny<byte[]>(), | ||
It.IsAny<HashAlgorithmName>(), It.IsAny<CancellationToken>())) | ||
.ReturnsAsync(true); | ||
mockSecurityKey.Setup(m => m.DecryptAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>())) | ||
.ReturnsAsync(expectedData); | ||
|
||
// Act | ||
var result = await _cryptographyService.ValidateAndDecryptMessageAsync(new SignedMessage(), mockSecurityKey.Object, | ||
HashAlgorithmName.MD5); | ||
|
||
// Result | ||
|
||
} | ||
|
||
|
||
#endregion | ||
} | ||
} |
Oops, something went wrong.