mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 22:36:31 +00:00
84 lines
3.0 KiB
C#
84 lines
3.0 KiB
C#
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace Azaion.Common.Services;
|
|
|
|
public static class Security
|
|
{
|
|
private const int BUFFER_SIZE = 524288; // 512 KB buffer size
|
|
|
|
public static string ToHash(this string str) =>
|
|
Convert.ToBase64String(SHA384.HashData(Encoding.UTF8.GetBytes(str)));
|
|
|
|
public static string MakeEncryptionKey(string email, string password, string? hardwareHash) =>
|
|
$"{email}-{password}-{hardwareHash}-#%@AzaionKey@%#---".ToHash();
|
|
|
|
public static SecureString ToSecureString(this string str)
|
|
{
|
|
var secureString = new SecureString();
|
|
foreach (var c in str.ToCharArray())
|
|
secureString.AppendChar(c);
|
|
|
|
return secureString;
|
|
}
|
|
|
|
public static string? ToRealString(this SecureString value)
|
|
{
|
|
var valuePtr = IntPtr.Zero;
|
|
try
|
|
{
|
|
valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
|
|
return Marshal.PtrToStringUni(valuePtr);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
|
|
}
|
|
}
|
|
|
|
|
|
public static async Task EncryptTo(this Stream stream, Stream toStream, string key, CancellationToken cancellationToken = default)
|
|
{
|
|
if (stream is { CanRead: false }) throw new ArgumentNullException(nameof(stream));
|
|
if (key is not { Length: > 0 }) throw new ArgumentNullException(nameof(key));
|
|
|
|
using var aes = Aes.Create();
|
|
aes.Key = SHA256.HashData(Encoding.UTF8.GetBytes(key));
|
|
aes.GenerateIV();
|
|
|
|
using var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
|
|
await using var cs = new CryptoStream(toStream, encryptor, CryptoStreamMode.Write, leaveOpen: true);
|
|
|
|
// Prepend IV to the encrypted data
|
|
await toStream.WriteAsync(aes.IV.AsMemory(0, aes.IV.Length), cancellationToken);
|
|
|
|
var buffer = new byte[BUFFER_SIZE];
|
|
int bytesRead;
|
|
while ((bytesRead = await stream.ReadAsync(buffer, cancellationToken)) > 0)
|
|
await cs.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken);
|
|
}
|
|
|
|
public static async Task DecryptTo(this Stream encryptedStream, Stream toStream, string key, CancellationToken cancellationToken = default)
|
|
{
|
|
using var aes = Aes.Create();
|
|
aes.Key = SHA256.HashData(Encoding.UTF8.GetBytes(key));
|
|
|
|
// Read the IV from the start of the input stream
|
|
var iv = new byte[aes.BlockSize / 8];
|
|
_ = await encryptedStream.ReadAsync(iv, cancellationToken);
|
|
aes.IV = iv;
|
|
|
|
using var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
|
|
await using var cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read, leaveOpen: true);
|
|
|
|
// Read and write in chunks
|
|
var buffer = new byte[BUFFER_SIZE];
|
|
int bytesRead;
|
|
while ((bytesRead = await cryptoStream.ReadAsync(buffer, cancellationToken)) > 0)
|
|
await toStream.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken);
|
|
}
|
|
}
|