Files
hcs/Hcs.Client/GostXades/GostCryptoProvider.cs

131 lines
4.9 KiB
C#

using GostCryptography.Config;
using GostCryptography.Gost_R3410;
using GostCryptography.Gost_R3411;
using GostXades.Abstractions;
using GostXades.Helpers;
using Microsoft.Xades;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
namespace GostXades
{
public class GostCryptoProvider : ICryptoProvider
{
public GostCryptoProvider(CryptoProviderTypeEnum cryptoProviderType)
{
GostCryptoConfig.ProviderType = (GostCryptography.Base.ProviderType)cryptoProviderType;
}
private Dictionary<string, string> HashAlgorithmMap { get; set; } = new Dictionary<string, string>
{
["http://www.w3.org/2001/04/xmldsig-more#gostr3411"] = "GOST3411"
};
public HashAlgorithm GetHashAlgorithm(string algorithm)
{
string algorithmName;
var algorithmUrl = algorithm;
if (!HashAlgorithmMap.TryGetValue(algorithmUrl, out algorithmName))
{
return null;
}
var pkHash = HashAlgorithm.Create(algorithmName);
return pkHash;
}
private int _referenceIndex;
public string SignatureMethod => Gost_R3410_2012_256_AsymmetricAlgorithm.SignatureAlgorithmValue;
public string DigestMethod => Gost_R3411_2012_256_HashAlgorithm.AlgorithmNameValue;
private HashAlgorithm GetHashAlgorithm() => new Gost_R3411_2012_256_HashAlgorithm();
public AsymmetricAlgorithm GetAsymmetricAlgorithm(X509Certificate2 certificate, string privateKeyPassword)
{
var provider = certificate.GetPrivateKeyAlgorithm();
if (!string.IsNullOrEmpty(privateKeyPassword))
{
var secureString = new SecureString();
foreach (var chr in privateKeyPassword)
secureString.AppendChar(chr);
if (provider is Gost_R3410_2012_256_AsymmetricAlgorithm alg1)
alg1.SetContainerPassword(secureString);
else if (provider is Gost_R3410_2012_512_AsymmetricAlgorithm alg2)
alg2.SetContainerPassword(secureString);
else throw new NotSupportedException(
$"Неизвестный тип алгоритма {provider.SignatureAlgorithm} для применения пароля");
}
return provider;
}
public Reference GetReference(string signedElementId, string signatureId)
{
var reference = new Reference
{
Uri = $"#{signedElementId}",
DigestMethod = DigestMethod,
Id = $"{signatureId}-ref{_referenceIndex}"
};
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
_referenceIndex++;
return reference;
}
public AsymmetricSignatureFormatter GetSignatureFormatter(X509Certificate2 certificate)
{
var alg = certificate.GetPrivateKeyAlgorithm();
var signatureDescription =
(SignatureDescription)CryptoConfig.CreateFromName(alg.SignatureAlgorithm);
return signatureDescription.CreateFormatter(alg);
}
public XadesObject GetXadesObject(XadesInfo xadesInfo, string signatureId)
{
var xadesObject = new XadesObject
{
QualifyingProperties = new QualifyingProperties
{
Target = $"#{signatureId}",
SignedProperties = new SignedProperties { Id = $"{signatureId}-signedprops" }
}
};
var hashAlgorithm = GetHashAlgorithm();
var hashValue = hashAlgorithm.ComputeHash(xadesInfo.RawCertData);
var x509CertificateParser = new X509CertificateParser();
var bouncyCert = x509CertificateParser.ReadCertificate(xadesInfo.RawCertData);
var cert = new Cert
{
IssuerSerial = new IssuerSerial
{
X509IssuerName = bouncyCert.IssuerDN.ToX509IssuerName(),
X509SerialNumber = bouncyCert.SerialNumber.ToString()
},
CertDigest =
{
DigestValue = hashValue,
DigestMethod = new DigestMethod { Algorithm = DigestMethod }
}
};
var signedSignatureProperties = xadesObject.QualifyingProperties.SignedProperties.SignedSignatureProperties;
signedSignatureProperties.SigningCertificate.CertCollection.Add(cert);
signedSignatureProperties.SigningTime = xadesInfo.SigningDateTimeUtc.ToDateTimeOffset(xadesInfo.TimeZoneOffsetMinutes);
return xadesObject;
}
}
}