-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from houseofcat/master
Release v1.2.2
- Loading branch information
Showing
11 changed files
with
253 additions
and
68 deletions.
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
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
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
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
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
141 changes: 141 additions & 0 deletions
141
src/HouseofCat.Encryption/AesStreamEncryptionProvider.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,141 @@ | ||
using HouseofCat.Utilities.Errors; | ||
using System; | ||
using System.Buffers; | ||
using System.IO; | ||
using System.Security.Cryptography; | ||
|
||
namespace HouseofCat.Encryption | ||
{ | ||
public class AesStreamEncryptionProvider : IStreamEncryptionProvider | ||
{ | ||
public string Type { get; } | ||
|
||
private readonly ReadOnlyMemory<byte> _key; | ||
private readonly ArrayPool<byte> _pool = ArrayPool<byte>.Shared; | ||
|
||
private readonly CipherMode _cipherMode; | ||
private readonly PaddingMode _paddingMode; | ||
|
||
public AesStreamEncryptionProvider( | ||
ReadOnlyMemory<byte> key, | ||
string hashType, | ||
CipherMode cipherMode = CipherMode.CBC, | ||
PaddingMode paddingMode = PaddingMode.PKCS7) | ||
{ | ||
Guard.AgainstEmpty(key, nameof(key)); | ||
|
||
if (!Constants.Aes.ValidKeySizes.Contains(key.Length)) throw new ArgumentException("Keysize is an invalid length."); | ||
_key = key; | ||
|
||
_cipherMode = cipherMode; | ||
_paddingMode = paddingMode; | ||
|
||
switch (_key.Length) | ||
{ | ||
case 16: Type = $"AES{_cipherMode}_128"; break; | ||
case 24: Type = $"AES{_cipherMode}_192"; break; | ||
case 32: Type = $"AES{_cipherMode}_256"; break; | ||
} | ||
|
||
if (!string.IsNullOrWhiteSpace(hashType)) { Type = $"HOC_{hashType}-{Type}"; } | ||
} | ||
|
||
/// <summary> | ||
/// Creates a CryptoStream from the input Stream, but with Nonce/IV size and nonce pre-appended to the Stream | ||
/// before creating the CryptoStream. Primarily designed for FileStreams. | ||
/// <para> | ||
/// Byte Structure | ||
/// </para> | ||
/// <para> | ||
/// IV Nonce Length (NL) | ||
/// [ 0 - 3 ] | ||
/// </para> | ||
/// <para> | ||
/// IV Nonce | ||
/// [ 3 - (NL) ] | ||
/// </para> | ||
/// <para> | ||
/// CipherText | ||
/// [ (NL) - n ] | ||
/// </para> | ||
/// </summary> | ||
/// <param name="stream"></param> | ||
/// <returns></returns> | ||
public CryptoStream GetEncryptStream(Stream stream, bool leaveOpen = false) | ||
{ | ||
stream.Seek(0, SeekOrigin.Begin); | ||
|
||
using AesManaged aes = new AesManaged | ||
{ | ||
Key = _key.ToArray(), | ||
Mode = _cipherMode, | ||
Padding = _paddingMode, | ||
}; | ||
|
||
var nonceSize = aes.BlockSize / 8; | ||
stream.Write(BitConverter.GetBytes(nonceSize)); | ||
stream.Write(aes.IV, 0, aes.IV.Length); | ||
|
||
return new CryptoStream( | ||
stream, | ||
aes.CreateEncryptor(aes.Key, aes.IV), | ||
CryptoStreamMode.Write, | ||
leaveOpen); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a CryptoStream from the input Stream, but with Nonce/IV size and nonce pre-read to the Stream | ||
/// before creating the CryptoStream. Primarily designed for FileStreams. | ||
/// <para> | ||
/// Byte Structure | ||
/// </para> | ||
/// <para> | ||
/// IV Nonce Length (NL) | ||
/// [ 0 - 3 ] | ||
/// </para> | ||
/// <para> | ||
/// IV Nonce | ||
/// [ 3 - (NL) ] | ||
/// </para> | ||
/// <para> | ||
/// CipherText | ||
/// [ (NL) - n ] | ||
/// </para> | ||
/// </summary> | ||
/// <param name="stream"></param> | ||
/// <returns></returns> | ||
public CryptoStream GetDecryptStream(Stream stream, bool leaveOpen = false) | ||
{ | ||
stream.Seek(0, SeekOrigin.Begin); | ||
|
||
using AesManaged aes = new AesManaged | ||
{ | ||
Key = _key.ToArray(), | ||
Mode = _cipherMode, | ||
Padding = _paddingMode, | ||
}; | ||
|
||
var nonceSizeBytes = _pool.Rent(4); | ||
stream.Read(nonceSizeBytes, 0, 4); | ||
|
||
var nonceSize = BitConverter.ToInt32(nonceSizeBytes); | ||
var nonce = _pool.Rent(nonceSize); | ||
|
||
stream.Read(nonce, 0, nonceSize); | ||
|
||
aes.IV = nonce | ||
.AsSpan() | ||
.Slice(0, nonceSize) | ||
.ToArray(); | ||
|
||
_pool.Return(nonceSizeBytes); | ||
_pool.Return(nonce); | ||
|
||
return new CryptoStream( | ||
stream, | ||
aes.CreateDecryptor(aes.Key, aes.IV), | ||
CryptoStreamMode.Read, | ||
leaveOpen); | ||
} | ||
} | ||
} |
Oops, something went wrong.