Add project
Basic formatting applied. Unnecessary comments have been removed. Suspicious code is covered by TODO.
This commit is contained in:
11
Hcs.Client/GostCryptography/Xml/GetIdElementDelegate.cs
Normal file
11
Hcs.Client/GostCryptography/Xml/GetIdElementDelegate.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Xml;
|
||||
|
||||
namespace GostCryptography.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Возвращает XML-элемент с указанным идентификатором
|
||||
/// </summary>
|
||||
/// <param name="document">Документ для поиска идентификатора элемента</param>
|
||||
/// <param name="idValue">Значение идентификатора элемента</param>
|
||||
public delegate XmlElement GetIdElementDelegate(XmlDocument document, string idValue);
|
||||
}
|
||||
349
Hcs.Client/GostCryptography/Xml/GostEncryptedXml.cs
Normal file
349
Hcs.Client/GostCryptography/Xml/GostEncryptedXml.cs
Normal file
@ -0,0 +1,349 @@
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Config;
|
||||
using GostCryptography.Gost_28147_89;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Cryptography.Xml;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace GostCryptography.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Объект для шифрации и дешифрации XML по ГОСТ 34.10
|
||||
/// </summary>
|
||||
public sealed class GostEncryptedXml
|
||||
{
|
||||
/// <summary>
|
||||
/// URI пространства имен для синтаксиса и правил обработки при шифровании XML по ГОСТ
|
||||
/// </summary>
|
||||
public const string XmlEncGostNamespaceUrl = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:";
|
||||
|
||||
/// <summary>
|
||||
/// URI алгоритма экспорта ключа по ГОСТ 28147-89
|
||||
/// </summary>
|
||||
public const string XmlEncGostKeyExportUrl = XmlEncGostNamespaceUrl + "kw-gost";
|
||||
|
||||
/// <summary>
|
||||
/// URI алгоритма экспорта ключа КриптоПро
|
||||
/// </summary>
|
||||
public const string XmlEncGostCryptoProKeyExportUrl = XmlEncGostNamespaceUrl + "kw-cp";
|
||||
|
||||
static GostEncryptedXml()
|
||||
{
|
||||
GostCryptoConfig.Initialize();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml()"/>
|
||||
public GostEncryptedXml() : this(GostCryptoConfig.ProviderType)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml()"/>
|
||||
public GostEncryptedXml(ProviderType providerType)
|
||||
{
|
||||
_encryptedXml = new GostEncryptedXmlImpl(providerType);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml(XmlDocument)"/>
|
||||
public GostEncryptedXml(XmlDocument document) : this(GostCryptoConfig.ProviderType, document)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml(XmlDocument)"/>
|
||||
public GostEncryptedXml(ProviderType providerType, XmlDocument document)
|
||||
{
|
||||
_encryptedXml = new GostEncryptedXmlImpl(providerType, document);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml(XmlDocument,Evidence)"/>
|
||||
public GostEncryptedXml(XmlDocument document, Evidence evidence) : this(GostCryptoConfig.ProviderType, document, evidence)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml(XmlDocument,Evidence)"/>
|
||||
public GostEncryptedXml(ProviderType providerType, XmlDocument document, Evidence evidence)
|
||||
{
|
||||
_encryptedXml = new GostEncryptedXmlImpl(providerType, document, evidence);
|
||||
}
|
||||
|
||||
private readonly GostEncryptedXmlImpl _encryptedXml;
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml.DocumentEvidence"/>
|
||||
public Evidence DocumentEvidence
|
||||
{
|
||||
get => _encryptedXml.DocumentEvidence;
|
||||
set => _encryptedXml.DocumentEvidence = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml.Resolver"/>
|
||||
public XmlResolver Resolver
|
||||
{
|
||||
get => _encryptedXml.Resolver;
|
||||
set => _encryptedXml.Resolver = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml.Padding"/>
|
||||
public PaddingMode Padding
|
||||
{
|
||||
get => _encryptedXml.Padding;
|
||||
set => _encryptedXml.Padding = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml.Mode"/>
|
||||
public CipherMode Mode
|
||||
{
|
||||
get => _encryptedXml.Mode;
|
||||
set => _encryptedXml.Mode = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml.Encoding"/>
|
||||
public Encoding Encoding
|
||||
{
|
||||
get => _encryptedXml.Encoding;
|
||||
set => _encryptedXml.Encoding = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EncryptedXml.Recipient"/>
|
||||
public string Recipient
|
||||
{
|
||||
get => _encryptedXml.Recipient;
|
||||
set => _encryptedXml.Recipient = value;
|
||||
}
|
||||
|
||||
// Encryption
|
||||
|
||||
/// <summary>
|
||||
/// Шифрует XML-элемент с помощью ключа с указанным именем
|
||||
/// </summary>
|
||||
/// <param name="element">Шифруемый XML-элемент</param>
|
||||
/// <param name="keyName">Имя ключа для шифрования XML-элемента</param>
|
||||
/// <returns>Зашифрованное представление XML-элемента</returns>
|
||||
public EncryptedData Encrypt(XmlElement element, string keyName)
|
||||
{
|
||||
return _encryptedXml.Encrypt(element, keyName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шифрует XML-элемент с помощью сертификата
|
||||
/// </summary>
|
||||
/// <param name="element">Шифруемый XML-элемент</param>
|
||||
/// <param name="certificate">Сертификат X.509 для шифрования XML-элемента</param>
|
||||
/// <returns>Зашифрованное представление XML-элемента</returns>
|
||||
public EncryptedData Encrypt(XmlElement element, X509Certificate2 certificate)
|
||||
{
|
||||
return _encryptedXml.Encrypt(element, certificate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шифрует данные с помощью указанного симметричного ключа
|
||||
/// </summary>
|
||||
/// <param name="data">Шифруемые данные</param>
|
||||
/// <param name="symmetricKey">Симметричный ключ для шифрования данных</param>
|
||||
/// <returns>Массив байт, содержащий зашифрованные данные</returns>
|
||||
public byte[] EncryptData(byte[] data, SymmetricAlgorithm symmetricKey)
|
||||
{
|
||||
return _encryptedXml.EncryptData(data, symmetricKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шифрует XML-элемент с помощью указанного симметричного ключа
|
||||
/// </summary>
|
||||
/// <param name="element">Шифруемый XML-элемент</param>
|
||||
/// <param name="symmetricKey">Симметричный ключ для шифрования XML-элемента</param>
|
||||
/// <param name="content">Значение true для шифрования только содержимого элемента; значение false для шифрования всего элемента</param>
|
||||
/// <returns>Массив байт, содержащий зашифрованные данные</returns>
|
||||
public byte[] EncryptData(XmlElement element, SymmetricAlgorithm symmetricKey, bool content)
|
||||
{
|
||||
return _encryptedXml.EncryptData(element, symmetricKey, content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шифрует сессионный ключ с помощью указанного общего симметричного ключа
|
||||
/// </summary>
|
||||
/// <param name="keyData">Шифруемый сессионный ключ</param>
|
||||
/// <param name="sharedKey">Общий симметричный ключ для шифрования сессионного ключа</param>
|
||||
/// <returns>Массив байт, содержащий зашифрованный сессионный ключ</returns>
|
||||
/// <remarks>Как правило сессионный ключ используется для шифрования данных и в свою очередь так же шифруется</remarks>
|
||||
public static byte[] EncryptKey(byte[] keyData, SymmetricAlgorithm sharedKey)
|
||||
{
|
||||
return EncryptedXml.EncryptKey(keyData, sharedKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шифрует сессионный ключ с помощью указанного асимметричного ключа RSA
|
||||
/// </summary>
|
||||
/// <param name="keyData">Шифруемый сессионный ключ</param>
|
||||
/// <param name="publicKey">Открытый ключ RSA для шифрования сессионного ключа</param>
|
||||
/// <param name="useOaep">Значение, указывающее, следует ли использовать заполнение OAEP (Optimal Asymmetric Encryption Padding)</param>
|
||||
/// <returns>Массив байт, содержащий зашифрованный сессионный ключ</returns>
|
||||
/// <remarks>Как правило сессионный ключ используется для шифрования данных и в свою очередь так же шифруется</remarks>
|
||||
public static byte[] EncryptKey(byte[] keyData, RSA publicKey, bool useOaep)
|
||||
{
|
||||
return EncryptedXml.EncryptKey(keyData, publicKey, useOaep);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шифрует сессионный ключ с помощью указанного асимметричного ключа ГОСТ Р 34.10
|
||||
/// </summary>
|
||||
/// <param name="sessionKey">Шифруемый сессионный ключ</param>
|
||||
/// <param name="publicKey">Открытый ключ ГОСТ Р 34.10 для шифрования сессионного ключа</param>
|
||||
/// <returns>Массив байт, содержащий зашифрованный сессионный ключ</returns>
|
||||
/// <remarks>Как правило сессионный ключ используется для шифрования данных и в свою очередь так же шифруется</remarks>
|
||||
public static byte[] EncryptKey(Gost_28147_89_SymmetricAlgorithmBase sessionKey, GostAsymmetricAlgorithm publicKey)
|
||||
{
|
||||
return GostEncryptedXmlImpl.EncryptKey(sessionKey, publicKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Шифрует сессионный ключ с помощью указанного симметричного ключа ГОСТ 28147
|
||||
/// </summary>
|
||||
/// <param name="sessionKey">Шифруемый сессионный ключ</param>
|
||||
/// <param name="sharedKey">Общий симметричный ключ ГОСТ 28147 для шифрования сессионного ключа</param>
|
||||
/// <param name="exportMethod">Алгоритм экспорта сессионного ключа</param>
|
||||
/// <returns>Массив байт, содержащий зашифрованный сессионный ключ</returns>
|
||||
/// <remarks>Как правило сессионный ключ используется для шифрования данных и в свою очередь так же шифруется</remarks>
|
||||
public static byte[] EncryptKey(Gost_28147_89_SymmetricAlgorithmBase sessionKey, Gost_28147_89_SymmetricAlgorithmBase sharedKey, GostKeyExchangeExportMethod exportMethod = GostKeyExchangeExportMethod.GostKeyExport)
|
||||
{
|
||||
return GostEncryptedXmlImpl.EncryptKey(sessionKey, sharedKey, exportMethod);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Расшифровывает зашифрованный XML-элемент с помощью указанного симметричного ключа
|
||||
/// </summary>
|
||||
/// <param name="encryptedData">Зашифрованное представление XML-элемента</param>
|
||||
/// <param name="symmetricKey">Симметричный ключ для расшифровки данных</param>
|
||||
/// <returns>Массив байт, содержащий расшифрованный XML-элемент</returns>
|
||||
public byte[] DecryptData(EncryptedData encryptedData, SymmetricAlgorithm symmetricKey)
|
||||
{
|
||||
return _encryptedXml.DecryptData(encryptedData, symmetricKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Расшифровывает все зашифрованные XML-элементы документа
|
||||
/// </summary>
|
||||
public void DecryptDocument()
|
||||
{
|
||||
_encryptedXml.DecryptDocument();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает вектор инициализации для расшифровки XML-элемента
|
||||
/// </summary>
|
||||
/// <param name="encryptedData">Зашифрованное представление XML-элемента</param>
|
||||
/// <param name="symmetricAlgorithmUri">URI алгоритма шифрования</param>
|
||||
/// <returns>Массив байт, содержащий вектор инициализации для расшифровки XML-элемента</returns>
|
||||
public byte[] GetDecryptionIV(EncryptedData encryptedData, string symmetricAlgorithmUri)
|
||||
{
|
||||
return _encryptedXml.GetDecryptionIV(encryptedData, symmetricAlgorithmUri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает симметричный ключ для расшифровки XML-элемента
|
||||
/// </summary>
|
||||
/// <param name="encryptedData">Зашифрованное представление XML-элемента</param>
|
||||
/// <param name="symmetricAlgorithmUri">URI алгоритма шифрования</param>
|
||||
/// <returns>Симметричный ключ для расшифровки XML-элемента</returns>
|
||||
public SymmetricAlgorithm GetDecryptionKey(EncryptedData encryptedData, string symmetricAlgorithmUri)
|
||||
{
|
||||
return _encryptedXml.GetDecryptionKey(encryptedData, symmetricAlgorithmUri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Извлекает ключ из элемента <EncryptedKey>
|
||||
/// </summary>
|
||||
/// <param name="encryptedKey">Элемент <EncryptedKey> с информацией о ключе шифрования</param>
|
||||
/// <returns>Массив байт, содержащий ключ для расшифровки</returns>
|
||||
public byte[] DecryptEncryptedKey(EncryptedKey encryptedKey)
|
||||
{
|
||||
return _encryptedXml.DecryptEncryptedKey(encryptedKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Расшифровывает сессионный ключ с помощью указанного общего симметричного ключа
|
||||
/// </summary>
|
||||
/// <param name="keyData">Массив байт, содержащий зашифрованный сессионный ключ</param>
|
||||
/// <param name="sharedKey">Общий симметричный ключ для расшифровки сессионного ключа</param>
|
||||
/// <returns>Массив байт, который содержит сессионный ключ</returns>
|
||||
/// <remarks>Как правило сессионный ключ используется для шифрования данных и в свою очередь так же шифруется</remarks>
|
||||
public static byte[] DecryptKey(byte[] keyData, SymmetricAlgorithm sharedKey)
|
||||
{
|
||||
return EncryptedXml.EncryptKey(keyData, sharedKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Расшифровывает сессионный ключ с помощью указанного асимметричного ключа RSA
|
||||
/// </summary>
|
||||
/// <param name="keyData">Массив байт, содержащий зашифрованный сессионный ключ</param>
|
||||
/// <param name="privateKey">Закрытый ключ RSA для расшифровки сессионного ключа</param>
|
||||
/// <param name="useOaep">Значение, указывающее, следует ли использовать заполнение OAEP (Optimal Asymmetric Encryption Padding)</param>
|
||||
/// <returns>Массив байт, который содержит сессионный ключ</returns>
|
||||
/// <remarks>Как правило сессионный ключ используется для шифрования данных и в свою очередь так же шифруется</remarks>
|
||||
public static byte[] DecryptKey(byte[] keyData, RSA privateKey, bool useOaep)
|
||||
{
|
||||
return EncryptedXml.DecryptKey(keyData, privateKey, useOaep);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Расшифровывает сессионный ключ с помощью указанного асимметричного ключа ГОСТ Р 34.10
|
||||
/// </summary>
|
||||
/// <param name="keyData">Массив байт, содержащий зашифрованный сессионный ключ</param>
|
||||
/// <param name="privateKey">Закрытый ключ ГОСТ Р 34.10 для расшифровки сессионного ключа</param>
|
||||
/// <returns>Сессионный ключ</returns>
|
||||
/// <remarks>Как правило сессионный ключ используется для шифрования данных и в свою очередь так же шифруется</remarks>
|
||||
public static SymmetricAlgorithm DecryptKey(byte[] keyData, GostAsymmetricAlgorithm privateKey)
|
||||
{
|
||||
return GostEncryptedXmlImpl.DecryptKeyClass(keyData, privateKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Заменяет указанный зашифрованный XML-элемент его расшифрованным представлением
|
||||
/// </summary>
|
||||
/// <param name="element">Заменяемый зашифрованный XML-элемент</param>
|
||||
/// <param name="decryptedData">Расшифрованное представление XML-элемента</param>
|
||||
public void ReplaceData(XmlElement element, byte[] decryptedData)
|
||||
{
|
||||
_encryptedXml.ReplaceData(element, decryptedData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Заменяет указанный XML-элемент его зашифрованным представлением
|
||||
/// </summary>
|
||||
/// <param name="element">Заменяемый XML-элемент</param>
|
||||
/// <param name="encryptedData">Зашифрованное представление XML-элемента</param>
|
||||
/// <param name="content">Значение true для замены только содержимого элемента; значение false для замены всего элемента</param>
|
||||
public static void ReplaceElement(XmlElement element, EncryptedData encryptedData, bool content)
|
||||
{
|
||||
EncryptedXml.ReplaceElement(element, encryptedData, content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает XML-элемент с указанным идентификатором
|
||||
/// </summary>
|
||||
/// <param name="document">Документ для поиска идентификатора XML-элемента</param>
|
||||
/// <param name="idValue">Значение идентификатора XML-элемента</param>
|
||||
public XmlElement GetIdElement(XmlDocument document, string idValue)
|
||||
{
|
||||
return _encryptedXml.GetIdElement(document, idValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сопоставляет имя ключа шифрования со значением
|
||||
/// </summary>
|
||||
/// <param name="keyName">Имя ключа шифрования</param>
|
||||
/// <param name="keyObject">Значение ключа шифрования</param>
|
||||
public void AddKeyNameMapping(string keyName, object keyObject)
|
||||
{
|
||||
_encryptedXml.AddKeyNameMapping(keyName, keyObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сбрасывает все сопоставления между именами и ключами шифрования
|
||||
/// </summary>
|
||||
public void ClearKeyNameMappings()
|
||||
{
|
||||
_encryptedXml.ClearKeyNameMappings();
|
||||
}
|
||||
}
|
||||
}
|
||||
429
Hcs.Client/GostCryptography/Xml/GostEncryptedXmlImpl.cs
Normal file
429
Hcs.Client/GostCryptography/Xml/GostEncryptedXmlImpl.cs
Normal file
@ -0,0 +1,429 @@
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Config;
|
||||
using GostCryptography.Gost_28147_89;
|
||||
using GostCryptography.Properties;
|
||||
using GostCryptography.Reflection;
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Cryptography.Xml;
|
||||
using System.Security.Policy;
|
||||
using System.Xml;
|
||||
|
||||
namespace GostCryptography.Xml
|
||||
{
|
||||
sealed class GostEncryptedXmlImpl : EncryptedXml
|
||||
{
|
||||
public GostEncryptedXmlImpl(ProviderType providerType)
|
||||
{
|
||||
ProviderType = providerType;
|
||||
}
|
||||
|
||||
public GostEncryptedXmlImpl(ProviderType providerType, XmlDocument document) : base(document)
|
||||
{
|
||||
ProviderType = providerType;
|
||||
}
|
||||
|
||||
public GostEncryptedXmlImpl(ProviderType providerType, XmlDocument document, Evidence evidence) : base(document, evidence)
|
||||
{
|
||||
ProviderType = providerType;
|
||||
}
|
||||
|
||||
public ProviderType ProviderType { get; }
|
||||
|
||||
public new void AddKeyNameMapping(string keyName, object keyObject)
|
||||
{
|
||||
if (string.IsNullOrEmpty(keyName))
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyName));
|
||||
}
|
||||
|
||||
if (keyObject == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyObject));
|
||||
}
|
||||
|
||||
if (keyObject is GostAsymmetricAlgorithm)
|
||||
{
|
||||
this.GetKeyNameMapping().Add(keyName, keyObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.AddKeyNameMapping(keyName, keyObject);
|
||||
}
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
public new EncryptedData Encrypt(XmlElement element, X509Certificate2 certificate)
|
||||
{
|
||||
if (element == null || certificate == null || !certificate.IsGost())
|
||||
{
|
||||
return base.Encrypt(element, certificate);
|
||||
}
|
||||
|
||||
var publicKey = (GostAsymmetricAlgorithm)certificate.GetPublicKeyAlgorithm();
|
||||
var encryptionKey = new Gost_28147_89_SymmetricAlgorithm(publicKey.ProviderType);
|
||||
|
||||
var encryptedKey = new EncryptedKey();
|
||||
encryptedKey.KeyInfo.AddClause(new KeyInfoX509Data(certificate));
|
||||
encryptedKey.EncryptionMethod = new EncryptionMethod(publicKey.KeyExchangeAlgorithm);
|
||||
encryptedKey.CipherData.CipherValue = EncryptKey(encryptionKey, publicKey);
|
||||
|
||||
var encryptedData = new EncryptedData
|
||||
{
|
||||
Type = XmlEncElementUrl,
|
||||
EncryptionMethod = new EncryptionMethod(encryptionKey.AlgorithmName)
|
||||
};
|
||||
|
||||
encryptedData.KeyInfo.AddClause(new KeyInfoEncryptedKey(encryptedKey));
|
||||
encryptedData.CipherData.CipherValue = EncryptData(element, encryptionKey, false);
|
||||
|
||||
return encryptedData;
|
||||
}
|
||||
|
||||
public static byte[] EncryptKey(Gost_28147_89_SymmetricAlgorithmBase sessionKey, GostAsymmetricAlgorithm publicKey)
|
||||
{
|
||||
if (sessionKey == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(sessionKey));
|
||||
}
|
||||
|
||||
if (publicKey == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(publicKey));
|
||||
}
|
||||
|
||||
var formatter = publicKey.CreateKeyExchangeFormatter();
|
||||
return formatter.CreateKeyExchangeData(sessionKey);
|
||||
}
|
||||
|
||||
public static byte[] EncryptKey(Gost_28147_89_SymmetricAlgorithmBase sessionKey, Gost_28147_89_SymmetricAlgorithmBase sharedKey, GostKeyExchangeExportMethod exportMethod)
|
||||
{
|
||||
if (sessionKey == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(sessionKey));
|
||||
}
|
||||
|
||||
if (sharedKey == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(sharedKey));
|
||||
}
|
||||
|
||||
return sharedKey.EncodePrivateKey(sessionKey, exportMethod);
|
||||
}
|
||||
|
||||
public override byte[] GetDecryptionIV(EncryptedData encryptedData, string symmetricAlgorithmUri)
|
||||
{
|
||||
if (encryptedData == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(encryptedData));
|
||||
}
|
||||
|
||||
if (symmetricAlgorithmUri == null)
|
||||
{
|
||||
if (encryptedData.EncryptionMethod == null)
|
||||
{
|
||||
return base.GetDecryptionIV(encryptedData, null);
|
||||
}
|
||||
|
||||
symmetricAlgorithmUri = encryptedData.EncryptionMethod.KeyAlgorithm;
|
||||
}
|
||||
|
||||
if (Gost_28147_89_SymmetricAlgorithm.AlgorithmNameValue.Equals(symmetricAlgorithmUri, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var iv = new byte[8];
|
||||
Buffer.BlockCopy(this.GetCipherValue(encryptedData.CipherData), 0, iv, 0, iv.Length);
|
||||
|
||||
return iv;
|
||||
}
|
||||
|
||||
return base.GetDecryptionIV(encryptedData, symmetricAlgorithmUri);
|
||||
}
|
||||
|
||||
public override SymmetricAlgorithm GetDecryptionKey(EncryptedData encryptedData, string symmetricAlgorithmUri)
|
||||
{
|
||||
if (encryptedData == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(encryptedData));
|
||||
}
|
||||
|
||||
SymmetricAlgorithm decryptionKey = null;
|
||||
|
||||
if (encryptedData.KeyInfo != null)
|
||||
{
|
||||
EncryptedKey encryptedKey = null;
|
||||
|
||||
foreach (var keyInfo in encryptedData.KeyInfo)
|
||||
{
|
||||
// Извлечение ключа по имени
|
||||
if (keyInfo is KeyInfoName)
|
||||
{
|
||||
var keyName = ((KeyInfoName)keyInfo).Value;
|
||||
var keyAlgorithm = this.GetKeyNameMapping()[keyName];
|
||||
|
||||
if (keyAlgorithm == null)
|
||||
{
|
||||
var nsManager = new XmlNamespaceManager(this.GetDocument().NameTable);
|
||||
nsManager.AddNamespace("enc", XmlEncNamespaceUrl);
|
||||
|
||||
var encryptedKeyNodes = this.GetDocument().SelectNodes("//enc:EncryptedKey", nsManager);
|
||||
|
||||
if (encryptedKeyNodes != null)
|
||||
{
|
||||
foreach (XmlElement encryptedKeyNode in encryptedKeyNodes)
|
||||
{
|
||||
var currentEncryptedKey = new EncryptedKey();
|
||||
currentEncryptedKey.LoadXml(encryptedKeyNode);
|
||||
|
||||
if ((currentEncryptedKey.CarriedKeyName == keyName) && (currentEncryptedKey.Recipient == Recipient))
|
||||
{
|
||||
encryptedKey = currentEncryptedKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decryptionKey = (SymmetricAlgorithm)keyAlgorithm;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Извлечение ключа по ссылке
|
||||
if (keyInfo is KeyInfoRetrievalMethod)
|
||||
{
|
||||
var idValue = CryptographyXmlUtils.ExtractIdFromLocalUri(((KeyInfoRetrievalMethod)keyInfo).Uri);
|
||||
var idElement = GetIdElement(this.GetDocument(), idValue);
|
||||
|
||||
if (idElement != null)
|
||||
{
|
||||
encryptedKey = new EncryptedKey();
|
||||
encryptedKey.LoadXml(idElement);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Ключ в готовом виде
|
||||
if (keyInfo is KeyInfoEncryptedKey)
|
||||
{
|
||||
encryptedKey = ((KeyInfoEncryptedKey)keyInfo).EncryptedKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (decryptionKey == null && encryptedKey != null)
|
||||
{
|
||||
if (symmetricAlgorithmUri == null)
|
||||
{
|
||||
if (encryptedData.EncryptionMethod == null)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.XmlMissingAlgorithm);
|
||||
}
|
||||
|
||||
symmetricAlgorithmUri = encryptedData.EncryptionMethod.KeyAlgorithm;
|
||||
}
|
||||
|
||||
decryptionKey = DecryptEncryptedKeyClass(encryptedKey, symmetricAlgorithmUri);
|
||||
}
|
||||
}
|
||||
|
||||
return decryptionKey;
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
private SymmetricAlgorithm DecryptEncryptedKeyClass(EncryptedKey encryptedKey, string symmetricAlgorithmUri)
|
||||
{
|
||||
if (encryptedKey == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(encryptedKey));
|
||||
}
|
||||
|
||||
SymmetricAlgorithm decryptionKey = null;
|
||||
|
||||
if (encryptedKey.KeyInfo != null)
|
||||
{
|
||||
foreach (var keyInfo in encryptedKey.KeyInfo)
|
||||
{
|
||||
// Извлечение ключа по имени
|
||||
if (keyInfo is KeyInfoName)
|
||||
{
|
||||
var keyName = ((KeyInfoName)keyInfo).Value;
|
||||
var keyAlgorithm = this.GetKeyNameMapping()[keyName];
|
||||
|
||||
if (keyAlgorithm != null)
|
||||
{
|
||||
if (keyAlgorithm is SymmetricAlgorithm)
|
||||
{
|
||||
decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (SymmetricAlgorithm)keyAlgorithm, symmetricAlgorithmUri, encryptedKey.EncryptionMethod.KeyAlgorithm);
|
||||
}
|
||||
else if (keyAlgorithm is RSA)
|
||||
{
|
||||
var useOaep = (encryptedKey.EncryptionMethod != null) && (encryptedKey.EncryptionMethod.KeyAlgorithm == XmlEncRSAOAEPUrl);
|
||||
decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (RSA)keyAlgorithm, useOaep, symmetricAlgorithmUri);
|
||||
}
|
||||
else if (keyAlgorithm is GostAsymmetricAlgorithm)
|
||||
{
|
||||
decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (GostAsymmetricAlgorithm)keyAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Извлечение ключа из сертификата
|
||||
if (keyInfo is KeyInfoX509Data)
|
||||
{
|
||||
var certificates = CryptographyXmlUtils.BuildBagOfCertsDecryption((KeyInfoX509Data)keyInfo);
|
||||
|
||||
foreach (var certificate in certificates)
|
||||
{
|
||||
var privateKey = certificate.GetPrivateKeyAlgorithm();
|
||||
|
||||
if (privateKey is RSA)
|
||||
{
|
||||
var useOaep = (encryptedKey.EncryptionMethod != null) && (encryptedKey.EncryptionMethod.KeyAlgorithm == XmlEncRSAOAEPUrl);
|
||||
decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (RSA)privateKey, useOaep, symmetricAlgorithmUri);
|
||||
}
|
||||
else if (privateKey is GostAsymmetricAlgorithm)
|
||||
{
|
||||
decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (GostAsymmetricAlgorithm)privateKey);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Извлечение ключа по ссылке
|
||||
if (keyInfo is KeyInfoRetrievalMethod)
|
||||
{
|
||||
var idValue = CryptographyXmlUtils.ExtractIdFromLocalUri(((KeyInfoRetrievalMethod)keyInfo).Uri);
|
||||
var idElement = GetIdElement(this.GetDocument(), idValue);
|
||||
|
||||
if (idElement != null)
|
||||
{
|
||||
var secondEncryptedKey = new EncryptedKey();
|
||||
secondEncryptedKey.LoadXml(idElement);
|
||||
|
||||
decryptionKey = DecryptEncryptedKeyClass(secondEncryptedKey, symmetricAlgorithmUri);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Ключ в готовом виде
|
||||
if (keyInfo is KeyInfoEncryptedKey)
|
||||
{
|
||||
var secondEncryptedKey = ((KeyInfoEncryptedKey)keyInfo).EncryptedKey;
|
||||
var symmetricAlgorithm = DecryptEncryptedKeyClass(secondEncryptedKey, symmetricAlgorithmUri);
|
||||
|
||||
if (symmetricAlgorithm != null)
|
||||
{
|
||||
decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, symmetricAlgorithm, symmetricAlgorithmUri, encryptedKey.EncryptionMethod.KeyAlgorithm);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decryptionKey;
|
||||
}
|
||||
|
||||
private static SymmetricAlgorithm DecryptKeyClass(byte[] keyData, SymmetricAlgorithm algorithm, string symmetricAlgorithmUri, string encryptionKeyAlgorithm)
|
||||
{
|
||||
if (keyData == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyData));
|
||||
}
|
||||
|
||||
if (algorithm == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(algorithm));
|
||||
}
|
||||
|
||||
SymmetricAlgorithm decryptionKey = null;
|
||||
|
||||
if (algorithm is Gost_28147_89_SymmetricAlgorithmBase gost28147)
|
||||
{
|
||||
if (string.Equals(encryptionKeyAlgorithm, GostEncryptedXml.XmlEncGostKeyExportUrl, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
decryptionKey = gost28147.DecodePrivateKey(keyData, GostKeyExchangeExportMethod.GostKeyExport);
|
||||
}
|
||||
|
||||
if (string.Equals(encryptionKeyAlgorithm, GostEncryptedXml.XmlEncGostCryptoProKeyExportUrl, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
decryptionKey = gost28147.DecodePrivateKey(keyData, GostKeyExchangeExportMethod.CryptoProKeyExport);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var decryptionKeyBytes = DecryptKey(keyData, algorithm);
|
||||
|
||||
if (decryptionKeyBytes != null)
|
||||
{
|
||||
decryptionKey = (SymmetricAlgorithm)GostCryptoConfig.CreateFromName(symmetricAlgorithmUri);
|
||||
decryptionKey.Key = decryptionKeyBytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (decryptionKey == null)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.XmlMissingAlgorithm);
|
||||
}
|
||||
|
||||
return decryptionKey;
|
||||
}
|
||||
|
||||
private static SymmetricAlgorithm DecryptKeyClass(byte[] keyData, RSA algorithm, bool useOaep, string symmetricAlgorithmUri)
|
||||
{
|
||||
if (keyData == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyData));
|
||||
}
|
||||
|
||||
if (algorithm == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(algorithm));
|
||||
}
|
||||
|
||||
SymmetricAlgorithm decryptionKey = null;
|
||||
|
||||
var decryptionKeyBytes = DecryptKey(keyData, algorithm, useOaep);
|
||||
|
||||
if (decryptionKeyBytes != null)
|
||||
{
|
||||
decryptionKey = (SymmetricAlgorithm)GostCryptoConfig.CreateFromName(symmetricAlgorithmUri);
|
||||
decryptionKey.Key = decryptionKeyBytes;
|
||||
}
|
||||
|
||||
if (decryptionKey == null)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.XmlMissingAlgorithm);
|
||||
}
|
||||
|
||||
return decryptionKey;
|
||||
}
|
||||
|
||||
public static SymmetricAlgorithm DecryptKeyClass(byte[] keyData, GostAsymmetricAlgorithm privateKey)
|
||||
{
|
||||
if (keyData == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(keyData));
|
||||
}
|
||||
|
||||
if (privateKey == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(privateKey));
|
||||
}
|
||||
|
||||
var deformatter = privateKey.CreateKeyExchangeDeformatter();
|
||||
var decryptionKey = deformatter.DecryptKeyExchangeAlgorithm(keyData);
|
||||
|
||||
return decryptionKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
Hcs.Client/GostCryptography/Xml/GostKeyValue.cs
Normal file
50
Hcs.Client/GostCryptography/Xml/GostKeyValue.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using GostCryptography.Base;
|
||||
using System.Security.Cryptography.Xml;
|
||||
using System.Xml;
|
||||
|
||||
namespace GostCryptography.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Параметры открытого ключа цифровой подписи ГОСТ Р 34.10 элемента <see cref="KeyInfo"/>
|
||||
/// </summary>
|
||||
public abstract class GostKeyValue : KeyInfoClause
|
||||
{
|
||||
/// <summary>
|
||||
/// URI пространства имен для XML-подписи ГОСТ Р 34.10
|
||||
/// </summary>
|
||||
public const string XmlDsigNamespaceUrl = "urn:ietf:params:xml:ns:cpxmlsec";
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр класса с заданным публичным ключом
|
||||
/// </summary>
|
||||
protected GostKeyValue(GostAsymmetricAlgorithm publicKey)
|
||||
{
|
||||
PublicKey = publicKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Открытый ключ
|
||||
/// </summary>
|
||||
public GostAsymmetricAlgorithm PublicKey { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void LoadXml(XmlElement element)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(element));
|
||||
}
|
||||
|
||||
PublicKey.FromXmlString(element.OuterXml);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override XmlElement GetXml()
|
||||
{
|
||||
var document = new XmlDocument { PreserveWhitespace = true };
|
||||
var element = document.CreateElement("KeyValue", SignedXml.XmlDsigNamespaceUrl);
|
||||
element.InnerXml = PublicKey.ToXmlString(false);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
143
Hcs.Client/GostCryptography/Xml/GostSignedXml.cs
Normal file
143
Hcs.Client/GostCryptography/Xml/GostSignedXml.cs
Normal file
@ -0,0 +1,143 @@
|
||||
using GostCryptography.Config;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Cryptography.Xml;
|
||||
using System.Xml;
|
||||
|
||||
namespace GostCryptography.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Объект для работы с подписями XML по ГОСТ 34.10
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Данный класс реализует стандарт XML-DSig с использованием ГОСТ 34.10. Стандарт XML-DSig разработан консорциумом W3C
|
||||
/// и определяет рекомендации по формированию подписанных сообщений в формате XML. Фактически XML-DSig решает те же вопросы,
|
||||
/// что и CMS/PKCS#7. Основное отличие в том, что в CMS/PKCS#7 данные хранятся в структурах, сформированных в соответствии
|
||||
/// с разметкой ANS.1 (фактически, бинарные данные), а в XML-DSig данные хранятся в текстовом формате в соответствии с правилами
|
||||
/// документа "XML Signature Syntax and Processing". Основное применение XML-DSig - это XML-ориентированные протоколы, например,
|
||||
/// Web- и SOAP-сервисы.
|
||||
/// </remarks>
|
||||
public sealed class GostSignedXml
|
||||
{
|
||||
static GostSignedXml()
|
||||
{
|
||||
GostCryptoConfig.Initialize();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml()"/>
|
||||
public GostSignedXml()
|
||||
{
|
||||
_signedXml = new GostSignedXmlImpl();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml(XmlElement)"/>
|
||||
public GostSignedXml(XmlElement element)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(element));
|
||||
}
|
||||
|
||||
_signedXml = new GostSignedXmlImpl(element);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml(XmlDocument)"/>
|
||||
public GostSignedXml(XmlDocument document)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw ExceptionUtility.ArgumentNull(nameof(document));
|
||||
}
|
||||
|
||||
_signedXml = new GostSignedXmlImpl(document);
|
||||
}
|
||||
|
||||
private readonly GostSignedXmlImpl _signedXml;
|
||||
|
||||
/// <inheritdoc cref="SignedXml.SignedInfo"/>
|
||||
public SignedInfo SignedInfo => _signedXml.SignedInfo;
|
||||
|
||||
/// <inheritdoc cref="SignedXml.KeyInfo"/>
|
||||
public KeyInfo KeyInfo
|
||||
{
|
||||
get => _signedXml.KeyInfo;
|
||||
set => _signedXml.KeyInfo = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml.SigningKey"/>
|
||||
public AsymmetricAlgorithm SigningKey
|
||||
{
|
||||
get => _signedXml.SigningKey;
|
||||
set => _signedXml.SigningKey = value;
|
||||
}
|
||||
|
||||
#if !NET40
|
||||
/// <inheritdoc cref="SignedXml.SafeCanonicalizationMethods"/>
|
||||
public System.Collections.ObjectModel.Collection<string> SafeCanonicalizationMethods
|
||||
{
|
||||
get => _signedXml.SafeCanonicalizationMethods;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Обработчик для перекрытия метода <see cref="GetIdElement"/>
|
||||
/// </summary>
|
||||
public GetIdElementDelegate GetIdElementHandler
|
||||
{
|
||||
get => _signedXml.GetIdElementHandler;
|
||||
set => _signedXml.GetIdElementHandler = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Устанавливает сертификат для вычисления цифровой подписи
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
public void SetSigningCertificate(X509Certificate2 certificate)
|
||||
{
|
||||
SigningKey = certificate.GetPrivateKeyAlgorithm();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml.AddReference"/>
|
||||
public void AddReference(Reference reference)
|
||||
{
|
||||
_signedXml.AddReference(reference);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml.ComputeSignature()"/>
|
||||
public void ComputeSignature()
|
||||
{
|
||||
_signedXml.ComputeSignatureGost();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml.CheckSignature()"/>
|
||||
public bool CheckSignature()
|
||||
{
|
||||
return _signedXml.CheckSignature();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml.CheckSignature(AsymmetricAlgorithm)"/>
|
||||
public bool CheckSignature(AsymmetricAlgorithm publicKey)
|
||||
{
|
||||
return _signedXml.CheckSignature(publicKey);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml.LoadXml(XmlElement)"/>
|
||||
public void LoadXml(XmlElement element)
|
||||
{
|
||||
_signedXml.LoadXml(element);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml.GetXml()"/>
|
||||
public XmlElement GetXml()
|
||||
{
|
||||
return _signedXml.GetXml();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignedXml.GetIdElement(XmlDocument,string)"/>
|
||||
public XmlElement GetIdElement(XmlDocument document, string idValue)
|
||||
{
|
||||
return _signedXml.GetIdElement(document, idValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
159
Hcs.Client/GostCryptography/Xml/GostSignedXmlImpl.cs
Normal file
159
Hcs.Client/GostCryptography/Xml/GostSignedXmlImpl.cs
Normal file
@ -0,0 +1,159 @@
|
||||
using GostCryptography.Base;
|
||||
using GostCryptography.Properties;
|
||||
using GostCryptography.Reflection;
|
||||
using System.Collections;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Cryptography.Xml;
|
||||
using System.Xml;
|
||||
|
||||
namespace GostCryptography.Xml
|
||||
{
|
||||
sealed class GostSignedXmlImpl : SignedXml
|
||||
{
|
||||
public GostSignedXmlImpl()
|
||||
{
|
||||
}
|
||||
|
||||
public GostSignedXmlImpl(XmlElement element) : base(element)
|
||||
{
|
||||
}
|
||||
|
||||
public GostSignedXmlImpl(XmlDocument document) : base(document)
|
||||
{
|
||||
}
|
||||
|
||||
public GetIdElementDelegate GetIdElementHandler { get; set; }
|
||||
|
||||
private IEnumerator KeyInfoEnumerable
|
||||
{
|
||||
get => this.GetKeyInfoEnumerable();
|
||||
set => this.SetKeyInfoEnumerable(value);
|
||||
}
|
||||
|
||||
private IEnumerator X509Enumerable
|
||||
{
|
||||
get => this.GetX509Enumerable();
|
||||
set => this.SetX509Enumerable(value);
|
||||
}
|
||||
|
||||
private X509Certificate2Collection X509Collection
|
||||
{
|
||||
get => this.GetX509Collection();
|
||||
set => this.SetX509Collection(value);
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
public void ComputeSignatureGost()
|
||||
{
|
||||
var signingKey = SigningKey;
|
||||
|
||||
if (signingKey == null)
|
||||
{
|
||||
ComputeSignatureBase();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((SignedInfo.SignatureMethod == null) && (signingKey is GostAsymmetricAlgorithm))
|
||||
{
|
||||
SignedInfo.SignatureMethod = signingKey.SignatureAlgorithm;
|
||||
}
|
||||
|
||||
ComputeSignatureBase();
|
||||
}
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
private void ComputeSignatureBase()
|
||||
{
|
||||
ComputeSignature();
|
||||
}
|
||||
|
||||
protected override AsymmetricAlgorithm GetPublicKey()
|
||||
{
|
||||
if (KeyInfo == null)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.XmlKeyInfoRequired);
|
||||
}
|
||||
|
||||
if (X509Enumerable != null)
|
||||
{
|
||||
var nextCertificatePublicKey = GetNextCertificatePublicKey();
|
||||
|
||||
if (nextCertificatePublicKey != null)
|
||||
{
|
||||
return nextCertificatePublicKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (KeyInfoEnumerable == null)
|
||||
{
|
||||
KeyInfoEnumerable = KeyInfo.GetEnumerator();
|
||||
}
|
||||
|
||||
var keyInfoEnum = KeyInfoEnumerable;
|
||||
|
||||
while (keyInfoEnum.MoveNext())
|
||||
{
|
||||
if (keyInfoEnum.Current is RSAKeyValue rsaKeyValue)
|
||||
{
|
||||
return rsaKeyValue.Key;
|
||||
}
|
||||
|
||||
if (keyInfoEnum.Current is DSAKeyValue dsaKeyValue)
|
||||
{
|
||||
return dsaKeyValue.Key;
|
||||
}
|
||||
|
||||
if (keyInfoEnum.Current is GostKeyValue gostKeyValue)
|
||||
{
|
||||
return gostKeyValue.PublicKey;
|
||||
}
|
||||
|
||||
if (keyInfoEnum.Current is KeyInfoX509Data keyInfoX509Data)
|
||||
{
|
||||
X509Collection = CryptographyXmlUtils.BuildBagOfCertsVerification(keyInfoX509Data);
|
||||
|
||||
if (X509Collection.Count > 0)
|
||||
{
|
||||
X509Enumerable = X509Collection.GetEnumerator();
|
||||
|
||||
var nextCertificatePublicKey = GetNextCertificatePublicKey();
|
||||
|
||||
if (nextCertificatePublicKey != null)
|
||||
{
|
||||
return nextCertificatePublicKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
private AsymmetricAlgorithm GetNextCertificatePublicKey()
|
||||
{
|
||||
while (X509Enumerable.MoveNext())
|
||||
{
|
||||
if (X509Enumerable.Current is X509Certificate2 certificate)
|
||||
{
|
||||
return certificate.GetPublicKeyAlgorithm();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override XmlElement GetIdElement(XmlDocument document, string idValue)
|
||||
{
|
||||
if (GetIdElementHandler != null)
|
||||
{
|
||||
return GetIdElementHandler(document, idValue);
|
||||
}
|
||||
|
||||
return base.GetIdElement(document, idValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Hcs.Client/GostCryptography/Xml/Gost_R3410_2001_KeyValue.cs
Normal file
36
Hcs.Client/GostCryptography/Xml/Gost_R3410_2001_KeyValue.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using GostCryptography.Gost_R3410;
|
||||
using System.Security.Cryptography.Xml;
|
||||
|
||||
namespace GostCryptography.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Параметры открытого ключа цифровой подписи ГОСТ Р 34.10-2001 элемента <see cref="KeyInfo"/>
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2001_KeyValue : GostKeyValue
|
||||
{
|
||||
/// <summary>
|
||||
/// URI параметров ключа ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public const string KeyValueUrl = SignedXml.XmlDsigNamespaceUrl + " KeyValue/" + Gost_R3410_2001_KeyExchangeXmlSerializer.KeyValueTag;
|
||||
|
||||
/// <summary>
|
||||
/// Известные URIs параметров ключа ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public static readonly string[] KnownValueUrls = { KeyValueUrl };
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр класса с новым ключом ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public Gost_R3410_2001_KeyValue() : base(new Gost_R3410_2001_AsymmetricAlgorithm())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр класса с заданным ключом ГОСТ Р 34.10-2001
|
||||
/// </summary>
|
||||
public Gost_R3410_2001_KeyValue(Gost_R3410_2001_AsymmetricAlgorithm publicKey) : base(publicKey)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
using GostCryptography.Gost_R3410;
|
||||
using System.Security.Cryptography.Xml;
|
||||
|
||||
namespace GostCryptography.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Параметры открытого ключа цифровой подписи ГОСТ Р 34.10-2012/256 элемента <see cref="KeyInfo"/>
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_256_KeyValue : GostKeyValue
|
||||
{
|
||||
/// <summary>
|
||||
/// URI параметров ключа ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public const string KeyValueUrl = SignedXml.XmlDsigNamespaceUrl + " KeyValue/" + Gost_R3410_2012_256_KeyExchangeXmlSerializer.KeyValueTag;
|
||||
|
||||
/// <summary>
|
||||
/// Известные URIs параметров ключа ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public static readonly string[] KnownValueUrls = { KeyValueUrl };
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр класса с новым ключом ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public Gost_R3410_2012_256_KeyValue() : base(new Gost_R3410_2012_256_AsymmetricAlgorithm())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр класса с заданным ключом ГОСТ Р 34.10-2012/256
|
||||
/// </summary>
|
||||
public Gost_R3410_2012_256_KeyValue(Gost_R3410_2012_256_AsymmetricAlgorithm publicKey) : base(publicKey)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
using GostCryptography.Gost_R3410;
|
||||
using System.Security.Cryptography.Xml;
|
||||
|
||||
namespace GostCryptography.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Параметры открытого ключа цифровой подписи ГОСТ Р 34.10-2012/512 элемента <see cref="KeyInfo"/>
|
||||
/// </summary>
|
||||
public sealed class Gost_R3410_2012_512_KeyValue : GostKeyValue
|
||||
{
|
||||
/// <summary>
|
||||
/// URI параметров ключа ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public const string KeyValueUrl = SignedXml.XmlDsigNamespaceUrl + " KeyValue/" + Gost_R3410_2012_512_KeyExchangeXmlSerializer.KeyValueTag;
|
||||
|
||||
/// <summary>
|
||||
/// Известные URIs параметров ключа ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public static readonly string[] KnownValueUrls = { KeyValueUrl };
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр класса с новым ключом ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public Gost_R3410_2012_512_KeyValue() : base(new Gost_R3410_2012_512_AsymmetricAlgorithm())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает экземпляр класса с заданным ключом ГОСТ Р 34.10-2012/512
|
||||
/// </summary>
|
||||
public Gost_R3410_2012_512_KeyValue(Gost_R3410_2012_512_AsymmetricAlgorithm publicKey) : base(publicKey)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user