<PackageReference Include="SSH.NET" Version="2024.1.0" />

AesGcmCipher

AES GCM cipher implementation. .
using Renci.SshNet.Common; using System; using System.Buffers.Binary; using System.Security.Cryptography; namespace Renci.SshNet.Security.Cryptography.Ciphers { internal sealed class AesGcmCipher : SymmetricCipher, IDisposable { private readonly byte[] _iv; private readonly AesGcm _aesGcm; public override byte MinimumSize => 16; public override int TagSize => 16; public AesGcmCipher(byte[] key, byte[] iv) : base(key) { _iv = iv.Take(12); _aesGcm = new AesGcm(key, TagSize); } public override byte[] Encrypt(byte[] input, int offset, int length) { ReadOnlySpan<byte> associatedData = new ReadOnlySpan<byte>(input, offset, 4); ReadOnlySpan<byte> plaintext = new ReadOnlySpan<byte>(input, offset + 4, length - 4); byte[] array = new byte[length + TagSize]; associatedData.CopyTo(array); Span<byte> ciphertext = new Span<byte>(array, 4, length - 4); Span<byte> tag = new Span<byte>(array, length, TagSize); _aesGcm.Encrypt(_iv, plaintext, ciphertext, tag, associatedData); IncrementCounter(); return array; } public override byte[] Decrypt(byte[] input, int offset, int length) { ReadOnlySpan<byte> associatedData = new ReadOnlySpan<byte>(input, 4, 4); ReadOnlySpan<byte> ciphertext = new ReadOnlySpan<byte>(input, offset, length); ReadOnlySpan<byte> tag = new ReadOnlySpan<byte>(input, offset + length, TagSize); byte[] array = new byte[length]; Span<byte> plaintext = new Span<byte>(array); _aesGcm.Decrypt(_iv, ciphertext, tag, plaintext, associatedData); IncrementCounter(); return array; } private void IncrementCounter() { Span<byte> span = new Span<byte>(_iv, 4, 8); ulong num = BinaryPrimitives.ReadUInt64BigEndian(span); BinaryPrimitives.WriteUInt64BigEndian(span, num + 1); } public void Dispose(bool disposing) { if (disposing) _aesGcm.Dispose(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } }