internal static int GetAlgId(IntPtr certHandle) { try { if (certHandle == IntPtr.Zero) { throw new Exception("Ошибка при попытке получить Handle сертификата."); } var certContext = Marshal.PtrToStructure <CERT_CONTEXT>(certHandle); var certInfo = Marshal.PtrToStructure <CERT_INFO>(certContext.pCertInfo); var publicKeyAlg = certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId; string signatureAlgOid = GetSignatureAlg(publicKeyAlg); CRYPT_OID_INFO oidInfo = new CRYPT_OID_INFO(); if (IsUnix) { oidInfo = SignServiceUnix.GetHashAlg(signatureAlgOid); } else { oidInfo = SignServiceWin.GetHashAlg(signatureAlgOid); } return((int)oidInfo.Algid); } catch (Exception ex) { throw new CryptographicException($"Ошибка при получении хэш алгоритма ГОСТ. {ex.Message}."); } }
internal static HashAlgorithm GetHashAlgObject(IntPtr certificate, ref int algId) { var certContext = Marshal.PtrToStructure <CERT_CONTEXT>(certificate); var certInfo = Marshal.PtrToStructure <CERT_INFO>(certContext.pCertInfo); var publicKeyAlg = certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId; string signatureAlgOid = GetSignatureAlg(publicKeyAlg); if (IsUnix) { var algInfo = SignServiceUnix.GetHashAlg(signatureAlgOid); algId = (int)algInfo.Algid; if (algInfo.Algid == GOST341194) { return(new HashAlgGost2001Unix()); } else if (algInfo.Algid == GOST2012_256) { return(new HashAlgGost2012_256Unix()); } else if (algInfo.Algid == GOST2012_512) { return(new HashAlgGost2012_512Unix()); } else { throw new Exception($"Ошибка при попытке определить функцию хэширования."); } } else { var algInfo = SignServiceWin.GetHashAlg(signatureAlgOid); algId = (int)algInfo.Algid; if (algInfo.Algid == GOST341194) { return(new HashAlgGost2001Win()); } else if (algInfo.Algid == GOST2012_256) { return(new HashAlgGost2012_256Win()); } else if (algInfo.Algid == GOST2012_512) { return(new HashAlgGost2012_512Win()); } else { throw new Exception($"Ошибка при попытке определить функцию хэширования."); } } }
/// <summary> /// Метод получения хэндлера сертификата /// </summary> /// <param name="thumbprint"></param> /// <returns></returns> public IntPtr GetCertificateHandle(string thumbprint) { if (SignServiceUtils.IsUnix) { var unixService = new SignServiceUnix(loggerFactory); return(unixService.FindCertificate(thumbprint)); } else { var winService = new SignServiceWin(loggerFactory); return(winService.FindCertificate(thumbprint)); } }
/// <summary> /// Метод подписи данных /// </summary> /// <param name="data"></param> /// <param name="thumbprint"></param> /// <returns></returns> public byte[] Sign(byte[] data, string thumbprint) { if (SignServiceUtils.IsUnix) { var unixService = new SignServiceUnix(loggerFactory); return(unixService.Sign(data, thumbprint)); } else { var winService = new SignServiceWin(loggerFactory); return(winService.Sign(data, thumbprint)); } }
/// <summary> /// Метод получения хэш /// </summary> /// <param name="data"></param> /// <param name="algId"></param> /// <returns></returns> private string GetHashBySigAlgId(Stream data, uint algId) { if (SignServiceUtils.IsUnix) { log.LogDebug("Вычисляем хэш под Unix платформой."); var unixService = new SignServiceUnix(loggerFactory); return(unixService.GetHashBySigAlgId(data, algId)); } else { log.LogDebug("Вычисляем хэш под Windows платформой."); var winService = new SignServiceWin(loggerFactory); return(winService.GetHashBySigAlgId(data, algId)); } }
/// <summary> /// Метод проверки открепленной подписи /// </summary> /// <param name="sign"></param> /// <returns></returns> public bool VerifyDetachedMessage(byte[] sign, byte[] data, bool isCheckTrusted, ref X509Certificate2 certFromSign) { if (SignServiceUtils.IsUnix) { log.LogDebug("Выполняем проверку открепленной подписи под Unix платформой."); var unixService = new SignServiceUnix(loggerFactory); return(unixService.VerifyDetachedMessage(sign, data, isCheckTrusted, ref certFromSign)); } else { log.LogDebug("Выполняем проверку открепленной подписи под Windows платформой."); var winService = new SignServiceWin(loggerFactory); return(winService.VerifyDetachedMessage(sign, data, isCheckTrusted, ref certFromSign)); } }
/// <summary> /// Метод получения списка доверительных сертификатов /// </summary> /// <returns></returns> public X509Certificate2Collection GetTrustedCertificates() { X509Certificate2Collection confCertificates = new X509Certificate2Collection(); if (SignServiceUtils.IsUnix) { var unixService = new SignServiceUnix(loggerFactory); confCertificates = unixService.GetTrustedCertificates(); } else { var winService = new SignServiceWin(loggerFactory); confCertificates = winService.GetTrustedCertificates(); } return(confCertificates); }
/// <summary> /// Метод подписи XML /// </summary> /// <param name="xml"></param> /// <param name="mr"></param> /// <param name="thumbprint"></param> /// <returns></returns> public string SignSoap(string xml, Mr mr, string thumbprint) { string signedXml = string.Empty; if (SignServiceUtils.IsUnix) { log.LogDebug($"Попытка выполнить метод подписания XML под Unix платформой."); var unixService = new SignServiceUnix(loggerFactory); signedXml = unixService.SignSoap(xml, mr, thumbprint); } else { log.LogDebug($"Попытка выполнить метод подписания XML под Windows платформой."); var winService = new SignServiceWin(loggerFactory); signedXml = winService.SignSoap(xml, mr, thumbprint); } return(signedXml); }
/// <summary> /// Метод получения алгоритма хэширования /// </summary> /// <param name="signatureAlgOid"></param> /// <returns></returns> private uint GetHashAlg(string publicKeyAlg) { string signatureAlgOid = SignServiceUtils.GetSignatureAlg(publicKeyAlg); if (SignServiceUtils.IsUnix) { log.LogDebug("Получаем алгоритм хэширования под Unix платформой."); var cryptOidInfo = SignServiceUnix.GetHashAlg(signatureAlgOid); return(cryptOidInfo.Algid); } else { log.LogDebug("Получаем алгоритм хэширования под Windows платформой."); var cryptOidInfo = SignServiceWin.GetHashAlg(signatureAlgOid); return(cryptOidInfo.Algid); } }
/// <summary> /// Метод подписания вложений подписью органа власти /// </summary> /// <param name="doc"></param> /// <param name="certificate"></param> /// <returns></returns> private XmlDocument SignAttachmentsOv(XmlDocument doc, IntPtr certificate) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); string prefix = FindPrefix(doc.DocumentElement, true); nsmgr.AddNamespace(prefix, NamespaceUri.Smev3TypesBasic); log.LogDebug($"Пытаемся найти тэг заголовка вложений."); string findHeaderString = string.Format("//{0}:AttachmentHeaderList", prefix); XmlElement attachmentHeaderList = doc.SelectSingleNode(findHeaderString, nsmgr) as XmlElement; log.LogDebug($"Пытаемся найти тэг с контентом вложений."); string findContentString = string.Format("//{0}:AttachmentContentList", prefix); XmlElement attachmentContentList = doc.SelectSingleNode(findContentString, nsmgr) as XmlElement; if (attachmentHeaderList != null && attachmentContentList != null) { log.LogDebug("Список заголовков и контента с вложениями был успешно получен."); bool changed = false; AttachmentHeaderList headerList = null; try { log.LogDebug("Пытаемся получить объект AttachmentHeaderList."); headerList = DeserializeXml <AttachmentHeaderList>(attachmentHeaderList, NamespaceUri.Smev3TypesBasic); log.LogDebug("Объект AttachmentHeaderList успешно получен."); } catch (Exception ex) { throw new Exception($"Ошибка при получении объекта AttachmentHeaderList. {ex.Message}."); } // Если нет информации о вложениях if (headerList == null || headerList.AttachmentHeader == null || headerList.AttachmentHeader.Length <= 0) { log.LogDebug("Вложения для подписи не найдены."); return(doc); } // Проверим есть ли вложения для которых необходима подпись log.LogDebug("Проверим есть ли вложения для которых необходима подпись."); var needSigned = false; foreach (var header in headerList.AttachmentHeader) { if (header.SignaturePKCS7 == null || header.SignaturePKCS7.Length <= 0) { log.LogDebug($"Вложение {header.contentId} нуждается в подписи."); needSigned = true; break; } } // Если все вложения уже подписаны, выходим if (!needSigned) { log.LogDebug("Все вложения являются подписанными."); return(doc); } // Пытаемся получить список контента вложений. Обрабатывает только вложения указанные в XML в виде base64 строки, для случаев с // расположением вложения на FTP или в случае если данный XML является частью МТОМ запроса предполагается что вложения были подписаны отдельно, заранее AttachmentContentList contentList = null; try { contentList = DeserializeXml <AttachmentContentList>(attachmentContentList, NamespaceUri.Smev3TypesBasic); } catch (Exception ex) { throw new Exception($"Ошибка при десериализации контента вложений. " + $"Убедитесь, что для вложений, которые находятся на FTP, или будут расположены в МТОМ запросе подпись была получена отдельно. " + $"Содержимое ошибки {ex.Message}."); } if (contentList != null && contentList.AttachmentContent != null && contentList.AttachmentContent.Length > 0) { foreach (AttachmentHeaderType header in headerList.AttachmentHeader) { if (header.SignaturePKCS7 == null || header.SignaturePKCS7.Length == 0) { log.LogDebug($"В заголовке вложения отсутствует подпись. Пытаемся подписать."); AttachmentContentType content = contentList.AttachmentContent.FirstOrDefault(cnt => cnt.Id == header.contentId); if (content != null && content.Content != null && content.Content.Length > 0) { byte[] signature = null; try { if (SignServiceUtils.IsUnix) { log.LogDebug($"Выполняем подпись под Unix платформой."); signature = SignServiceUnix.Sign(content.Content, certificate); } else { log.LogDebug($"Выполняем подпись под Windows платформой."); signature = SignServiceWin.Sign(content.Content, certificate); } } catch (Exception ex) { throw new Exception($"Ошибка при вычислении подписи для вложения. {ex.Message}."); } header.SignaturePKCS7 = signature; changed = true; } } } if (changed) { string prefixForSerialize = FindPrefix(doc.DocumentElement, false); try { log.LogDebug($"Пытаемся обновить список вложений."); XmlElement attachmentHeaderListNew = this.SerializeToXmlElement(headerList, NamespaceUri.Smev3TypesBasic, prefixForSerialize); attachmentHeaderListNew = doc.ImportNode(attachmentHeaderListNew, true) as XmlElement; attachmentHeaderList.ParentNode.ReplaceChild(attachmentHeaderListNew, attachmentHeaderList); log.LogDebug("Список вложений успешно обновлен."); } catch (Exception ex) { throw new Exception($"Ошибка при попытке обновить подписанные вложения. {ex.Message}."); } } } } return(doc); }