Skip to content

Instantly share code, notes, and snippets.

@santisq
Last active March 29, 2026 13:03
Show Gist options
  • Select an option

  • Save santisq/a68d958641f654b5e40549e931cdce8c to your computer and use it in GitHub Desktop.

Select an option

Save santisq/a68d958641f654b5e40549e931cdce8c to your computer and use it in GitHub Desktop.
AES encrypt / decrypt strings
using System;
using System.IO;
using System.Management.Automation;
using System.Security.Cryptography;
using System.Text;
[Cmdlet(VerbsDiagnostic.Test, "Encrypt")]
public sealed class EncryptAes : PSCmdlet
{
[Parameter(Mandatory = true, Position = 0)]
public string Content { get; set; } = null!;
[Parameter(Mandatory = true, Position = 1)]
public byte[] Secret { get; set; } = null!;
protected override void EndProcessing()
{
using SymmetricAlgorithm algo = Aes.Create();
using MemoryStream mem = new();
using (CryptoStream crypto = new(
stream: mem,
transform: algo.CreateEncryptor(Secret, algo.IV),
mode: CryptoStreamMode.Write))
{
crypto.Write(algo.IV);
crypto.Write(Encoding.UTF8.GetBytes(Content));
}
WriteObject(Convert.ToBase64String(mem.ToArray()));
}
}
[Cmdlet(VerbsDiagnostic.Test, "Decrypt")]
public sealed class DecryptAes : PSCmdlet
{
[Parameter(Mandatory = true, Position = 0)]
public string Content { get; set; } = null!;
[Parameter(Mandatory = true, Position = 1)]
public byte[] Secret { get; set; } = null!;
protected override void EndProcessing()
{
ReadOnlySpan<byte> span = Convert.FromBase64String(Content);
using Aes aes = Aes.Create();
using MemoryStream mem = new();
using (CryptoStream cryptoStream = new(
stream: mem,
transform: aes.CreateDecryptor(Secret, [.. span[..16]]),
mode: CryptoStreamMode.Write))
{
cryptoStream.Write([.. span[16..]], 0, span.Length - 16);
}
WriteObject(Encoding.UTF8.GetString(mem.ToArray()));
}
}
using System;
using System.Buffers;
using System.Security.Cryptography;
using System.Text;
const int NonceSize = 12; // AesGcm.NonceByteSizes.MaxSize;
const int TagSize = 16; // AesGcm.TagByteSizes.MaxSize;
const int NonceTagOffset = NonceSize + TagSize;
string? key = args[2];
ArgumentException.ThrowIfNullOrWhiteSpace(key, nameof(key));
ReadOnlySpan<byte> keySpan = Convert.FromBase64String(key);
switch (args[0])
{
case "-e":
Console.WriteLine(Encrypt(args[1], keySpan));
break;
case "-d":
Console.WriteLine(Decrypt(args[1], keySpan));
break;
default:
Console.Error.WriteLine($"""
Unknown parameter: {args[0]}
Usage:
{AppDomain.CurrentDomain.FriendlyName} -e <plainText> <b64key>
{AppDomain.CurrentDomain.FriendlyName} -d <cipherText> <b64key>
Options:
-e Encrypt the given plain text using the base64-encoded key
-d Decrypt the given cipher text using the base64-encoded key
Examples:
{AppDomain.CurrentDomain.FriendlyName} -e "Hello World" "your-base64-key-here"
{AppDomain.CurrentDomain.FriendlyName} -d "encrypted-text-here" "your-base64-key-here"
""");
break;
}
static string Encrypt(string? plainText, ReadOnlySpan<byte> key)
{
ArgumentException.ThrowIfNullOrWhiteSpace(plainText, nameof(plainText));
byte[] cipherPool = ArrayPool<byte>.Shared.Rent(512);
byte[] resultPool = ArrayPool<byte>.Shared.Rent(512);
try
{
ReadOnlySpan<byte> plain = Encoding.UTF8.GetBytes(plainText);
using AesGcm aes = new(key, TagSize);
Span<byte> nonce = stackalloc byte[NonceSize];
Span<byte> tag = stackalloc byte[TagSize];
RandomNumberGenerator.Fill(nonce);
Span<byte> cipher = cipherPool.AsSpan(0, plain.Length);
aes.Encrypt(nonce, plain, cipher, tag);
return Convert.ToBase64String(
resultPool
.AsSpan(0, NonceTagOffset + cipher.Length)
.Concat(nonce, cipher, tag));
}
finally
{
ArrayPool<byte>.Shared.Return(cipherPool);
ArrayPool<byte>.Shared.Return(resultPool);
}
}
static string Decrypt(string? encryptedText, ReadOnlySpan<byte> key)
{
ArgumentException.ThrowIfNullOrWhiteSpace(encryptedText, nameof(encryptedText));
byte[] resultPool = ArrayPool<byte>.Shared.Rent(512);
try
{
using AesGcm aes = new(key, TagSize);
ReadOnlySpan<byte> encrypted = Convert.FromBase64String(encryptedText);
ReadOnlySpan<byte> cipher = encrypted[NonceSize..^TagSize];
Span<byte> result = resultPool.AsSpan(0, cipher.Length);
aes.Decrypt(encrypted[..NonceSize], cipher, encrypted[^TagSize..], result);
return Encoding.UTF8.GetString(result);
}
finally
{
ArrayPool<byte>.Shared.Return(resultPool);
}
}
internal static class Extensions
{
extension<T>(Span<T> source)
{
internal ReadOnlySpan<T> Concat(
ReadOnlySpan<T> s1,
ReadOnlySpan<T> s2,
ReadOnlySpan<T> s3)
{
s1.CopyTo(source);
int offset = s1.Length;
s2.CopyTo(source[offset..]);
offset += s2.Length;
s3.CopyTo(source[offset..]);
return source;
}
}
}
using System;
using System.Buffers;
using System.Management.Automation;
using System.Security.Cryptography;
using System.Text;
[Cmdlet(VerbsDiagnostic.Test, "Encrypt")]
public sealed class EncryptAes : PSCmdlet
{
[Parameter(Mandatory = true, Position = 0)]
public string Content { get; set; } = null!;
[Parameter(Mandatory = true, Position = 1)]
public byte[] Key { get; set; } = null!;
protected override void EndProcessing()
{
ReadOnlySpan<byte> nonce = RandomNumberGenerator.GetBytes(AesGcm.NonceByteSizes.MaxSize);
Span<byte> tag = stackalloc byte[AesCcm.TagByteSizes.MaxSize];
ReadOnlySpan<byte> plain = Encoding.UTF8.GetBytes(Content);
Span<byte> cipher = stackalloc byte[plain.Length];
using AesGcm aes = new(Key, AesCcm.TagByteSizes.MaxSize);
aes.Encrypt(nonce, plain, cipher, tag);
ReadOnlySpan<byte> result = [..nonce, ..cipher, ..tag];
WriteObject(Convert.ToBase64String(result));
}
}
[Cmdlet(VerbsDiagnostic.Test, "Decrypt")]
public sealed class DecryptAes : PSCmdlet
{
[Parameter(Mandatory = true, Position = 0)]
public string Content { get; set; } = null!;
[Parameter(Mandatory = true, Position = 1)]
public byte[] Key { get; set; } = null!;
protected override void EndProcessing()
{
int nonceSize = AesGcm.NonceByteSizes.MaxSize;
int tagSize = AesGcm.TagByteSizes.MaxSize;
ReadOnlySpan<byte> encrypted = Convert.FromBase64String(Content);
ReadOnlySpan<byte> cipher = encrypted[nonceSize..^tagSize];
Span<byte> result = stackalloc byte[cipher.Length];
using AesGcm aes = new(Key, tagSize);
aes.Decrypt(
nonce: encrypted[..nonceSize],
ciphertext: cipher,
tag: encrypted[^tagSize..],
plaintext: result);
WriteObject(Encoding.UTF8.GetString(result));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment