Implement IKeyManager
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using Isopoh.Cryptography.Argon2;
|
||||
using Isopoh.Cryptography.SecureArray;
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
@@ -75,5 +76,60 @@ namespace Akari.Prototype.Server.Utils
|
||||
{
|
||||
return Argon2idDeriveBytes(Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), length, clear, threads);
|
||||
}
|
||||
|
||||
// Source: https://stackoverflow.com/a/60891115/7465768
|
||||
public static byte[] AesGcmEncrypt(AesGcm key, Span<byte> plain)
|
||||
{
|
||||
// Get parameter sizes
|
||||
int nonceSize = AesGcm.NonceByteSizes.MaxSize;
|
||||
int tagSize = AesGcm.TagByteSizes.MaxSize;
|
||||
int cipherSize = plain.Length;
|
||||
|
||||
// We write everything into one big array for easier encoding
|
||||
int encryptedDataLength = 4 + nonceSize + 4 + tagSize + cipherSize;
|
||||
Span<byte> encryptedData = encryptedDataLength < 1024
|
||||
? stackalloc byte[encryptedDataLength]
|
||||
: new byte[encryptedDataLength];
|
||||
|
||||
// Copy parameters
|
||||
BinaryPrimitives.WriteInt32LittleEndian(encryptedData.Slice(0, 4), nonceSize);
|
||||
BinaryPrimitives.WriteInt32LittleEndian(encryptedData.Slice(4 + nonceSize, 4), tagSize);
|
||||
|
||||
var nonce = encryptedData.Slice(4, nonceSize);
|
||||
var tag = encryptedData.Slice(4 + nonceSize + 4, tagSize);
|
||||
var cipherBytes = encryptedData.Slice(4 + nonceSize + 4 + tagSize, cipherSize);
|
||||
|
||||
// Generate secure nonce
|
||||
RandomNumberGenerator.Fill(nonce);
|
||||
|
||||
// Encrypt
|
||||
key.Encrypt(nonce, plain, cipherBytes, tag);
|
||||
|
||||
// Encode for transmission
|
||||
return encryptedData.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] AesGcmDecrypt(AesGcm key, Span<byte> encryptedData)
|
||||
{
|
||||
// Extract parameter sizes
|
||||
int nonceSize = BinaryPrimitives.ReadInt32LittleEndian(encryptedData.Slice(0, 4));
|
||||
int tagSize = BinaryPrimitives.ReadInt32LittleEndian(encryptedData.Slice(4 + nonceSize, 4));
|
||||
int cipherSize = encryptedData.Length - 4 - nonceSize - 4 - tagSize;
|
||||
|
||||
// Extract parameters
|
||||
var nonce = encryptedData.Slice(4, nonceSize);
|
||||
var tag = encryptedData.Slice(4 + nonceSize + 4, tagSize);
|
||||
var cipherBytes = encryptedData.Slice(4 + nonceSize + 4 + tagSize, cipherSize);
|
||||
|
||||
// Decrypt
|
||||
Span<byte> plainBytes = cipherSize < 1024
|
||||
? stackalloc byte[cipherSize]
|
||||
: new byte[cipherSize];
|
||||
|
||||
key.Decrypt(nonce, cipherBytes, tag, plainBytes);
|
||||
|
||||
// Convert plain bytes back into string
|
||||
return plainBytes.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user