<PackageReference Include="SshNet.Security.Cryptography" Version="1.3.0" />

HMAC

public abstract class HMAC : KeyedHashAlgorithm
Provides HMAC algorithm implementation.
using System; using System.Security.Cryptography; namespace SshNet.Security.Cryptography { public abstract class HMAC : KeyedHashAlgorithm { private IHashProvider _hashProvider; private byte[] _innerPadding; private byte[] _outerPadding; private readonly int _hashSize; private bool _innerPaddingWritten; protected abstract int BlockSize { get; } public override int HashSize => _hashSize; public override byte[] Key { get { return base.Key; } set { SetKey(value); } } private HMAC(IHashProvider hashProvider) { if (hashProvider == null) throw new ArgumentNullException("hashProvider"); _hashProvider = hashProvider; _hashSize = _hashProvider.HashSize; } internal HMAC(IHashProvider hashProvider, byte[] key, int hashSize) : this(hashProvider, key) { _hashSize = hashSize; } internal HMAC(IHashProvider hashProvider, byte[] key) : this(hashProvider) { SetKey(key); } public override void Initialize() { _hashProvider.Reset(); _innerPaddingWritten = false; } protected override void HashCore(byte[] rgb, int ib, int cb) { if (!_innerPaddingWritten) { _hashProvider.TransformBlock(_innerPadding, 0, BlockSize, _innerPadding, 0); _innerPaddingWritten = true; } _hashProvider.HashCore(rgb, ib, cb); } protected override byte[] HashFinal() { byte[] array = _hashProvider.ComputeHash(new byte[0]); _hashProvider.TransformBlock(_outerPadding, 0, BlockSize, _outerPadding, 0); _hashProvider.TransformFinalBlock(array, 0, array.Length); byte[] hash = _hashProvider.Hash; return GetTruncatedHash(hash); } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (_hashProvider != null) { _hashProvider.Dispose(); _hashProvider = null; } } private byte[] GetTruncatedHash(byte[] hash) { int num = HashSize / 8; if (hash.Length == num) return hash; byte[] array = new byte[num]; Buffer.BlockCopy(hash, 0, array, 0, num); return array; } private void SetKey(byte[] value) { byte[] shortenedKey = GetShortenedKey(value); _innerPadding = new byte[BlockSize]; _outerPadding = new byte[BlockSize]; for (int i = 0; i < shortenedKey.Length; i++) { _innerPadding[i] = (byte)(54 ^ shortenedKey[i]); _outerPadding[i] = (byte)(92 ^ shortenedKey[i]); } for (int j = shortenedKey.Length; j < BlockSize; j++) { _innerPadding[j] = 54; _outerPadding[j] = 92; } base.Key = shortenedKey; } private byte[] GetShortenedKey(byte[] key) { if (key.Length > BlockSize) return _hashProvider.ComputeHash(key); return key; } } }