using GostCryptography.Base;
using GostCryptography.Gost_28147_89;
using GostCryptography.Native;
using System;
using System.Security;
namespace GostCryptography.Gost_R3411
{
///
/// Базовый класс для всех реализаций Hash-based Message Authentication Code (HMAC) на базе алгоритма хэширования ГОСТ Р 34.11
///
public abstract class Gost_R3411_HMAC : GostHMAC, ISafeHandleProvider where THash : GostHashAlgorithm
{
///
[SecuritySafeCritical]
protected Gost_R3411_HMAC(int hashSize) : base(hashSize)
{
InitDefaults(new Gost_28147_89_SymmetricAlgorithm(ProviderType));
}
///
[SecuritySafeCritical]
protected Gost_R3411_HMAC(ProviderType providerType, int hashSize) : base(providerType, hashSize)
{
InitDefaults(new Gost_28147_89_SymmetricAlgorithm(ProviderType));
}
///
/// Конструктор
///
/// Алгоритм для вычисления HMAC
/// Размер хэш-кода в битах
///
[SecuritySafeCritical]
protected Gost_R3411_HMAC(Gost_28147_89_SymmetricAlgorithmBase keyAlgorithm, int hashSize) : base(keyAlgorithm.ProviderType, hashSize)
{
if (keyAlgorithm == null)
{
throw ExceptionUtility.ArgumentNull(nameof(keyAlgorithm));
}
InitDefaults(Gost_28147_89_SymmetricAlgorithm.CreateFromKey(keyAlgorithm));
}
[SecuritySafeCritical]
private void InitDefaults(Gost_28147_89_SymmetricAlgorithm keyAlgorithm)
{
HashName = typeof(THash).Name;
_keyAlgorithm = keyAlgorithm;
_hmacHandle = CreateHashHMAC(keyAlgorithm.ProviderType, CryptoApiHelper.GetProviderHandle(keyAlgorithm.ProviderType), keyAlgorithm.GetSafeHandle());
}
///
/// Создает дескриптор функции хэширования HMAC криптографического провайдера
///
[SecuritySafeCritical]
protected abstract SafeHashHandleImpl CreateHashHMAC(ProviderType providerType, SafeProvHandleImpl providerHandle, SafeKeyHandleImpl symKeyHandle);
[SecurityCritical]
private SafeHashHandleImpl _hmacHandle;
private Gost_28147_89_SymmetricAlgorithm _keyAlgorithm;
///
SafeHashHandleImpl ISafeHandleProvider.SafeHandle
{
[SecurityCritical]
get { return _hmacHandle; }
}
///
/// Алгоритм для вычисления HMAC
///
public Gost_28147_89_SymmetricAlgorithmBase KeyAlgorithm
{
get
{
return _keyAlgorithm;
}
[SecuritySafeCritical]
set
{
_keyAlgorithm = Gost_28147_89_SymmetricAlgorithm.CreateFromKey(value);
}
}
///
public override byte[] Key
{
get
{
return _keyAlgorithm.Key;
}
set
{
_keyAlgorithm = new Gost_28147_89_SymmetricAlgorithm(ProviderType) { Key = value };
Initialize();
}
}
///
[SecuritySafeCritical]
public override void Initialize()
{
var hmacHandle = CreateHashHMAC(ProviderType, CryptoApiHelper.GetProviderHandle(ProviderType), _keyAlgorithm.GetSafeHandle());
_hmacHandle.TryDispose();
_hmacHandle = hmacHandle;
}
///
[SecuritySafeCritical]
protected override void HashCore(byte[] data, int dataOffset, int dataLength)
{
CryptoApiHelper.HashData(_hmacHandle, data, dataOffset, dataLength);
}
///
[SecuritySafeCritical]
protected override byte[] HashFinal()
{
return CryptoApiHelper.EndHashData(_hmacHandle);
}
///
[SecuritySafeCritical]
protected override void Dispose(bool disposing)
{
if (disposing)
{
_keyAlgorithm?.Clear();
_hmacHandle.TryDispose();
}
base.Dispose(disposing);
}
}
}