Basic formatting applied. Unnecessary comments have been removed. Suspicious code is covered by TODO.
168 lines
7.3 KiB
C#
168 lines
7.3 KiB
C#
using GostCryptography.Base;
|
||
using GostCryptography.Gost_28147_89;
|
||
using System;
|
||
using System.Security;
|
||
|
||
namespace GostCryptography.Gost_R3411
|
||
{
|
||
/// <summary>
|
||
/// Базовый класс для всех реализаций генератора псевдослучайной последовательности (Pseudorandom Function, PRF) на базе алгоритма хэширования ГОСТ Р 34.11
|
||
/// </summary>
|
||
/// <typeparam name="THMAC">Тип HMAC</typeparam>
|
||
public abstract class Gost_R3411_PRF<THMAC> : GostPRF where THMAC : GostHMAC
|
||
{
|
||
/// <summary>
|
||
/// Конструктор
|
||
/// </summary>
|
||
/// <param name="key">Симметричный ключ ГОСТ 28147 для вычисления HMAC на основе алгоритма ГОСТ Р 34.11</param>
|
||
/// <param name="label">Метка для порождения ключей (аргумент label функции PRF)</param>
|
||
/// <param name="seed">Начальное число для порождения ключей (аргумент seed функции PRF)</param>
|
||
/// <exception cref="ArgumentException"></exception>
|
||
/// <exception cref="ArgumentNullException"></exception>
|
||
[SecuritySafeCritical]
|
||
protected Gost_R3411_PRF(Gost_28147_89_SymmetricAlgorithmBase key, byte[] label, byte[] seed)
|
||
: this(key.ProviderType, Gost_28147_89_SymmetricAlgorithm.CreateFromKey(key), label, seed)
|
||
{
|
||
}
|
||
|
||
/// <summary>
|
||
/// Конструктор
|
||
/// </summary>
|
||
/// <param name="providerType">Тип криптографического провайдера</param>
|
||
/// <param name="key">Симметричный ключ ГОСТ 28147 для вычисления HMAC на основе алгоритма ГОСТ Р 34.11</param>
|
||
/// <param name="label">Метка для порождения ключей (аргумент label функции PRF)</param>
|
||
/// <param name="seed">Начальное число для порождения ключей (аргумент seed функции PRF)</param>
|
||
/// <exception cref="ArgumentException"></exception>
|
||
/// <exception cref="ArgumentNullException"></exception>
|
||
[SecuritySafeCritical]
|
||
protected Gost_R3411_PRF(ProviderType providerType, byte[] key, byte[] label, byte[] seed)
|
||
: this(providerType, Gost_28147_89_SymmetricAlgorithm.CreateFromSessionKey(providerType, key), label, seed)
|
||
{
|
||
}
|
||
|
||
/// <summary>
|
||
/// Конструктор
|
||
/// </summary>
|
||
/// <param name="providerType">Тип криптографического провайдера</param>
|
||
/// <param name="key">Симметричный ключ ГОСТ 28147 для вычисления HMAC на основе алгоритма ГОСТ Р 34.11</param>
|
||
/// <param name="label">Метка для порождения ключей (аргумент label функции PRF)</param>
|
||
/// <param name="seed">Начальное число для порождения ключей (аргумент seed функции PRF)</param>
|
||
/// <exception cref="ArgumentException"></exception>
|
||
/// <exception cref="ArgumentNullException"></exception>
|
||
[SecuritySafeCritical]
|
||
private Gost_R3411_PRF(ProviderType providerType, Gost_28147_89_SymmetricAlgorithm key, byte[] label, byte[] seed) : base(providerType)
|
||
{
|
||
if (label == null)
|
||
{
|
||
throw ExceptionUtility.ArgumentNull(nameof(label));
|
||
}
|
||
|
||
if (seed == null)
|
||
{
|
||
throw ExceptionUtility.ArgumentNull(nameof(seed));
|
||
}
|
||
|
||
_key = key;
|
||
_hmac = CreateHMAC(key);
|
||
|
||
var labelAndSeed = new byte[label.Length + seed.Length];
|
||
label.CopyTo(labelAndSeed, 0);
|
||
seed.CopyTo(labelAndSeed, label.Length);
|
||
|
||
_labelAndSeed = labelAndSeed;
|
||
_buffer = new byte[labelAndSeed.Length + (_hmac.HashSize / 8)];
|
||
|
||
_value = labelAndSeed;
|
||
_keyIndex = 0;
|
||
}
|
||
|
||
private readonly Gost_28147_89_SymmetricAlgorithm _key;
|
||
private readonly GostHMAC _hmac;
|
||
private readonly byte[] _labelAndSeed;
|
||
private readonly byte[] _buffer;
|
||
private byte[] _value;
|
||
private int _keyIndex;
|
||
|
||
/// <summary>
|
||
/// Создает экземпляр <typeparamref name="THMAC"/> на основе заданного ключа
|
||
/// </summary>
|
||
[SecuritySafeCritical]
|
||
protected abstract THMAC CreateHMAC(Gost_28147_89_SymmetricAlgorithm key);
|
||
|
||
/// <summary>
|
||
/// Возвращает очередной набор псевдослучайной последовательности
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Размер последовательности зависит от алгоритма хэширования
|
||
/// </remarks>
|
||
[SecurityCritical]
|
||
public byte[] DeriveBytes()
|
||
{
|
||
var randomBuffer = GenerateNextBytes();
|
||
|
||
return _hmac.ComputeHash(randomBuffer);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Возвращает псевдослучайный симметричный ключ ГОСТ 28147
|
||
/// </summary>
|
||
[SecuritySafeCritical]
|
||
public Gost_28147_89_SymmetricAlgorithmBase DeriveKey()
|
||
{
|
||
var randomPassword = GenerateNextBytes();
|
||
|
||
using (var hmac = CreateHMAC(_key))
|
||
{
|
||
return Gost_28147_89_SymmetricAlgorithm.CreateFromPassword(hmac, randomPassword);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Возвращает псевдослучайный симметричный ключ ГОСТ 28147
|
||
/// </summary>
|
||
/// <param name="position">Позиция ключа в псевдослучайной последовательности</param>
|
||
/// <exception cref="ArgumentOutOfRangeException">Если позиция ключа <paramref name="position"/> не кратна размеру ключа в байтах или ключ с данной позицией уже был создан</exception>
|
||
[SecurityCritical]
|
||
public Gost_28147_89_SymmetricAlgorithmBase DeriveKey(int position)
|
||
{
|
||
if ((position % _hmac.HashSize) != 0)
|
||
{
|
||
throw ExceptionUtility.ArgumentOutOfRange(nameof(position));
|
||
}
|
||
|
||
var keyIndex = position / _hmac.HashSize;
|
||
|
||
if (keyIndex < _keyIndex)
|
||
{
|
||
throw ExceptionUtility.ArgumentOutOfRange(nameof(position));
|
||
}
|
||
|
||
while (keyIndex > _keyIndex)
|
||
{
|
||
DeriveKey().Clear();
|
||
}
|
||
|
||
return DeriveKey();
|
||
}
|
||
|
||
[SecurityCritical]
|
||
private byte[] GenerateNextBytes()
|
||
{
|
||
_value = _hmac.ComputeHash(_value);
|
||
_value.CopyTo(_buffer, 0);
|
||
_labelAndSeed.CopyTo(_buffer, _value.Length);
|
||
|
||
_keyIndex++;
|
||
|
||
return _buffer;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
protected override void Dispose(bool disposing)
|
||
{
|
||
_key.Clear();
|
||
_hmac.Dispose();
|
||
}
|
||
}
|
||
}
|