Basic formatting applied. Unnecessary comments have been removed. Suspicious code is covered by TODO.
164 lines
6.5 KiB
C#
164 lines
6.5 KiB
C#
using GostCryptography.Asn1.Gost.Gost_28147_89;
|
||
using GostCryptography.Asn1.Gost.Gost_R3410;
|
||
using GostCryptography.Base;
|
||
using GostCryptography.Gost_28147_89;
|
||
using GostCryptography.Native;
|
||
using GostCryptography.Properties;
|
||
using System.Security;
|
||
using System.Security.Cryptography;
|
||
|
||
namespace GostCryptography.Gost_R3410
|
||
{
|
||
/// <summary>
|
||
/// Базовый класс всех реализаций общего секретного ключа ГОСТ Р 34.10
|
||
/// </summary>
|
||
public abstract class Gost_R3410_KeyExchangeAlgorithm : GostKeyExchangeAlgorithm
|
||
{
|
||
/// <inheritdoc />
|
||
[SecurityCritical]
|
||
protected Gost_R3410_KeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_KeyExchangeParams keyExchangeParameters, int keySize, int signatureAlgId) : base(providerType)
|
||
{
|
||
if (provHandle == null)
|
||
{
|
||
throw ExceptionUtility.ArgumentNull(nameof(provHandle));
|
||
}
|
||
|
||
if (keyHandle == null)
|
||
{
|
||
throw ExceptionUtility.ArgumentNull(nameof(keyHandle));
|
||
}
|
||
|
||
if (keyExchangeParameters == null)
|
||
{
|
||
throw ExceptionUtility.ArgumentNull(nameof(keyExchangeParameters));
|
||
}
|
||
|
||
_provHandle = provHandle.DangerousAddRef();
|
||
_keyHandle = keyHandle.DangerousAddRef();
|
||
_keyExchangeParameters = keyExchangeParameters;
|
||
_keySize = keySize;
|
||
_signatureAlgId = signatureAlgId;
|
||
}
|
||
|
||
[SecurityCritical]
|
||
private readonly SafeProvHandleImpl _provHandle;
|
||
[SecurityCritical]
|
||
private readonly SafeKeyHandleImpl _keyHandle;
|
||
[SecurityCritical]
|
||
private readonly Gost_R3410_KeyExchangeParams _keyExchangeParameters;
|
||
|
||
private readonly int _keySize;
|
||
private readonly int _signatureAlgId;
|
||
|
||
/// <inheritdoc />
|
||
[SecuritySafeCritical]
|
||
public override byte[] EncodeKeyExchange(SymmetricAlgorithm keyExchangeAlgorithm, GostKeyExchangeExportMethod keyExchangeExportMethod)
|
||
{
|
||
if (keyExchangeAlgorithm is Gost_28147_89_SymmetricAlgorithm symAlg)
|
||
{
|
||
return EncodeKeyExchangeInternal(symAlg, keyExchangeExportMethod);
|
||
}
|
||
|
||
if (keyExchangeAlgorithm is Gost_28147_89_SymmetricAlgorithmBase symAlgBase)
|
||
{
|
||
using (var gostKeyExchangeAlgorithm = new Gost_28147_89_SymmetricAlgorithm(symAlgBase.ProviderType))
|
||
{
|
||
return gostKeyExchangeAlgorithm.EncodePrivateKey(symAlgBase, keyExchangeExportMethod);
|
||
}
|
||
}
|
||
|
||
throw ExceptionUtility.Argument(nameof(keyExchangeAlgorithm), Resources.RequiredGost28147);
|
||
}
|
||
|
||
[SecurityCritical]
|
||
private byte[] EncodeKeyExchangeInternal(Gost_28147_89_SymmetricAlgorithm keyExchangeAlgorithm, GostKeyExchangeExportMethod keyExchangeExportMethod)
|
||
{
|
||
switch (keyExchangeExportMethod)
|
||
{
|
||
case GostKeyExchangeExportMethod.GostKeyExport:
|
||
return EncodeKeyExchangeInternal(keyExchangeAlgorithm, Constants.CALG_SIMPLE_EXPORT);
|
||
|
||
case GostKeyExchangeExportMethod.CryptoProKeyExport:
|
||
return EncodeKeyExchangeInternal(keyExchangeAlgorithm, Constants.CALG_PRO_EXPORT);
|
||
}
|
||
|
||
throw ExceptionUtility.ArgumentOutOfRange(nameof(keyExchangeExportMethod));
|
||
}
|
||
|
||
[SecurityCritical]
|
||
private byte[] EncodeKeyExchangeInternal(Gost_28147_89_SymmetricAlgorithm keyExchangeAlgorithm, int keyExchangeExportAlgId)
|
||
{
|
||
Gost_28147_89_KeyExchangeInfo keyExchangeInfo;
|
||
|
||
SafeKeyHandleImpl keyExchangeHandle = null;
|
||
|
||
try
|
||
{
|
||
var importedKeyBytes = CryptoApiHelper.EncodePublicBlob(_keyExchangeParameters, _keySize, _signatureAlgId);
|
||
CryptoApiHelper.ImportCspBlob(importedKeyBytes, _provHandle, _keyHandle, out keyExchangeHandle);
|
||
CryptoApiHelper.SetKeyExchangeExportAlgId(ProviderType, keyExchangeHandle, keyExchangeExportAlgId);
|
||
|
||
var symKeyHandle = keyExchangeAlgorithm.GetSafeHandle();
|
||
keyExchangeInfo = CryptoApiHelper.ExportKeyExchange(symKeyHandle, keyExchangeHandle);
|
||
}
|
||
finally
|
||
{
|
||
keyExchangeHandle.TryDispose();
|
||
}
|
||
|
||
return keyExchangeInfo.Encode();
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
[SecuritySafeCritical]
|
||
public override SymmetricAlgorithm DecodeKeyExchange(byte[] encodedKeyExchangeData, GostKeyExchangeExportMethod keyExchangeExportMethod)
|
||
{
|
||
switch (keyExchangeExportMethod)
|
||
{
|
||
case GostKeyExchangeExportMethod.GostKeyExport:
|
||
return DecodeKeyExchangeInternal(encodedKeyExchangeData, Constants.CALG_SIMPLE_EXPORT);
|
||
|
||
case GostKeyExchangeExportMethod.CryptoProKeyExport:
|
||
return DecodeKeyExchangeInternal(encodedKeyExchangeData, Constants.CALG_PRO_EXPORT);
|
||
}
|
||
|
||
throw ExceptionUtility.ArgumentOutOfRange(nameof(keyExchangeExportMethod));
|
||
}
|
||
|
||
[SecurityCritical]
|
||
private SymmetricAlgorithm DecodeKeyExchangeInternal(byte[] encodedKeyExchangeData, int keyExchangeExportAlgId)
|
||
{
|
||
var keyExchangeInfo = new Gost_28147_89_KeyExchangeInfo();
|
||
keyExchangeInfo.Decode(encodedKeyExchangeData);
|
||
|
||
SafeKeyHandleImpl symKeyHandle;
|
||
SafeKeyHandleImpl keyExchangeHandle = null;
|
||
|
||
try
|
||
{
|
||
var importedKeyBytes = CryptoApiHelper.EncodePublicBlob(_keyExchangeParameters, _keySize, _signatureAlgId);
|
||
CryptoApiHelper.ImportCspBlob(importedKeyBytes, _provHandle, _keyHandle, out keyExchangeHandle);
|
||
CryptoApiHelper.SetKeyExchangeExportAlgId(ProviderType, keyExchangeHandle, keyExchangeExportAlgId);
|
||
|
||
symKeyHandle = CryptoApiHelper.ImportKeyExchange(_provHandle, keyExchangeInfo, keyExchangeHandle);
|
||
}
|
||
finally
|
||
{
|
||
keyExchangeHandle.TryDispose();
|
||
}
|
||
|
||
return new Gost_28147_89_SymmetricAlgorithm(ProviderType, _provHandle, symKeyHandle);
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
[SecuritySafeCritical]
|
||
protected override void Dispose(bool disposing)
|
||
{
|
||
_keyHandle.TryDispose();
|
||
_provHandle.TryDispose();
|
||
|
||
base.Dispose(disposing);
|
||
}
|
||
}
|
||
}
|