Advertisement
PavelDevelop

Untitled

May 6th, 2016
309
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.96 KB | None | 0 0
  1. public static class GisSignatureHelper
  2.     {
  3.         public const bool PreserveWhitespace = true;
  4.  
  5.         public static string GetSignedRequestXades(string request, string thumbprint, string privateKeyPassword)
  6.         {
  7.             var originalDoc = new XmlDocument { PreserveWhitespace = PreserveWhitespace };
  8.             originalDoc.LoadXml(request);
  9.  
  10.             var cert = GetCertificateByThumbprint(thumbprint);
  11.  
  12.             var signatureid = $"xmldsig-{Guid.NewGuid().ToString().ToLower()}";
  13.             var signedXml = GetXadesSignedXml(cert, originalDoc, signatureid, privateKeyPassword);
  14.  
  15.             var keyInfo = GetKeyInfo(Convert.ToBase64String(cert.GetRawCertData()));
  16.             signedXml.KeyInfo = keyInfo;
  17.  
  18.             var xadesInfo = GetXadesInfo(cert);
  19.  
  20.             var xadesObject = GetXadesObject(xadesInfo, signatureid);
  21.             signedXml.AddXadesObject(xadesObject);
  22.  
  23.             signedXml.ComputeSignature();
  24.  
  25.             InjectSignatureToOriginalDoc(signedXml, originalDoc);
  26.  
  27.             return originalDoc.OuterXml;
  28.         }
  29.  
  30.         public static XadesInfo GetXadesInfo(X509Certificate2 certificate)
  31.         {
  32.             var xadesInfo = new XadesInfo
  33.             {
  34.                 RawPK = Convert.ToBase64String(certificate.GetRawCertData()),
  35.                 SigningDateTimeUTC = DateTime.UtcNow
  36.             };
  37.             var delta = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now);
  38.             xadesInfo.TimeZoneOffsetMinutes = Convert.ToInt32(delta.TotalMinutes);
  39.             return xadesInfo;
  40.         }
  41.  
  42.         public static void InjectSignatureToOriginalDoc(XadesSignedXml signedXml, XmlDocument originalDoc)
  43.         {
  44.             var xmlSig = signedXml.GetXml();
  45.             var signedDataContainer = signedXml.GetIdElement(originalDoc, "signed-data-container");
  46.             signedDataContainer.InsertBefore(originalDoc.ImportNode(xmlSig, true), signedDataContainer.FirstChild);
  47.         }
  48.  
  49.         public static XadesObject GetXadesObject(XadesInfo xadesInfo, string signatureid)
  50.         {
  51.             var xadesObject = new XadesObject
  52.             {
  53.                 QualifyingProperties =
  54.                 {
  55.                     Target = $"#{signatureid}",
  56.                     SignedProperties = {Id = $"{signatureid}-signedprops"}
  57.                 }
  58.             };
  59.             var signedSignatureProperties = xadesObject.QualifyingProperties.SignedProperties.SignedSignatureProperties;
  60.  
  61.             var x509CertificateParser = new X509CertificateParser();
  62.             var bouncyCert = x509CertificateParser.ReadCertificate(Convert.FromBase64String(xadesInfo.RawPK));
  63.  
  64.             var cert = new Cert
  65.             {
  66.                 IssuerSerial =
  67.                 {
  68.                     X509IssuerName = GetOidRepresentation(bouncyCert.IssuerDN.ToString()),
  69.                     X509SerialNumber = bouncyCert.SerialNumber.ToString()
  70.                 }
  71.             };
  72.  
  73.             cert.CertDigest.DigestMethod.Algorithm = CPSignedXml.XmlDsigGost3411UrlObsolete;
  74.  
  75.             var rawCertData = Convert.FromBase64String(xadesInfo.RawPK);
  76.             var pkHash = HashAlgorithm.Create("GOST3411");
  77.             var hashValue = pkHash.ComputeHash(rawCertData);
  78.             cert.CertDigest.DigestValue = hashValue;
  79.  
  80.             signedSignatureProperties.SigningCertificate.CertCollection.Add(cert);
  81.  
  82.             signedSignatureProperties.SigningTime = GetSigningTimeOffset(xadesInfo.SigningDateTimeUTC, xadesInfo.TimeZoneOffsetMinutes);
  83.             return xadesObject;
  84.         }
  85.  
  86.         public static DateTimeOffset GetSigningTimeOffset(DateTime dtUTC, int timeZoneOffsetMinutes)
  87.         {
  88.             var dtUnspecified = DateTime.SpecifyKind(dtUTC.AddMinutes(timeZoneOffsetMinutes), DateTimeKind.Unspecified);
  89.             return new DateTimeOffset(dtUnspecified, new TimeSpan(0, timeZoneOffsetMinutes, 0));
  90.         }
  91.  
  92.         public static XadesSignedXml GetXadesSignedXml(X509Certificate2 certificate, XmlDocument originalDoc, string signatureid, string privateKeyPassword)
  93.         {
  94.             var secureString = new SecureString();
  95.             foreach (var ch in privateKeyPassword)
  96.                 secureString.AppendChar(ch);
  97.  
  98.             var provider = (Gost3410CryptoServiceProvider)certificate.PrivateKey;
  99.             provider.SetContainerPassword(secureString);
  100.  
  101.             var signedXml = new XadesSignedXml(originalDoc) { SigningKey = provider };
  102.  
  103.             signedXml.Signature.Id = signatureid;
  104.             signedXml.SignatureValueId = $"{signatureid}-sigvalue";
  105.  
  106.             var reference = new Reference
  107.             {
  108.                 Uri = "#signed-data-container",
  109.                 DigestMethod = CPSignedXml.XmlDsigGost3411UrlObsolete,
  110.                 Id = $"{signatureid}-ref0"
  111.             };
  112.             reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
  113.             reference.AddTransform(new XmlDsigExcC14NTransform());
  114.             signedXml.AddReference(reference);
  115.  
  116.             signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigCanonicalizationUrl;
  117.             signedXml.SignedInfo.SignatureMethod = CPSignedXml.XmlDsigGost3410UrlObsolete;
  118.  
  119.             return signedXml;
  120.         }
  121.  
  122.         public static KeyInfo GetKeyInfo(string rawPkString)
  123.         {
  124.             var keyInfo = new KeyInfo();
  125.  
  126.             var doc = new XmlDocument();
  127.             var keyInfoElement = (XmlElement)doc.AppendChild(doc.CreateElement("ds", "KeyInfo", "http://www.w3.org/2000/09/xmldsig#"));
  128.             var x509DataElement = doc.CreateElement("ds", "X509Data", "http://www.w3.org/2000/09/xmldsig#");
  129.             var x509DataNode = keyInfoElement.AppendChild(x509DataElement);
  130.             x509DataNode.AppendChild(doc.CreateElement("ds", "X509Certificate", "http://www.w3.org/2000/09/xmldsig#")).InnerText = rawPkString;
  131.  
  132.             keyInfo.AddClause(new KeyInfoNode(x509DataElement));
  133.             //keyInfo.AddClause(new KeyInfoX509Data(certificate));
  134.             return keyInfo;
  135.         }
  136.  
  137.         private static X509Certificate2 GetCertificateByThumbprint(string thumbprint)
  138.         {
  139.             var store = new X509Store("MY", StoreLocation.CurrentUser);
  140.             store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
  141.  
  142.             var fcollection = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
  143.             var cert = new X509Certificate2();
  144.             foreach (var x509 in fcollection)
  145.             {
  146.                 cert = x509;
  147.             }
  148.  
  149.             return cert;
  150.         }
  151.  
  152.         /// <summary>
  153.         /// Заменяет части IssuerName на OID. https://technet.microsoft.com/en-us/library/cc772812(WS.10).aspx
  154.         /// </summary>
  155.         /// <param name="issuerName"></param>
  156.         /// <returns></returns>
  157.         private static string GetOidRepresentation(string issuerName)
  158.         {
  159.             var result = issuerName;
  160.             result = result.Replace("E=", "1.2.840.113549.1.9.1=");
  161.             return result;
  162.         }
  163.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement