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

ChaCha20Poly1305Cipher

ChaCha20Poly1305 cipher implementation. .
using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Macs; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Utilities; using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; using System; using System.Buffers.Binary; namespace Renci.SshNet.Security.Cryptography.Ciphers { internal sealed class ChaCha20Poly1305Cipher : SymmetricCipher { private readonly byte[] _iv; private readonly int _aadLength; private readonly KeyParameter _aadKeyParameter; private readonly KeyParameter _keyParameter; private readonly ChaCha7539Engine _aadCipher; private readonly ChaCha7539Engine _cipher; private readonly Poly1305 _mac; public override byte MinimumSize => 16; public override int TagSize => 16; public ChaCha20Poly1305Cipher(byte[] key, int aadLength) : base(key) { _iv = new byte[12]; _aadLength = aadLength; _keyParameter = new KeyParameter(key, 0, 32); _cipher = new ChaCha7539Engine(); if (aadLength > 0) { _aadKeyParameter = new KeyParameter(key, 32, 32); _aadCipher = new ChaCha7539Engine(); } _mac = new Poly1305(); } public override byte[] Encrypt(byte[] input, int offset, int length) { ChaCha7539Engine aadCipher = _aadCipher; if (aadCipher != null) aadCipher.Init(true, new ParametersWithIV(_aadKeyParameter, _iv)); _cipher.Init(true, new ParametersWithIV(_keyParameter, _iv)); byte[] array = new byte[64]; _cipher.ProcessBytes(array, 0, array.Length, array, 0); _mac.Init(new KeyParameter(array, 0, 32)); byte[] array2 = new byte[length + TagSize]; ChaCha7539Engine aadCipher2 = _aadCipher; if (aadCipher2 != null) aadCipher2.ProcessBytes(input, offset, _aadLength, array2, 0); _cipher.ProcessBytes(input, offset + _aadLength, length - _aadLength, array2, _aadLength); _mac.BlockUpdate(array2, 0, length); _mac.DoFinal(array2, length); return array2; } public override byte[] Decrypt(byte[] input) { _aadCipher.Init(false, new ParametersWithIV(_aadKeyParameter, _iv)); byte[] array = new byte[input.Length]; _aadCipher.ProcessBytes(input, 0, input.Length, array, 0); return array; } public override byte[] Decrypt(byte[] input, int offset, int length) { _cipher.Init(false, new ParametersWithIV(_keyParameter, _iv)); byte[] array = new byte[64]; _cipher.ProcessBytes(array, 0, array.Length, array, 0); _mac.Init(new KeyParameter(array, 0, 32)); byte[] array2 = new byte[TagSize]; _mac.BlockUpdate(input, offset - _aadLength, length + _aadLength); _mac.DoFinal(array2, 0); if (!Arrays.FixedTimeEquals(TagSize, array2, 0, input, offset + length)) throw new SshConnectionException("MAC error", DisconnectReason.MacError); byte[] array3 = new byte[length]; _cipher.ProcessBytes(input, offset, length, array3, 0); return array3; } internal override void SetSequenceNumber(uint sequenceNumber) { BinaryPrimitives.WriteUInt64BigEndian(_iv.AsSpan(4), sequenceNumber); } } }