Add migrated to .NET 8.0 variant of Hcs.Client
This commit is contained in:
@ -0,0 +1,127 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2001;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Config;
|
||||
using GostCryptography.Gost_R3411;
|
||||
using GostCryptography.Native;
|
||||
using GostCryptography.Properties;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация алгоритма ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2001_AsymmetricAlgorithm : Gost_R3410_AsymmetricAlgorithm<Gost_R3410_2001_KeyExchangeParams, Gost_R3410_2001_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <summary>
|
||||
/// Размер ключа ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public const int DefaultKeySizeValue = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма цифровой подписи ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public const string SignatureAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102001-gostr3411";
|
||||
|
||||
/// <summary>
|
||||
/// Устаревшее наименование алгоритма цифровой подписи ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public const string ObsoleteSignatureAlgorithmValue = "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411";
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма обмена ключами ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public const string KeyExchangeAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2001";
|
||||
|
||||
/// <summary>
|
||||
/// Известные наименования алгоритма цифровой подписи ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public static readonly string[] KnownSignatureAlgorithmNames = { SignatureAlgorithmValue, ObsoleteSignatureAlgorithmValue };
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2001_AsymmetricAlgorithm() : this(GostCryptoConfig.ProviderType)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2001_AsymmetricAlgorithm(ProviderType providerType) : base(providerType, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2001_AsymmetricAlgorithm(CspParameters providerParameters) : base(providerParameters, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string AlgorithmName => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string SignatureAlgorithm => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string KeyExchangeAlgorithm => KeyExchangeAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int ExchangeAlgId => Constants.CALG_DH_EL_SF;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int SignatureAlgId => Constants.CALG_GR3410EL;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_2001_KeyExchangeParams CreateKeyExchangeParams()
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeParams();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected override Gost_R3410_2001_KeyExchangeAlgorithm CreateKeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_2001_KeyExchangeParams keyExchangeParameters)
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeAlgorithm(providerType, provHandle, keyHandle, keyExchangeParameters, KeySizeValue, SignatureAlgId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override GostHashAlgorithm CreateHashAlgorithm()
|
||||
{
|
||||
return new Gost_R3411_94_HashAlgorithm(ProviderType, this.GetSafeHandle<SafeProvHandleImpl>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void ValidateHashParameter(byte[] hash)
|
||||
{
|
||||
if (hash == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(hash));
|
||||
}
|
||||
|
||||
if (hash.Length != Gost_R3411_94_HashAlgorithm.DefaultHashSizeValue / 8)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentOutOfRange(nameof(hash), Resources.InvalidHashSize, Gost_R3411_94_HashAlgorithm.DefaultHashSizeValue / 8);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeFormatter CreateKeyExchangeFormatter()
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeFormatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeDeformatter CreateKeyExchangeDeformatter()
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeDeformatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_KeyExchangeXmlSerializer<Gost_R3410_2001_KeyExchangeParams> CreateKeyExchangeXmlSerializer()
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeXmlSerializer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2001;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Config;
|
||||
using GostCryptography.Gost_R3411;
|
||||
using GostCryptography.Native;
|
||||
using System.Security;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация алгоритма ГОСТ Р 34.10-2001 на основе эфимерного ключа
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2001_EphemeralAsymmetricAlgorithm : Gost_R3410_EphemeralAsymmetricAlgorithm<Gost_R3410_2001_KeyExchangeParams, Gost_R3410_2001_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <summary>
|
||||
/// Размер ключа ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public const int DefaultKeySizeValue = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма цифровой подписи ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public const string SignatureAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102001-gostr3411";
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма обмена ключами ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public const string KeyExchangeAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2001";
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2001_EphemeralAsymmetricAlgorithm() : this(GostCryptoConfig.ProviderType)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2001_EphemeralAsymmetricAlgorithm(ProviderType providerType) : base(providerType, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2001_EphemeralAsymmetricAlgorithm(Gost_R3410_2001_KeyExchangeParams keyParameters) : this(GostCryptoConfig.ProviderType, keyParameters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2001_EphemeralAsymmetricAlgorithm(ProviderType providerType, Gost_R3410_2001_KeyExchangeParams keyParameters) : base(providerType, keyParameters, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string AlgorithmName => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string SignatureAlgorithm => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string KeyExchangeAlgorithm => KeyExchangeAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int ExchangeAlgId => Constants.CALG_DH_EL_EPHEM;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int SignatureAlgId => Constants.CALG_GR3410EL;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_2001_KeyExchangeParams CreateKeyExchangeParams()
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeParams();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected override Gost_R3410_2001_KeyExchangeAlgorithm CreateKeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_2001_KeyExchangeParams keyExchangeParameters)
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeAlgorithm(providerType, provHandle, keyHandle, keyExchangeParameters, KeySizeValue, SignatureAlgId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override GostHashAlgorithm CreateHashAlgorithm()
|
||||
{
|
||||
return new Gost_R3411_94_HashAlgorithm(ProviderType, this.GetSafeHandle<SafeProvHandleImpl>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeFormatter CreateKeyExchangeFormatter()
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeFormatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeDeformatter CreateKeyExchangeDeformatter()
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeDeformatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_KeyExchangeXmlSerializer<Gost_R3410_2001_KeyExchangeParams> CreateKeyExchangeXmlSerializer()
|
||||
{
|
||||
return new Gost_R3410_2001_KeyExchangeXmlSerializer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2001;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Native;
|
||||
using System.Security;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public sealed class Gost_R3410_2001_KeyExchangeAlgorithm : Gost_R3410_KeyExchangeAlgorithm
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[SecurityCritical]
|
||||
public Gost_R3410_2001_KeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_2001_KeyExchangeParams keyExchangeParameters, int keySize, int signatureAlgId)
|
||||
: base(providerType, provHandle, keyHandle, keyExchangeParameters, keySize, signatureAlgId)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2001;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация дешифрования общего секретного ключа по ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2001_KeyExchangeDeformatter : Gost_R3410_KeyExchangeDeformatter<
|
||||
Gost_R3410_2001_KeyExchange,
|
||||
Gost_R3410_2001_KeyExchangeParams,
|
||||
Gost_R3410_2001_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2001_KeyExchangeDeformatter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2001_KeyExchangeDeformatter(AsymmetricAlgorithm privateKey) : base(privateKey)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2001;
|
||||
using GostCryptography.Base;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация шифрования общего секретного ключа по ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2001_KeyExchangeFormatter : Gost_R3410_KeyExchangeFormatter<
|
||||
Gost_R3410_2001_KeyExchange,
|
||||
Gost_R3410_2001_KeyExchangeParams,
|
||||
Gost_R3410_2001_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2001_KeyExchangeFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2001_KeyExchangeFormatter(AsymmetricAlgorithm publicKey) : base(publicKey)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_EphemeralAsymmetricAlgorithm<Gost_R3410_2001_KeyExchangeParams, Gost_R3410_2001_KeyExchangeAlgorithm> CreateEphemeralAlgorithm(ProviderType providerType, Gost_R3410_2001_KeyExchangeParams keyExchangeParameters)
|
||||
{
|
||||
return new Gost_R3410_2001_EphemeralAsymmetricAlgorithm(providerType, keyExchangeParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2001;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// XML-сериализатора параметров ключа цифровой подписи ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2001_KeyExchangeXmlSerializer : Gost_R3410_KeyExchangeXmlSerializer<Gost_R3410_2001_KeyExchangeParams>
|
||||
{
|
||||
/// <summary>
|
||||
/// Имя тега с информацией о параметрах ключа ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public const string KeyValueTag = "GostKeyValue";
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2001_KeyExchangeXmlSerializer() : base(KeyValueTag)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Gost_R3411;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Информация о свойствах цифровой подписи ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2001_SignatureDescription : GostSignatureDescription
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2001_SignatureDescription()
|
||||
{
|
||||
KeyAlgorithm = typeof(Gost_R3410_2001_AsymmetricAlgorithm).AssemblyQualifiedName;
|
||||
DigestAlgorithm = typeof(Gost_R3411_94_HashAlgorithm).AssemblyQualifiedName;
|
||||
FormatterAlgorithm = typeof(GostSignatureFormatter).AssemblyQualifiedName;
|
||||
DeformatterAlgorithm = typeof(GostSignatureDeformatter).AssemblyQualifiedName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_256;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Config;
|
||||
using GostCryptography.Gost_R3411;
|
||||
using GostCryptography.Native;
|
||||
using GostCryptography.Properties;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация алгоритма ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_256_AsymmetricAlgorithm : Gost_R3410_AsymmetricAlgorithm<Gost_R3410_2012_256_KeyExchangeParams, Gost_R3410_2012_256_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <summary>
|
||||
/// Размер ключа ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public const int DefaultKeySizeValue = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма цифровой подписи ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public const string SignatureAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256";
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма обмена ключами ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public const string KeyExchangeAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2012-256";
|
||||
|
||||
/// <summary>
|
||||
/// Известные наименования алгоритма цифровой подписи ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public static readonly string[] KnownSignatureAlgorithmNames = { SignatureAlgorithmValue };
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_256_AsymmetricAlgorithm() : this(GostCryptoConfig.ProviderType_2012_512)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_256_AsymmetricAlgorithm(ProviderType providerType) : base(providerType, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_256_AsymmetricAlgorithm(CspParameters providerParameters) : base(providerParameters, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string AlgorithmName => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string SignatureAlgorithm => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string KeyExchangeAlgorithm => KeyExchangeAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int ExchangeAlgId => Constants.CALG_DH_GR3410_2012_256_SF;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int SignatureAlgId => Constants.CALG_GR3410_2012_256;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_2012_256_KeyExchangeParams CreateKeyExchangeParams()
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeParams();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected override Gost_R3410_2012_256_KeyExchangeAlgorithm CreateKeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_2012_256_KeyExchangeParams keyExchangeParameters)
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeAlgorithm(providerType, provHandle, keyHandle, keyExchangeParameters, KeySizeValue, SignatureAlgId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override GostHashAlgorithm CreateHashAlgorithm()
|
||||
{
|
||||
return new Gost_R3411_2012_256_HashAlgorithm(ProviderType, this.GetSafeHandle<SafeProvHandleImpl>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void ValidateHashParameter(byte[] hash)
|
||||
{
|
||||
if (hash == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(hash));
|
||||
}
|
||||
|
||||
if (hash.Length != Gost_R3411_2012_256_HashAlgorithm.DefaultHashSizeValue / 8)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentOutOfRange(nameof(hash), Resources.InvalidHashSize, Gost_R3411_2012_256_HashAlgorithm.DefaultHashSizeValue / 8);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeFormatter CreateKeyExchangeFormatter()
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeFormatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeDeformatter CreateKeyExchangeDeformatter()
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeDeformatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_KeyExchangeXmlSerializer<Gost_R3410_2012_256_KeyExchangeParams> CreateKeyExchangeXmlSerializer()
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeXmlSerializer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_256;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Config;
|
||||
using GostCryptography.Gost_R3411;
|
||||
using GostCryptography.Native;
|
||||
using System.Security;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация алгоритма ГОСТ Р 34.10-2012/256 на основе эфимерного ключа
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_256_EphemeralAsymmetricAlgorithm : Gost_R3410_EphemeralAsymmetricAlgorithm<Gost_R3410_2012_256_KeyExchangeParams, Gost_R3410_2012_256_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <summary>
|
||||
/// Размер ключа ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public const int DefaultKeySizeValue = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма цифровой подписи ГОСТ Р 34.10-2012 для ключей длины 256 бит
|
||||
/// </summary>
|
||||
public const string SignatureAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256";
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма обмена ключами ГОСТ Р 34.10-2012 для ключей длины 256 бит
|
||||
/// </summary>
|
||||
public const string KeyExchangeAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2012-256";
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_256_EphemeralAsymmetricAlgorithm() : this(GostCryptoConfig.ProviderType_2012_512)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_256_EphemeralAsymmetricAlgorithm(ProviderType providerType) : base(providerType, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_256_EphemeralAsymmetricAlgorithm(Gost_R3410_2012_256_KeyExchangeParams keyParameters) : this(GostCryptoConfig.ProviderType_2012_512, keyParameters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_256_EphemeralAsymmetricAlgorithm(ProviderType providerType, Gost_R3410_2012_256_KeyExchangeParams keyParameters) : base(providerType, keyParameters, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string AlgorithmName => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string SignatureAlgorithm => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string KeyExchangeAlgorithm => KeyExchangeAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int ExchangeAlgId => Constants.CALG_DH_GR3410_12_256_EPHEM;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int SignatureAlgId => Constants.CALG_GR3410_2012_256;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_2012_256_KeyExchangeParams CreateKeyExchangeParams()
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeParams();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected override Gost_R3410_2012_256_KeyExchangeAlgorithm CreateKeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_2012_256_KeyExchangeParams keyExchangeParameters)
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeAlgorithm(providerType, provHandle, keyHandle, keyExchangeParameters, KeySizeValue, SignatureAlgId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override GostHashAlgorithm CreateHashAlgorithm()
|
||||
{
|
||||
return new Gost_R3411_2012_256_HashAlgorithm(ProviderType, this.GetSafeHandle<SafeProvHandleImpl>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeFormatter CreateKeyExchangeFormatter()
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeFormatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeDeformatter CreateKeyExchangeDeformatter()
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeDeformatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_KeyExchangeXmlSerializer<Gost_R3410_2012_256_KeyExchangeParams> CreateKeyExchangeXmlSerializer()
|
||||
{
|
||||
return new Gost_R3410_2012_256_KeyExchangeXmlSerializer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_256;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Native;
|
||||
using System.Security;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public sealed class Gost_R3410_2012_256_KeyExchangeAlgorithm : Gost_R3410_KeyExchangeAlgorithm
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[SecurityCritical]
|
||||
public Gost_R3410_2012_256_KeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_2012_256_KeyExchangeParams keyExchangeParameters, int keySize, int signatureAlgId)
|
||||
: base(providerType, provHandle, keyHandle, keyExchangeParameters, keySize, signatureAlgId)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_256;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация дешифрования общего секретного ключа по ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_256_KeyExchangeDeformatter : Gost_R3410_KeyExchangeDeformatter<
|
||||
Gost_R3410_2012_256_KeyExchange,
|
||||
Gost_R3410_2012_256_KeyExchangeParams,
|
||||
Gost_R3410_2012_256_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_256_KeyExchangeDeformatter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_256_KeyExchangeDeformatter(AsymmetricAlgorithm privateKey) : base(privateKey)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_256;
|
||||
using GostCryptography.Base;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация шифрования общего секретного ключа по ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_256_KeyExchangeFormatter : Gost_R3410_KeyExchangeFormatter<
|
||||
Gost_R3410_2012_256_KeyExchange,
|
||||
Gost_R3410_2012_256_KeyExchangeParams,
|
||||
Gost_R3410_2012_256_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_256_KeyExchangeFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_256_KeyExchangeFormatter(AsymmetricAlgorithm publicKey) : base(publicKey)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_EphemeralAsymmetricAlgorithm<Gost_R3410_2012_256_KeyExchangeParams, Gost_R3410_2012_256_KeyExchangeAlgorithm> CreateEphemeralAlgorithm(ProviderType providerType, Gost_R3410_2012_256_KeyExchangeParams keyExchangeParameters)
|
||||
{
|
||||
return new Gost_R3410_2012_256_EphemeralAsymmetricAlgorithm(providerType, keyExchangeParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_256;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// XML-сериализатора параметров ключа цифровой подписи ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_256_KeyExchangeXmlSerializer : Gost_R3410_KeyExchangeXmlSerializer<Gost_R3410_2012_256_KeyExchangeParams>
|
||||
{
|
||||
/// <summary>
|
||||
/// Имя тега с информацией о параметрах ключа ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public const string KeyValueTag = "Gost_R3410_2012_256_KeyValue";
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_256_KeyExchangeXmlSerializer() : base(KeyValueTag)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Gost_R3411;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Информация о свойствах цифровой подписи ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_256_SignatureDescription : GostSignatureDescription
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_256_SignatureDescription()
|
||||
{
|
||||
KeyAlgorithm = typeof(Gost_R3410_2012_256_AsymmetricAlgorithm).AssemblyQualifiedName;
|
||||
DigestAlgorithm = typeof(Gost_R3411_2012_256_HashAlgorithm).AssemblyQualifiedName;
|
||||
FormatterAlgorithm = typeof(GostSignatureFormatter).AssemblyQualifiedName;
|
||||
DeformatterAlgorithm = typeof(GostSignatureDeformatter).AssemblyQualifiedName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_512;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Config;
|
||||
using GostCryptography.Gost_R3411;
|
||||
using GostCryptography.Native;
|
||||
using GostCryptography.Properties;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация алгоритма ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_512_AsymmetricAlgorithm : Gost_R3410_AsymmetricAlgorithm<Gost_R3410_2012_512_KeyExchangeParams, Gost_R3410_2012_512_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <summary>
|
||||
/// Размер ключа ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public const int DefaultKeySizeValue = 1024;
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма цифровой подписи ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public const string SignatureAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-512";
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма обмена ключами ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public const string KeyExchangeAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2012-512";
|
||||
|
||||
/// <summary>
|
||||
/// Известные наименования алгоритма цифровой подписи ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public static readonly string[] KnownSignatureAlgorithmNames = { SignatureAlgorithmValue };
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_512_AsymmetricAlgorithm() : this(GostCryptoConfig.ProviderType_2012_1024)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_512_AsymmetricAlgorithm(ProviderType providerType) : base(providerType, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_512_AsymmetricAlgorithm(CspParameters providerParameters) : base(providerParameters, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string AlgorithmName => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string SignatureAlgorithm => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string KeyExchangeAlgorithm => KeyExchangeAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int ExchangeAlgId => Constants.CALG_DH_GR3410_2012_512_SF;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int SignatureAlgId => Constants.CALG_GR3410_2012_512;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_2012_512_KeyExchangeParams CreateKeyExchangeParams()
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeParams();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected override Gost_R3410_2012_512_KeyExchangeAlgorithm CreateKeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_2012_512_KeyExchangeParams keyExchangeParameters)
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeAlgorithm(providerType, provHandle, keyHandle, keyExchangeParameters, KeySizeValue, SignatureAlgId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override GostHashAlgorithm CreateHashAlgorithm()
|
||||
{
|
||||
return new Gost_R3411_2012_512_HashAlgorithm(ProviderType, this.GetSafeHandle<SafeProvHandleImpl>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void ValidateHashParameter(byte[] hash)
|
||||
{
|
||||
if (hash == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(hash));
|
||||
}
|
||||
|
||||
if (hash.Length != Gost_R3411_2012_512_HashAlgorithm.DefaultHashSizeValue / 8)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentOutOfRange(nameof(hash), Resources.InvalidHashSize, Gost_R3411_2012_512_HashAlgorithm.DefaultHashSizeValue / 8);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeFormatter CreateKeyExchangeFormatter()
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeFormatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeDeformatter CreateKeyExchangeDeformatter()
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeDeformatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_KeyExchangeXmlSerializer<Gost_R3410_2012_512_KeyExchangeParams> CreateKeyExchangeXmlSerializer()
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeXmlSerializer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_512;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Config;
|
||||
using GostCryptography.Gost_R3411;
|
||||
using GostCryptography.Native;
|
||||
using System.Security;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация алгоритма ГОСТ Р 34.10-2012/512 на основе эфимерного ключа
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_512_EphemeralAsymmetricAlgorithm : Gost_R3410_EphemeralAsymmetricAlgorithm<Gost_R3410_2012_512_KeyExchangeParams, Gost_R3410_2012_512_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <summary>
|
||||
/// Размер ключа ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public const int DefaultKeySizeValue = 1024;
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма цифровой подписи ГОСТ Р 34.10-2012 для ключей длины 512 бит
|
||||
/// </summary>
|
||||
public const string SignatureAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-512";
|
||||
|
||||
/// <summary>
|
||||
/// Наименование алгоритма обмена ключами ГОСТ Р 34.10-2012 для ключей длины 512 бит
|
||||
/// </summary>
|
||||
public const string KeyExchangeAlgorithmValue = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2012-512";
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_512_EphemeralAsymmetricAlgorithm() : this(GostCryptoConfig.ProviderType_2012_1024)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_512_EphemeralAsymmetricAlgorithm(ProviderType providerType) : base(providerType, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_512_EphemeralAsymmetricAlgorithm(Gost_R3410_2012_512_KeyExchangeParams keyParameters) : this(GostCryptoConfig.ProviderType_2012_1024, keyParameters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public Gost_R3410_2012_512_EphemeralAsymmetricAlgorithm(ProviderType providerType, Gost_R3410_2012_512_KeyExchangeParams keyParameters) : base(providerType, keyParameters, DefaultKeySizeValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string AlgorithmName => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string SignatureAlgorithm => SignatureAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string KeyExchangeAlgorithm => KeyExchangeAlgorithmValue;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int ExchangeAlgId => Constants.CALG_DH_GR3410_12_512_EPHEM;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override int SignatureAlgId => Constants.CALG_GR3410_2012_512;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_2012_512_KeyExchangeParams CreateKeyExchangeParams()
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeParams();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected override Gost_R3410_2012_512_KeyExchangeAlgorithm CreateKeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_2012_512_KeyExchangeParams keyExchangeParameters)
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeAlgorithm(providerType, provHandle, keyHandle, keyExchangeParameters, KeySizeValue, SignatureAlgId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override GostHashAlgorithm CreateHashAlgorithm()
|
||||
{
|
||||
return new Gost_R3411_2012_512_HashAlgorithm(ProviderType, this.GetSafeHandle<SafeProvHandleImpl>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeFormatter CreateKeyExchangeFormatter()
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeFormatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override GostKeyExchangeDeformatter CreateKeyExchangeDeformatter()
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeDeformatter(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_KeyExchangeXmlSerializer<Gost_R3410_2012_512_KeyExchangeParams> CreateKeyExchangeXmlSerializer()
|
||||
{
|
||||
return new Gost_R3410_2012_512_KeyExchangeXmlSerializer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_512;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Native;
|
||||
using System.Security;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public sealed class Gost_R3410_2012_512_KeyExchangeAlgorithm : Gost_R3410_KeyExchangeAlgorithm
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[SecurityCritical]
|
||||
public Gost_R3410_2012_512_KeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, Gost_R3410_2012_512_KeyExchangeParams keyExchangeParameters, int keySize, int signatureAlgId)
|
||||
: base(providerType, provHandle, keyHandle, keyExchangeParameters, keySize, signatureAlgId)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_512;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация дешифрования общего секретного ключа по ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_512_KeyExchangeDeformatter : Gost_R3410_KeyExchangeDeformatter<
|
||||
Gost_R3410_2012_512_KeyExchange,
|
||||
Gost_R3410_2012_512_KeyExchangeParams,
|
||||
Gost_R3410_2012_512_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_512_KeyExchangeDeformatter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_512_KeyExchangeDeformatter(AsymmetricAlgorithm privateKey) : base(privateKey)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_512;
|
||||
using GostCryptography.Base;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация шифрования общего секретного ключа по ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_512_KeyExchangeFormatter : Gost_R3410_KeyExchangeFormatter<
|
||||
Gost_R3410_2012_512_KeyExchange,
|
||||
Gost_R3410_2012_512_KeyExchangeParams,
|
||||
Gost_R3410_2012_512_KeyExchangeAlgorithm>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_512_KeyExchangeFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_512_KeyExchangeFormatter(AsymmetricAlgorithm publicKey) : base(publicKey)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Gost_R3410_EphemeralAsymmetricAlgorithm<Gost_R3410_2012_512_KeyExchangeParams, Gost_R3410_2012_512_KeyExchangeAlgorithm> CreateEphemeralAlgorithm(ProviderType providerType, Gost_R3410_2012_512_KeyExchangeParams keyExchangeParameters)
|
||||
{
|
||||
return new Gost_R3410_2012_512_EphemeralAsymmetricAlgorithm(providerType, keyExchangeParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410_2012_512;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// XML-сериализатора параметров ключа цифровой подписи ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_512_KeyExchangeXmlSerializer : Gost_R3410_KeyExchangeXmlSerializer<Gost_R3410_2012_512_KeyExchangeParams>
|
||||
{
|
||||
/// <summary>
|
||||
/// Имя тега с информацией о параметрах ключа ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public const string KeyValueTag = "Gost_R3410_2012_512_KeyValue";
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_512_KeyExchangeXmlSerializer() : base(KeyValueTag)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Gost_R3411;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Информация о свойствах цифровой подписи ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_512_SignatureDescription : GostSignatureDescription
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Gost_R3410_2012_512_SignatureDescription()
|
||||
{
|
||||
KeyAlgorithm = typeof(Gost_R3410_2012_512_AsymmetricAlgorithm).AssemblyQualifiedName;
|
||||
DigestAlgorithm = typeof(Gost_R3411_2012_512_HashAlgorithm).AssemblyQualifiedName;
|
||||
FormatterAlgorithm = typeof(GostSignatureFormatter).AssemblyQualifiedName;
|
||||
DeformatterAlgorithm = typeof(GostSignatureDeformatter).AssemblyQualifiedName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,636 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Native;
|
||||
using GostCryptography.Properties;
|
||||
using GostCryptography.Reflection;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Permissions;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <inheritdoc cref="Gost_R3410_AsymmetricAlgorithmBase{TKeyParams,TKeyAlgorithm}" />
|
||||
public abstract class Gost_R3410_AsymmetricAlgorithm<TKeyParams, TKeyAlgorithm> : Gost_R3410_AsymmetricAlgorithmBase<TKeyParams, TKeyAlgorithm>, ICspAsymmetricAlgorithm, ISafeHandleProvider<SafeProvHandleImpl>, ISafeHandleProvider<SafeKeyHandleImpl>
|
||||
where TKeyParams : Gost_R3410_KeyExchangeParams
|
||||
where TKeyAlgorithm : Gost_R3410_KeyExchangeAlgorithm
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected Gost_R3410_AsymmetricAlgorithm(ProviderType providerType, int keySize) : base(providerType, keySize)
|
||||
{
|
||||
_providerParameters = CreateDefaultProviderParameters();
|
||||
InitKeyContainer(_providerParameters, out _isRandomKeyContainer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор
|
||||
/// </summary>
|
||||
/// <param name="providerParameters">Параметры криптографического провайдера</param>
|
||||
/// <param name="keySize">Размер ключа в битах</param>
|
||||
[SecuritySafeCritical]
|
||||
protected Gost_R3410_AsymmetricAlgorithm(CspParameters providerParameters, int keySize) : base((ProviderType)providerParameters.ProviderType, keySize)
|
||||
{
|
||||
_providerParameters = CopyExistingProviderParameters(providerParameters);
|
||||
InitKeyContainer(_providerParameters, out _isRandomKeyContainer);
|
||||
}
|
||||
|
||||
private readonly CspParameters _providerParameters;
|
||||
private readonly bool _isRandomKeyContainer;
|
||||
private bool _isPersistentKey;
|
||||
private bool _isPublicKeyOnly;
|
||||
|
||||
[SecurityCritical]
|
||||
private SafeProvHandleImpl _providerHandle;
|
||||
[SecurityCritical]
|
||||
private volatile SafeKeyHandleImpl _keyHandle;
|
||||
|
||||
/// <inheritdoc />
|
||||
SafeProvHandleImpl ISafeHandleProvider<SafeProvHandleImpl>.SafeHandle
|
||||
{
|
||||
[SecurityCritical]
|
||||
get
|
||||
{
|
||||
GetKeyPair();
|
||||
|
||||
return _providerHandle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
SafeKeyHandleImpl ISafeHandleProvider<SafeKeyHandleImpl>.SafeHandle
|
||||
{
|
||||
[SecurityCritical]
|
||||
get
|
||||
{
|
||||
GetKeyPair();
|
||||
|
||||
return _keyHandle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int KeySize
|
||||
{
|
||||
[SecuritySafeCritical]
|
||||
get
|
||||
{
|
||||
GetKeyPair();
|
||||
|
||||
return base.KeySize;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Хранить ключ в криптографическом провайдере
|
||||
/// </summary>
|
||||
public bool IsPersistentKey
|
||||
{
|
||||
[SecuritySafeCritical]
|
||||
get
|
||||
{
|
||||
if (_providerHandle == null)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (_providerHandle == null)
|
||||
{
|
||||
_providerHandle = CreateProviderHandle(_providerParameters, _isRandomKeyContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _isPersistentKey;
|
||||
}
|
||||
[SecuritySafeCritical]
|
||||
set
|
||||
{
|
||||
var currentValue = IsPersistentKey;
|
||||
|
||||
if (currentValue != value)
|
||||
{
|
||||
var keyContainerPermission = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
|
||||
var containerAccessEntry = new KeyContainerPermissionAccessEntry(_providerParameters, value ? KeyContainerPermissionFlags.Create : KeyContainerPermissionFlags.Delete);
|
||||
keyContainerPermission.AccessEntries.Add(containerAccessEntry);
|
||||
keyContainerPermission.Demand();
|
||||
|
||||
_isPersistentKey = value;
|
||||
_providerHandle.DeleteOnClose = !_isPersistentKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Имеется доступ только к открытому ключу
|
||||
/// </summary>
|
||||
public bool IsPublicKeyOnly
|
||||
{
|
||||
[SecuritySafeCritical]
|
||||
get
|
||||
{
|
||||
GetKeyPair();
|
||||
|
||||
return _isPublicKeyOnly;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public CspKeyContainerInfo CspKeyContainerInfo
|
||||
{
|
||||
[SecuritySafeCritical]
|
||||
get
|
||||
{
|
||||
GetKeyPair();
|
||||
|
||||
return CspKeyContainerInfoHelper.CreateCspKeyContainerInfo(_providerParameters, _isRandomKeyContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public byte[] ExportCspBlob(bool includePrivateParameters)
|
||||
{
|
||||
GetKeyPair();
|
||||
|
||||
if (includePrivateParameters)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.UserExportBulkBlob);
|
||||
}
|
||||
|
||||
return CryptoApiHelper.ExportCspBlob(_keyHandle, SafeKeyHandleImpl.InvalidHandle, Constants.PUBLICKEYBLOB);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public void ImportCspBlob(byte[] importedKeyBytes)
|
||||
{
|
||||
if (importedKeyBytes == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(importedKeyBytes));
|
||||
}
|
||||
|
||||
if (!IsPublicKeyBlob(importedKeyBytes))
|
||||
{
|
||||
throw ExceptionUtility.Argument(nameof(importedKeyBytes), Resources.UserImportBulkBlob);
|
||||
}
|
||||
|
||||
var hProv = CryptoApiHelper.GetProviderHandle(ProviderType);
|
||||
|
||||
_providerParameters.KeyNumber = CryptoApiHelper.ImportCspBlob(importedKeyBytes, hProv, SafeKeyHandleImpl.InvalidHandle, out var hKey);
|
||||
_providerHandle = hProv;
|
||||
_keyHandle = hKey;
|
||||
|
||||
_isPublicKeyOnly = true;
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
public void ImportCspBlob(byte[] encodedParameters, byte[] encodedKeyValue)
|
||||
{
|
||||
var keyParams = CreateKeyExchangeParams();
|
||||
keyParams.DecodeParameters(encodedParameters);
|
||||
keyParams.DecodePublicKey(encodedKeyValue);
|
||||
|
||||
var keyBytes = CryptoApiHelper.EncodePublicBlob(keyParams, KeySizeValue, SignatureAlgId);
|
||||
|
||||
ImportCspBlob(keyBytes);
|
||||
}
|
||||
|
||||
private static bool IsPublicKeyBlob(byte[] importedKeyBytes)
|
||||
{
|
||||
if ((importedKeyBytes[0] != Constants.PUBLICKEYBLOB) || (importedKeyBytes.Length < 12))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var gostKeyMask = BitConverter.GetBytes(Constants.GR3410_1_MAGIC);
|
||||
|
||||
return (importedKeyBytes[8] == gostKeyMask[0])
|
||||
&& (importedKeyBytes[9] == gostKeyMask[1])
|
||||
&& (importedKeyBytes[10] == gostKeyMask[2])
|
||||
&& (importedKeyBytes[11] == gostKeyMask[3]);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override byte[] CreateSignature(byte[] hash)
|
||||
{
|
||||
return SignHash(hash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вычисляет цифровую подпись
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
public byte[] CreateSignature(byte[] data, object hashAlgorithm)
|
||||
{
|
||||
var hash = CryptographyUtils.ObjToHashAlgorithm(hashAlgorithm).ComputeHash(data);
|
||||
return SignHash(hash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вычисляет цифровую подпись
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
public byte[] CreateSignature(Stream data, object hashAlgorithm)
|
||||
{
|
||||
var hash = CryptographyUtils.ObjToHashAlgorithm(hashAlgorithm).ComputeHash(data);
|
||||
return SignHash(hash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вычисляет цифровую подпись
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
public byte[] CreateSignature(byte[] data, int dataOffset, int dataLength, object hashAlgorithm)
|
||||
{
|
||||
var hash = CryptographyUtils.ObjToHashAlgorithm(hashAlgorithm).ComputeHash(data, dataOffset, dataLength);
|
||||
return SignHash(hash);
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
private byte[] SignHash(byte[] hash)
|
||||
{
|
||||
ValidateHashParameter(hash);
|
||||
|
||||
if (IsPublicKeyOnly)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.NoPrivateKey);
|
||||
}
|
||||
|
||||
GetKeyPair();
|
||||
|
||||
if (!CspKeyContainerInfo.RandomlyGenerated)
|
||||
{
|
||||
var keyContainerPermission = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
|
||||
var keyContainerAccessEntry = new KeyContainerPermissionAccessEntry(_providerParameters, KeyContainerPermissionFlags.Sign);
|
||||
keyContainerPermission.AccessEntries.Add(keyContainerAccessEntry);
|
||||
keyContainerPermission.Demand();
|
||||
}
|
||||
|
||||
using (var hashAlgorithm = CreateHashAlgorithm())
|
||||
{
|
||||
var hashHandleProvider = (ISafeHandleProvider<SafeHashHandleImpl>)hashAlgorithm;
|
||||
return CryptoApiHelper.SignValue(_providerHandle, hashHandleProvider.SafeHandle, _providerParameters.KeyNumber, hash);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool VerifySignature(byte[] hash, byte[] signature)
|
||||
{
|
||||
return VerifyHash(hash, signature);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет цифровую подпись
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
public bool VerifySignature(byte[] buffer, object hashAlgorithm, byte[] signature)
|
||||
{
|
||||
var hash = CryptographyUtils.ObjToHashAlgorithm(hashAlgorithm).ComputeHash(buffer);
|
||||
return VerifyHash(hash, signature);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет цифровую подпись
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
public bool VerifySignature(Stream inputStream, object hashAlgorithm, byte[] signature)
|
||||
{
|
||||
var hash = CryptographyUtils.ObjToHashAlgorithm(hashAlgorithm).ComputeHash(inputStream);
|
||||
return VerifyHash(hash, signature);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет цифровую подпись
|
||||
/// </summary>
|
||||
public bool VerifySignature(byte[] data, int dataOffset, int dataLength, object hashAlgorithm, byte[] signature)
|
||||
{
|
||||
var hash = CryptographyUtils.ObjToHashAlgorithm(hashAlgorithm).ComputeHash(data, dataOffset, dataLength);
|
||||
return VerifyHash(hash, signature);
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
private bool VerifyHash(byte[] hash, byte[] signature)
|
||||
{
|
||||
ValidateHashParameter(hash);
|
||||
|
||||
if (signature == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(signature));
|
||||
}
|
||||
|
||||
GetKeyPair();
|
||||
|
||||
using (var hashAlgorithm = CreateHashAlgorithm())
|
||||
{
|
||||
var hashHandleProvider = (ISafeHandleProvider<SafeHashHandleImpl>)hashAlgorithm;
|
||||
return CryptoApiHelper.VerifySign(_providerHandle, hashHandleProvider.SafeHandle, _keyHandle, hash, signature);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет корректность хэша
|
||||
/// </summary>
|
||||
protected abstract void ValidateHashParameter(byte[] hash);
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override TKeyAlgorithm CreateKeyExchange(TKeyParams keyParameters)
|
||||
{
|
||||
GetKeyPair();
|
||||
|
||||
return CreateKeyExchangeAlgorithm(ProviderType, _providerHandle, _keyHandle, (TKeyParams)keyParameters.Clone());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override TKeyParams ExportParameters(bool includePrivateKey)
|
||||
{
|
||||
if (includePrivateKey)
|
||||
{
|
||||
throw ExceptionUtility.NotSupported(Resources.UserExportBulkKeyNotSupported);
|
||||
}
|
||||
|
||||
GetKeyPair();
|
||||
|
||||
return CryptoApiHelper.ExportPublicKey(_keyHandle, CreateKeyExchangeParams(), KeySizeValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override void ImportParameters(TKeyParams keyParameters)
|
||||
{
|
||||
if (keyParameters.PrivateKey != null)
|
||||
{
|
||||
throw ExceptionUtility.NotSupported(Resources.UserImportBulkKeyNotSupported);
|
||||
}
|
||||
|
||||
_keyHandle.TryDispose();
|
||||
|
||||
var hProv = CryptoApiHelper.GetProviderHandle(ProviderType);
|
||||
|
||||
var importedKeyBytes = CryptoApiHelper.EncodePublicBlob(keyParameters.Clone(), KeySizeValue, SignatureAlgId);
|
||||
|
||||
_providerParameters.KeyNumber = CryptoApiHelper.ImportCspBlob(importedKeyBytes, hProv, SafeKeyHandleImpl.InvalidHandle, out var keyHandle);
|
||||
_providerHandle = hProv;
|
||||
_keyHandle = keyHandle;
|
||||
|
||||
_isPublicKeyOnly = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Установка пароля доступа к контейнеру
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
[SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
|
||||
public void SetContainerPassword(SecureString password)
|
||||
{
|
||||
if (IsPublicKeyOnly)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.NoPrivateKey);
|
||||
}
|
||||
|
||||
GetKeyPair();
|
||||
SetSignatureKeyPassword(_providerHandle, password, _providerParameters.KeyNumber);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_keyHandle.TryDispose();
|
||||
|
||||
if (!_isPublicKeyOnly)
|
||||
{
|
||||
_providerHandle.TryDispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
private void GetKeyPair()
|
||||
{
|
||||
if (_keyHandle == null)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (_keyHandle == null)
|
||||
{
|
||||
GetKeyPairValue(_providerParameters, _isRandomKeyContainer, out var providerHandle, out var keyHandle);
|
||||
|
||||
_providerHandle = providerHandle;
|
||||
_keyHandle = keyHandle;
|
||||
|
||||
_isPersistentKey = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
private void GetKeyPairValue(CspParameters providerParams, bool randomKeyContainer, out SafeProvHandleImpl providerHandle, out SafeKeyHandleImpl keyHandle)
|
||||
{
|
||||
SafeProvHandleImpl resultProviderHandle = null;
|
||||
SafeKeyHandleImpl resultKeyHandle = null;
|
||||
|
||||
try
|
||||
{
|
||||
resultProviderHandle = CreateProviderHandle(providerParams, randomKeyContainer);
|
||||
|
||||
if (providerParams.ParentWindowHandle != IntPtr.Zero)
|
||||
{
|
||||
CryptoApiHelper.SetProviderParameter(resultProviderHandle, providerParams.KeyNumber, Constants.PP_CLIENT_HWND, providerParams.ParentWindowHandle);
|
||||
}
|
||||
else if (providerParams.KeyPassword != null)
|
||||
{
|
||||
SetSignatureKeyPassword(resultProviderHandle, providerParams.KeyPassword, providerParams.KeyNumber);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
resultKeyHandle = CryptoApiHelper.GetUserKey(resultProviderHandle, providerParams.KeyNumber);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
var errorCode = Marshal.GetHRForException(exception);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
if (((providerParams.Flags & CspProviderFlags.UseExistingKey) != CspProviderFlags.NoFlags) || (errorCode != Constants.NTE_NO_KEY))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
resultKeyHandle = CryptoApiHelper.GenerateKey(resultProviderHandle, providerParams.KeyNumber, providerParams.Flags);
|
||||
}
|
||||
}
|
||||
|
||||
var keyAlgIdInverted = CryptoApiHelper.GetKeyParameter(resultKeyHandle, Constants.KP_ALGID);
|
||||
var keyAlgId = keyAlgIdInverted[0] | (keyAlgIdInverted[1] << 8) | (keyAlgIdInverted[2] << 16) | (keyAlgIdInverted[3] << 24);
|
||||
|
||||
if ((keyAlgId != ExchangeAlgId) && (keyAlgId != SignatureAlgId))
|
||||
{
|
||||
throw ExceptionUtility.NotSupported(Resources.KeyAlgorithmNotSupported);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
resultProviderHandle?.Close();
|
||||
resultKeyHandle?.Close();
|
||||
throw;
|
||||
}
|
||||
|
||||
providerHandle = resultProviderHandle;
|
||||
keyHandle = resultKeyHandle;
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
private static SafeProvHandleImpl CreateProviderHandle(CspParameters providerParams, bool randomKeyContainer)
|
||||
{
|
||||
SafeProvHandleImpl providerHandle = null;
|
||||
|
||||
var keyContainerPermission = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
|
||||
|
||||
try
|
||||
{
|
||||
providerHandle = CryptoApiHelper.OpenProvider(providerParams);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
var errorCode = Marshal.GetHRForException(exception);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
if (((providerParams.Flags & CspProviderFlags.UseExistingKey) != CspProviderFlags.NoFlags)
|
||||
|| ((errorCode != Constants.NTE_KEYSET_NOT_DEF)
|
||||
&& (errorCode != Constants.NTE_BAD_KEYSET)
|
||||
&& (errorCode != Constants.SCARD_W_CANCELLED_BY_USER)))
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(errorCode);
|
||||
}
|
||||
|
||||
if (!randomKeyContainer)
|
||||
{
|
||||
var containerAccessEntry = new KeyContainerPermissionAccessEntry(providerParams, KeyContainerPermissionFlags.Create);
|
||||
keyContainerPermission.AccessEntries.Add(containerAccessEntry);
|
||||
keyContainerPermission.Demand();
|
||||
}
|
||||
|
||||
providerHandle = CryptoApiHelper.CreateProvider(providerParams);
|
||||
|
||||
return providerHandle;
|
||||
}
|
||||
}
|
||||
|
||||
if (!randomKeyContainer)
|
||||
{
|
||||
var containerAccessEntry = new KeyContainerPermissionAccessEntry(providerParams, KeyContainerPermissionFlags.Open);
|
||||
keyContainerPermission.AccessEntries.Add(containerAccessEntry);
|
||||
keyContainerPermission.Demand();
|
||||
}
|
||||
|
||||
return providerHandle;
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
private static void SetSignatureKeyPassword(SafeProvHandleImpl hProv, SecureString keyPassword, int keyNumber)
|
||||
{
|
||||
if (keyPassword == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyPassword));
|
||||
}
|
||||
|
||||
var keyPasswordData = Marshal.SecureStringToCoTaskMemAnsi(keyPassword);
|
||||
|
||||
try
|
||||
{
|
||||
CryptoApiHelper.SetProviderParameter(hProv, keyNumber, Constants.PP_SIGNATURE_PIN, keyPasswordData);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (keyPasswordData != IntPtr.Zero)
|
||||
{
|
||||
Marshal.ZeroFreeCoTaskMemAnsi(keyPasswordData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CspParameters CreateDefaultProviderParameters(CspProviderFlags defaultFlags = CspProviderFlags.UseMachineKeyStore)
|
||||
{
|
||||
return new CspParameters(ProviderType.ToInt())
|
||||
{
|
||||
Flags = defaultFlags
|
||||
};
|
||||
}
|
||||
|
||||
private CspParameters CopyExistingProviderParameters(CspParameters providerParameters)
|
||||
{
|
||||
ValidateProviderParameters(providerParameters.Flags);
|
||||
|
||||
return new CspParameters(providerParameters.ProviderType, providerParameters.ProviderName, providerParameters.KeyContainerName)
|
||||
{
|
||||
Flags = providerParameters.Flags,
|
||||
KeyNumber = providerParameters.KeyNumber
|
||||
};
|
||||
}
|
||||
|
||||
private static void ValidateProviderParameters(CspProviderFlags flags)
|
||||
{
|
||||
// Если информацию о провайдере нужно взять из текущего ключа
|
||||
if ((flags & CspProviderFlags.UseExistingKey) != CspProviderFlags.NoFlags)
|
||||
{
|
||||
const CspProviderFlags notExpectedFlags = CspProviderFlags.UseUserProtectedKey
|
||||
| CspProviderFlags.UseArchivableKey
|
||||
| CspProviderFlags.UseNonExportableKey;
|
||||
|
||||
if ((flags & notExpectedFlags) != CspProviderFlags.NoFlags)
|
||||
{
|
||||
throw ExceptionUtility.Argument(nameof(flags), Resources.InvalidCspProviderFlags);
|
||||
}
|
||||
}
|
||||
|
||||
// Если пользователь должен сам выбрать ключ (например, в диалоге)
|
||||
if ((flags & CspProviderFlags.UseUserProtectedKey) != CspProviderFlags.NoFlags)
|
||||
{
|
||||
if (!Environment.UserInteractive)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.UserInteractiveNotSupported);
|
||||
}
|
||||
|
||||
new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
|
||||
}
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
private void InitKeyContainer(CspParameters providerParameters, out bool randomKeyContainer)
|
||||
{
|
||||
// Установка типа ключа
|
||||
if (providerParameters.KeyNumber == -1)
|
||||
{
|
||||
providerParameters.KeyNumber = (int)KeyNumber.Exchange;
|
||||
}
|
||||
else if (providerParameters.KeyNumber == SignatureAlgId)
|
||||
{
|
||||
providerParameters.KeyNumber = (int)KeyNumber.Signature;
|
||||
}
|
||||
else if (providerParameters.KeyNumber == ExchangeAlgId)
|
||||
{
|
||||
providerParameters.KeyNumber = (int)KeyNumber.Exchange;
|
||||
}
|
||||
|
||||
// Использовать автогенерированный контейнер
|
||||
randomKeyContainer = ((providerParameters.KeyContainerName == null) && ((providerParameters.Flags & CspProviderFlags.UseDefaultKeyContainer) == CspProviderFlags.NoFlags));
|
||||
|
||||
if (randomKeyContainer)
|
||||
{
|
||||
providerParameters.KeyContainerName = Guid.NewGuid().ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
GetKeyPair();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Native;
|
||||
using System.Security;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Базовый класс для всех реализаций алгоритма ГОСТ Р 34.10
|
||||
/// </summary>
|
||||
/// <typeparam name="TKeyParams">Параметры ключа цифровой подписи ГОСТ Р 34.10</typeparam>
|
||||
/// <typeparam name="TKeyAlgorithm">Алгоритм общего секретного ключа ГОСТ Р 34.10</typeparam>
|
||||
public abstract class Gost_R3410_AsymmetricAlgorithmBase<TKeyParams, TKeyAlgorithm> : GostAsymmetricAlgorithm
|
||||
where TKeyParams : Gost_R3410_KeyExchangeParams
|
||||
where TKeyAlgorithm : Gost_R3410_KeyExchangeAlgorithm
|
||||
{
|
||||
/// <inheritdoc cref="GostAsymmetricAlgorithm(ProviderType,int)" />
|
||||
protected Gost_R3410_AsymmetricAlgorithmBase(ProviderType providerType, int keySize) : base(providerType, keySize)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор алгоритма обмена ключей
|
||||
/// </summary>
|
||||
protected abstract int ExchangeAlgId { get; }
|
||||
/// <summary>
|
||||
/// Идентификатор алгоритма цифровой подписи
|
||||
/// </summary>
|
||||
protected abstract int SignatureAlgId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр <typeparamref name="TKeyParams"/>
|
||||
/// </summary>
|
||||
protected abstract TKeyParams CreateKeyExchangeParams();
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр <typeparamref name="TKeyAlgorithm"/>
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
protected abstract TKeyAlgorithm CreateKeyExchangeAlgorithm(ProviderType providerType, SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle, TKeyParams keyExchangeParameters);
|
||||
|
||||
/// <summary>
|
||||
/// Создает общий секретный ключ
|
||||
/// </summary>
|
||||
/// <param name="keyParameters">Параметры открытого ключа, используемого для создания общего секретного ключа</param>
|
||||
public abstract TKeyAlgorithm CreateKeyExchange(TKeyParams keyParameters);
|
||||
|
||||
/// <summary>
|
||||
/// Экспортирует (шифрует) параметры ключа, используемого для создания общего секретного ключа
|
||||
/// </summary>
|
||||
/// <param name="includePrivateKey">Включить секретный ключ</param>
|
||||
public abstract TKeyParams ExportParameters(bool includePrivateKey);
|
||||
|
||||
/// <summary>
|
||||
/// Импортирует (дешифрует) параметры ключа, используемого для создания общего секретного ключа
|
||||
/// </summary>
|
||||
/// <param name="keyParameters">Параметры ключа, используемого для создания общего секретного ключа</param>
|
||||
public abstract void ImportParameters(TKeyParams keyParameters);
|
||||
|
||||
/// <summary>
|
||||
/// Создает XML-сериализатор параметров ключа цифровой подписи
|
||||
/// </summary>
|
||||
protected abstract Gost_R3410_KeyExchangeXmlSerializer<TKeyParams> CreateKeyExchangeXmlSerializer();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToXmlString(bool includePrivateKey)
|
||||
{
|
||||
var keyParameters = ExportParameters(includePrivateKey);
|
||||
var xmlSerializer = CreateKeyExchangeXmlSerializer();
|
||||
return xmlSerializer.Serialize(keyParameters);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void FromXmlString(string keyParametersXml)
|
||||
{
|
||||
var xmlSerializer = CreateKeyExchangeXmlSerializer();
|
||||
var keyParameters = xmlSerializer.Deserialize(keyParametersXml, CreateKeyExchangeParams());
|
||||
ImportParameters(keyParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Native;
|
||||
using GostCryptography.Properties;
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация алгоритма формирования общих ключей на основе алгоритма ГОСТ Р 34.10 и эфимерного ключа
|
||||
/// </summary>
|
||||
public abstract class Gost_R3410_EphemeralAsymmetricAlgorithm<TKeyParams, TKeyAlgorithm> : Gost_R3410_AsymmetricAlgorithmBase<TKeyParams, TKeyAlgorithm>, ISafeHandleProvider<SafeProvHandleImpl>, ISafeHandleProvider<SafeKeyHandleImpl>
|
||||
where TKeyParams : Gost_R3410_KeyExchangeParams
|
||||
where TKeyAlgorithm : Gost_R3410_KeyExchangeAlgorithm
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected Gost_R3410_EphemeralAsymmetricAlgorithm(ProviderType providerType, int keySize) : base(providerType, keySize)
|
||||
{
|
||||
_providerHandle = CryptoApiHelper.GetProviderHandle(ProviderType).DangerousAddRef();
|
||||
_keyHandle = CryptoApiHelper.GenerateKey(_providerHandle, ExchangeAlgId, CspProviderFlags.NoFlags);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор
|
||||
/// </summary>
|
||||
/// <param name="providerType">Тип криптографического провайдера</param>
|
||||
/// <param name="keyParameters">Параметры ключа, используемого для создания общего секретного ключа</param>
|
||||
/// <param name="keySize">Размер ключа в битах</param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
/// <remarks>
|
||||
/// В параметре <paramref name="keyParameters"/> достаточно передать идентификатор OID параметров хэширования
|
||||
/// <see cref="Gost_R3410_KeyExchangeParams.DigestParamSet"/> и идентификатор OID параметров открытого ключа
|
||||
/// <see cref="Gost_R3410_KeyExchangeParams.PublicKeyParamSet"/>. Остальные параметры не используются.
|
||||
/// </remarks>
|
||||
[SecuritySafeCritical]
|
||||
protected Gost_R3410_EphemeralAsymmetricAlgorithm(ProviderType providerType, TKeyParams keyParameters, int keySize) : base(providerType, keySize)
|
||||
{
|
||||
if (keyParameters == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyParameters));
|
||||
}
|
||||
|
||||
_providerHandle = CryptoApiHelper.GetProviderHandle(ProviderType).DangerousAddRef();
|
||||
_keyHandle = CryptoApiHelper.GenerateDhEphemeralKey(providerType, _providerHandle, ExchangeAlgId, keyParameters.DigestParamSet, keyParameters.PublicKeyParamSet);
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
private readonly SafeProvHandleImpl _providerHandle;
|
||||
[SecurityCritical]
|
||||
private readonly SafeKeyHandleImpl _keyHandle;
|
||||
|
||||
/// <inheritdoc />
|
||||
SafeProvHandleImpl ISafeHandleProvider<SafeProvHandleImpl>.SafeHandle
|
||||
{
|
||||
[SecurityCritical]
|
||||
get => _providerHandle;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
SafeKeyHandleImpl ISafeHandleProvider<SafeKeyHandleImpl>.SafeHandle
|
||||
{
|
||||
[SecurityCritical]
|
||||
get => _keyHandle;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override byte[] CreateSignature(byte[] hash)
|
||||
{
|
||||
throw ExceptionUtility.NotSupported(Resources.EphemKeyOperationNotSupported);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool VerifySignature(byte[] hash, byte[] signature)
|
||||
{
|
||||
throw ExceptionUtility.NotSupported(Resources.EphemKeyOperationNotSupported);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override TKeyAlgorithm CreateKeyExchange(TKeyParams keyParameters)
|
||||
{
|
||||
return CreateKeyExchangeAlgorithm(ProviderType, _providerHandle, _keyHandle, (TKeyParams)keyParameters.Clone());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
public override TKeyParams ExportParameters(bool includePrivateKey)
|
||||
{
|
||||
if (includePrivateKey)
|
||||
{
|
||||
throw ExceptionUtility.NotSupported(Resources.EphemKeyOperationNotSupported);
|
||||
}
|
||||
|
||||
return CryptoApiHelper.ExportPublicKey(_keyHandle, CreateKeyExchangeParams(), KeySizeValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ImportParameters(TKeyParams keyParameters)
|
||||
{
|
||||
throw ExceptionUtility.NotSupported(Resources.EphemKeyOperationNotSupported);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_keyHandle.TryDispose();
|
||||
_providerHandle.TryDispose();
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,163 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Properties;
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Базовый класс для реализации дешифрования общего секретного ключа по ГОСТ Р 34.10
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">Информация о ключе цифровой подписи ГОСТ Р 34.10</typeparam>
|
||||
/// <typeparam name="TKeyParams">Параметры ключа цифровой подписи ГОСТ Р 34.10</typeparam>
|
||||
/// <typeparam name="TKeyAlgorithm">Алгоритм общего секретного ключа ГОСТ Р 34.10</typeparam>
|
||||
public abstract class Gost_R3410_KeyExchangeDeformatter<TKey, TKeyParams, TKeyAlgorithm> : GostKeyExchangeDeformatter
|
||||
where TKey : Gost_R3410_KeyExchange, new()
|
||||
where TKeyParams : Gost_R3410_KeyExchangeParams
|
||||
where TKeyAlgorithm : Gost_R3410_KeyExchangeAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Конструктор
|
||||
/// </summary>
|
||||
protected Gost_R3410_KeyExchangeDeformatter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор
|
||||
/// </summary>
|
||||
/// <param name="privateKey">Секретный ключ для расшифровки общего секретного ключа</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
protected Gost_R3410_KeyExchangeDeformatter(AsymmetricAlgorithm privateKey)
|
||||
{
|
||||
SetKey(privateKey);
|
||||
}
|
||||
|
||||
private Gost_R3410_AsymmetricAlgorithmBase<TKeyParams, TKeyAlgorithm> _privateKey;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SetKey(AsymmetricAlgorithm privateKey)
|
||||
{
|
||||
if (privateKey == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(privateKey));
|
||||
}
|
||||
|
||||
if (!(privateKey is Gost_R3410_AsymmetricAlgorithmBase<TKeyParams, TKeyAlgorithm> gostPublicKey))
|
||||
{
|
||||
throw ExceptionUtility.ArgumentOutOfRange(nameof(privateKey), Resources.ShouldSupportGost3410);
|
||||
}
|
||||
|
||||
_privateKey = gostPublicKey;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override byte[] DecryptKeyExchange(byte[] encryptedKeyExchangeData)
|
||||
{
|
||||
var symmetricAlgorithm = DecryptKeyExchangeAlgorithm(encryptedKeyExchangeData);
|
||||
|
||||
return symmetricAlgorithm.Key;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override SymmetricAlgorithm DecryptKeyExchangeAlgorithm(byte[] encryptedKeyExchangeData)
|
||||
{
|
||||
if (encryptedKeyExchangeData == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(encryptedKeyExchangeData));
|
||||
}
|
||||
|
||||
var keyExchange = new TKey();
|
||||
keyExchange.Decode(encryptedKeyExchangeData);
|
||||
|
||||
return DecryptKeyExchangeAlgorithm(keyExchange);
|
||||
}
|
||||
|
||||
private SymmetricAlgorithm DecryptKeyExchangeAlgorithm(TKey encryptedKeyExchangeInfo)
|
||||
{
|
||||
if (encryptedKeyExchangeInfo == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(encryptedKeyExchangeInfo));
|
||||
}
|
||||
|
||||
var keyExchangeParameters = (TKeyParams)encryptedKeyExchangeInfo.TransportParameters;
|
||||
var keyExchangeAlg = _privateKey.CreateKeyExchange(keyExchangeParameters);
|
||||
var encodedKeyExchangeInfo = encryptedKeyExchangeInfo.SessionEncryptedKey.Encode();
|
||||
|
||||
return keyExchangeAlg.DecodeKeyExchange(encodedKeyExchangeInfo, GostKeyExchangeExportMethod.CryptoProKeyExport);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,162 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_28147_89;
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410;
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Gost_28147_89;
|
||||
using GostCryptography.Properties;
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Базовый класс для реализации шифрования общего секретного ключа по ГОСТ Р 34.10
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">Информация о ключе цифровой подписи ГОСТ Р 34.10</typeparam>
|
||||
/// <typeparam name="TKeyParams">Параметры ключа цифровой подписи ГОСТ Р 34.10</typeparam>
|
||||
/// <typeparam name="TKeyAlgorithm">Алгоритм общего секретного ключа ГОСТ Р 34.10</typeparam>
|
||||
public abstract class Gost_R3410_KeyExchangeFormatter<TKey, TKeyParams, TKeyAlgorithm> : GostKeyExchangeFormatter
|
||||
where TKey : Gost_R3410_KeyExchange, new()
|
||||
where TKeyParams : Gost_R3410_KeyExchangeParams
|
||||
where TKeyAlgorithm : Gost_R3410_KeyExchangeAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Конструктор
|
||||
/// </summary>
|
||||
protected Gost_R3410_KeyExchangeFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор
|
||||
/// </summary>
|
||||
/// <param name="publicKey">Открытый ключ для шифрации общего секретного ключа</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
protected Gost_R3410_KeyExchangeFormatter(AsymmetricAlgorithm publicKey)
|
||||
{
|
||||
SetKey(publicKey);
|
||||
}
|
||||
|
||||
private Gost_R3410_AsymmetricAlgorithmBase<TKeyParams, TKeyAlgorithm> _publicKey;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Parameters => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SetKey(AsymmetricAlgorithm publicKey)
|
||||
{
|
||||
if (publicKey == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(publicKey));
|
||||
}
|
||||
|
||||
if (!(publicKey is Gost_R3410_AsymmetricAlgorithmBase<TKeyParams, TKeyAlgorithm> gostPublicKey))
|
||||
{
|
||||
throw ExceptionUtility.ArgumentOutOfRange(nameof(publicKey), Resources.ShouldSupportGost3410);
|
||||
}
|
||||
|
||||
_publicKey = gostPublicKey;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override byte[] CreateKeyExchange(byte[] keyExchangeData)
|
||||
{
|
||||
if (keyExchangeData == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyExchangeData));
|
||||
}
|
||||
|
||||
using (var keyExchangeAlgorithm = new Gost_28147_89_SymmetricAlgorithm(_publicKey.ProviderType))
|
||||
{
|
||||
keyExchangeAlgorithm.Key = keyExchangeData;
|
||||
|
||||
return CreateKeyExchangeData(keyExchangeAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override byte[] CreateKeyExchange(byte[] keyExchangeData, Type keyExchangeAlgorithmType)
|
||||
{
|
||||
if (keyExchangeData == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyExchangeData));
|
||||
}
|
||||
|
||||
if (keyExchangeAlgorithmType == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyExchangeAlgorithmType));
|
||||
}
|
||||
|
||||
if (!typeof(GostSymmetricAlgorithm).IsAssignableFrom(keyExchangeAlgorithmType))
|
||||
{
|
||||
throw ExceptionUtility.ArgumentOutOfRange(nameof(keyExchangeAlgorithmType));
|
||||
}
|
||||
|
||||
GostSymmetricAlgorithm keyExchangeAlgorithm;
|
||||
|
||||
if (_publicKey != null)
|
||||
{
|
||||
var constructorInfo = keyExchangeAlgorithmType.GetConstructor(new[] { typeof(ProviderType) });
|
||||
keyExchangeAlgorithm = (GostSymmetricAlgorithm)constructorInfo.Invoke(new object[] { _publicKey.ProviderType });
|
||||
}
|
||||
else
|
||||
{
|
||||
keyExchangeAlgorithm = (GostSymmetricAlgorithm)Activator.CreateInstance(keyExchangeAlgorithmType);
|
||||
}
|
||||
|
||||
using (keyExchangeAlgorithm)
|
||||
{
|
||||
keyExchangeAlgorithm.Key = keyExchangeData;
|
||||
|
||||
return CreateKeyExchangeData(keyExchangeAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override byte[] CreateKeyExchangeData(SymmetricAlgorithm keyExchangeAlgorithm)
|
||||
{
|
||||
if (keyExchangeAlgorithm == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyExchangeAlgorithm));
|
||||
}
|
||||
|
||||
var keyExchangeInfo = CreateKeyExchangeInfo(keyExchangeAlgorithm);
|
||||
|
||||
return keyExchangeInfo.Encode();
|
||||
}
|
||||
|
||||
private TKey CreateKeyExchangeInfo(SymmetricAlgorithm keyExchangeAlgorithm)
|
||||
{
|
||||
if (keyExchangeAlgorithm == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyExchangeAlgorithm));
|
||||
}
|
||||
|
||||
var keyExchange = new TKey();
|
||||
var keyExchangeParameters = _publicKey.ExportParameters(false);
|
||||
|
||||
using (var keyExchangeAsym = CreateEphemeralAlgorithm(_publicKey.ProviderType, keyExchangeParameters))
|
||||
{
|
||||
byte[] encodedKeyExchangeInfo;
|
||||
|
||||
using (var keyExchangeAlg = keyExchangeAsym.CreateKeyExchange(keyExchangeParameters))
|
||||
{
|
||||
encodedKeyExchangeInfo = keyExchangeAlg.EncodeKeyExchange(keyExchangeAlgorithm, GostKeyExchangeExportMethod.CryptoProKeyExport);
|
||||
}
|
||||
|
||||
var keyExchangeInfo = new Gost_28147_89_KeyExchangeInfo();
|
||||
keyExchangeInfo.Decode(encodedKeyExchangeInfo);
|
||||
|
||||
keyExchange.SessionEncryptedKey = keyExchangeInfo;
|
||||
keyExchange.TransportParameters = keyExchangeAsym.ExportParameters(false);
|
||||
}
|
||||
|
||||
return keyExchange;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр алгоритма шифрования общего секретного ключа
|
||||
/// </summary>
|
||||
protected abstract Gost_R3410_EphemeralAsymmetricAlgorithm<TKeyParams, TKeyAlgorithm> CreateEphemeralAlgorithm(ProviderType providerType, TKeyParams keyExchangeParameters);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,201 @@
|
||||
using GostCryptography.Asn1.Gost.Gost_R3410;
|
||||
using GostCryptography.Properties;
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
|
||||
namespace GostCryptography.Gost_R3410
|
||||
{
|
||||
/// <summary>
|
||||
/// Базовый класс XML-сериализатора параметров ключа цифровой подписи ГОСТ Р 34.10
|
||||
/// </summary>
|
||||
/// <typeparam name="TKeyParams">Параметры ключа цифровой подписи ГОСТ Р 34.10</typeparam>
|
||||
public abstract class Gost_R3410_KeyExchangeXmlSerializer<TKeyParams> where TKeyParams : Gost_R3410_KeyExchangeParams
|
||||
{
|
||||
private const string OidPrefix = "urn:oid:";
|
||||
private const string PublicKeyParametersTag = "PublicKeyParameters";
|
||||
private const string PublicKeyParamSetTag = "publicKeyParamSet";
|
||||
private const string DigestParamSetTag = "digestParamSet";
|
||||
private const string EncryptionParamSetTag = "encryptionParamSet";
|
||||
private const string PublicKeyTag = "PublicKey";
|
||||
private const string PrivateKeyTag = "PrivateKey";
|
||||
|
||||
private readonly string _keyValueTag;
|
||||
|
||||
/// <summary>
|
||||
/// Создает новый экземпляр данного класса
|
||||
/// </summary>
|
||||
/// <param name="keyValueTag">Имя тега с информацией о параметрах ключа</param>
|
||||
protected Gost_R3410_KeyExchangeXmlSerializer(string keyValueTag)
|
||||
{
|
||||
_keyValueTag = keyValueTag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает XML с параметрами ключа
|
||||
/// </summary>
|
||||
public string Serialize(TKeyParams parameters)
|
||||
{
|
||||
var builder = new StringBuilder().AppendFormat("<{0}>", _keyValueTag);
|
||||
|
||||
if ((parameters.DigestParamSet != null) || (parameters.EncryptionParamSet != null) || (parameters.PublicKeyParamSet != null))
|
||||
{
|
||||
builder.AppendFormat("<{0}>", PublicKeyParametersTag);
|
||||
builder.AppendFormat("<{0}>{1}{2}</{0}>", PublicKeyParamSetTag, OidPrefix, parameters.PublicKeyParamSet);
|
||||
builder.AppendFormat("<{0}>{1}{2}</{0}>", DigestParamSetTag, OidPrefix, parameters.DigestParamSet);
|
||||
|
||||
if (parameters.EncryptionParamSet != null)
|
||||
{
|
||||
builder.AppendFormat("<{0}>{1}{2}</{0}>", EncryptionParamSetTag, OidPrefix, parameters.EncryptionParamSet);
|
||||
}
|
||||
|
||||
builder.AppendFormat("</{0}>", PublicKeyParametersTag);
|
||||
}
|
||||
|
||||
builder.AppendFormat("<{0}>{1}</{0}>", PublicKeyTag, Convert.ToBase64String(parameters.PublicKey));
|
||||
|
||||
if (parameters.PrivateKey != null)
|
||||
{
|
||||
builder.AppendFormat("<{0}>{1}</{0}>", PrivateKeyTag, Convert.ToBase64String(parameters.PublicKey));
|
||||
}
|
||||
|
||||
builder.AppendFormat("</{0}>", _keyValueTag);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает параметры ключа на основе XML
|
||||
/// </summary>
|
||||
public TKeyParams Deserialize(string keyParametersXml, TKeyParams parameters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(keyParametersXml))
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyParametersXml));
|
||||
}
|
||||
|
||||
var keyValue = SecurityElement.FromString(keyParametersXml);
|
||||
|
||||
if (keyValue == null)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.InvalidFromXmlString, _keyValueTag);
|
||||
}
|
||||
|
||||
keyValue = SelectChildElement(keyValue, _keyValueTag) ?? keyValue;
|
||||
|
||||
var publicKeyParameters = SelectChildElement(keyValue, PublicKeyParametersTag);
|
||||
|
||||
if (publicKeyParameters != null)
|
||||
{
|
||||
var publicKeyParamSet = RemoveWhiteSpaces(SelectChildElementText(publicKeyParameters, PublicKeyParamSetTag, false));
|
||||
|
||||
if (!publicKeyParamSet.StartsWith(OidPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.InvalidFromXmlString, PublicKeyParamSetTag);
|
||||
}
|
||||
|
||||
parameters.PublicKeyParamSet = publicKeyParamSet.Substring(OidPrefix.Length);
|
||||
|
||||
var digestParamSet = RemoveWhiteSpaces(SelectChildElementText(publicKeyParameters, DigestParamSetTag, false));
|
||||
|
||||
if (!digestParamSet.StartsWith(OidPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.InvalidFromXmlString, DigestParamSetTag);
|
||||
}
|
||||
|
||||
parameters.DigestParamSet = digestParamSet.Substring(OidPrefix.Length);
|
||||
|
||||
var encryptionParamSet = SelectChildElementText(publicKeyParameters, EncryptionParamSetTag, true);
|
||||
|
||||
if (!string.IsNullOrEmpty(encryptionParamSet))
|
||||
{
|
||||
encryptionParamSet = RemoveWhiteSpaces(encryptionParamSet);
|
||||
|
||||
if (!encryptionParamSet.StartsWith(OidPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.InvalidFromXmlString, EncryptionParamSetTag);
|
||||
}
|
||||
|
||||
parameters.EncryptionParamSet = encryptionParamSet.Substring(OidPrefix.Length);
|
||||
}
|
||||
}
|
||||
|
||||
var publicKey = SelectChildElementText(keyValue, PublicKeyTag, false);
|
||||
parameters.PublicKey = Convert.FromBase64String(RemoveWhiteSpaces(publicKey));
|
||||
|
||||
var privateKey = SelectChildElementText(keyValue, PrivateKeyTag, true);
|
||||
|
||||
if (privateKey != null)
|
||||
{
|
||||
parameters.PrivateKey = Convert.FromBase64String(RemoveWhiteSpaces(privateKey));
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static string SelectChildElementText(SecurityElement element, string childName, bool canNull)
|
||||
{
|
||||
string text = null;
|
||||
|
||||
var child = SelectChildElement(element, childName);
|
||||
|
||||
if (child != null && (child.Children == null || child.Children.Count == 0))
|
||||
{
|
||||
text = child.Text;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(text) && !canNull)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.InvalidFromXmlString, childName);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private static SecurityElement SelectChildElement(SecurityElement element, string childName)
|
||||
{
|
||||
var children = element.Children;
|
||||
|
||||
if (children != null)
|
||||
{
|
||||
foreach (SecurityElement child in children)
|
||||
{
|
||||
if (string.Equals(child.Tag, childName, StringComparison.OrdinalIgnoreCase)
|
||||
|| child.Tag.EndsWith(":" + childName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string RemoveWhiteSpaces(string value)
|
||||
{
|
||||
var length = value.Length;
|
||||
|
||||
var countWhiteSpace = 0;
|
||||
|
||||
for (var i = 0; i < length; ++i)
|
||||
{
|
||||
if (char.IsWhiteSpace(value[i]))
|
||||
{
|
||||
++countWhiteSpace;
|
||||
}
|
||||
}
|
||||
|
||||
var valueWithoutWhiteSpace = new char[length - countWhiteSpace];
|
||||
|
||||
for (int i = 0, j = 0; i < length; ++i)
|
||||
{
|
||||
if (!char.IsWhiteSpace(value[i]))
|
||||
{
|
||||
valueWithoutWhiteSpace[j++] = value[i];
|
||||
}
|
||||
}
|
||||
|
||||
return new string(valueWithoutWhiteSpace);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user