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 { /// /// Базовый класс всех реализаций общего секретного ключа ГОСТ Р 34.10 /// public abstract class Gost_R3410_KeyExchangeAlgorithm : GostKeyExchangeAlgorithm { /// [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; /// [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(); } /// [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); } /// [SecuritySafeCritical] protected override void Dispose(bool disposing) { _keyHandle.TryDispose(); _provHandle.TryDispose(); base.Dispose(disposing); } } }