Статус: Участник
Группы: Участники
Зарегистрирован: 05.03.2019(UTC) Сообщений: 12  Сказал(а) «Спасибо»: 1 раз
|
Здравствуйте! Я пытаюсь получить конверт с ЭП-СП подписью, который пройдёт проверку на https://smev3.gosuslugi.ru/portal/checkxmlform.jsp. Установлены JCP 2.0, CSP 4.0.9963. С помощью 11 версии клиента такой конверт удаётся получить следующим образом: Код:
String xml = "...";
Document doc = parseXML(xml);
Element data = doc.getDocumentElement();
Element sign = ru.smevx.crypto.smev3.xmldsig.XmlDSignUtils.sign(privateKey, cert, data);
При попытке получить хэш и подписать его на клиенте, падает ошибка "ЭП-СП не подтверждена: #PERSONAL_SIGNATURE Ошибка проверки ЭП: Нарушена целостность ЭП". Код функции, в которую приходит SignedInfo в Base64-виде пример: Код:
var CAPICOM_ENCODE_BASE64 = 0;
...
if (args.toSign) {
try {
var oHashedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.HashedData");
oHashedData.Algorithm = cadesplugin.CADESCOM_HASH_ALGORITHM_CP_GOST_3411; // ГОСТ Р 34.11-94
oHashedData.DataEncoding = cadesplugin.CADESCOM_BASE64_TO_BINARY;
yield oHashedData.Hash(args.toSign);
var oRawSignature = yield cadesplugin.CreateObjectAsync("CAdESCOM.RawSignature");
var signHash;
var certData;
// Вычисляем значение подписи
try {
signHash = yield oRawSignature.SignHash(oHashedData, oCertificate);
} catch (err) {
alert("Failed to create signature. Error: " + cadesplugin.getLastError(err));
return;
}
var signature = Base64.encode(utils.reverse(utils.hexToString(signHash)));
args.sig = signature;
certData = yield oCertificate.Export(CAPICOM_ENCODE_BASE64);
args.cert = certData;
} catch (err) {
alert(err);
}
}
Пример: PGRzOlNpZ25lZEluZm8geG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIj48L2RzOkNhbm9uaWNhbGl6YXRpb25NZXRob2Q+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI2dvc3RyMzQxMDIwMDEtZ29zdHIzNDExIj48L2RzOlNpZ25hdHVyZU1ldGhvZD48ZHM6UmVmZXJlbmNlIFVSST0iI1BFUlNPTkFMX1NJR05BVFVSRSI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyI+PC9kczpUcmFuc2Zvcm0+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09InVybjovL3NtZXYtZ292LXJ1L3htbGRzaWcvdHJhbnNmb3JtIj48L2RzOlRyYW5zZm9ybT48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI2dvc3RyMzQxMSI+PC9kczpEaWdlc3RNZXRob2Q+PGRzOkRpZ2VzdFZhbHVlPnFUNFlDVWxOLzdVYnNPTUg2V1FlYzZoUW5CSDhONE5YNVRDalF6TFZpNEE9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8+, хэш от него: F58DAA2F071BF497366DA3A45B2750D55188DB7757BFAFC9190ECD66AD4E2AD1, подпись: wpJ+w7RpF8OowrJDYnhCwqrDq0piGDrCi3jCsmTDm8KNw7TCk8ODw7MOwoHDgMOtwp7DtgUrLQnCoTQpOU3Cv8OFVMONNTR+bWDCkMOiw57DkHxhdjPDiCvCqsOSwok= ЧЯДНТ?
|
|
|
|
|
|
Статус: Эксперт
Группы: Участники
Зарегистрирован: 05.03.2015(UTC) Сообщений: 1,602  Откуда: Иркутская область Сказал(а) «Спасибо»: 110 раз Поблагодарили: 398 раз в 367 постах
|
Цитата:Пример: PGRzOlNpZ25lZEluZm8geG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpDYW5vbmljYWxpemF0aW9uT WV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIj48L2RzOkNhbm9uaWNhbGl6YXRpb25NZX Rob2Q+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI2dvc3RyMzQ xMDIwMDEtZ29zdHIzNDExIj48L2RzOlNpZ25hdHVyZU1ldGhvZD48ZHM6UmVmZXJlbmNlIFVSST0iI1BFUlNPTkFMX1NJR05BVFVSRSI+PGRz OlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyI+PC9kc zpUcmFuc2Zvcm0+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09InVybjovL3NtZXYtZ292LXJ1L3htbGRzaWcvdHJhbnNmb3JtIj48L2RzOlRyYW 5zZm9ybT48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHN pZy1tb3JlI2dvc3RyMzQxMSI+PC9kczpEaWdlc3RNZXRob2Q+PGRzOkRpZ2VzdFZhbHVlPnFUNFlDVWxOLzdVYnNPTUg2V1FlYzZoUW5CSDhO NE5YNVRDalF6TFZpNEE9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8+, хэш от него: F58DAA2F071BF497366DA3A45B2750D55188DB7757BFAFC9190ECD66AD4E2AD1, подпись: wpJ+w7RpF8OowrJDYnhCwqrDq0piGDrCi3jCsmTDm8KNw7TCk8ODw7MOwoHDgMOtwp7DtgUrLQnCoTQpOU3Cv8OFVMONNTR+bWDCkMOiw57Dk HxhdjPDiCvCqsOSwok=
ЧЯДНТ? Добрый день. Вкратце шаги xmldsig / xades:
1) выделяется фрагмент документа, который нужно подписать - как поток байтов в кодировке UTF-8, предполагается что переводы строк были нормализованы. 2) создается узел Signature и его базовая структура SignedInfo SignatureValue KeyInfo (обязательны для смэв) Object (обязателен если xades). В начале важен узел SignedInfo c узлами SignatureMethod CanonicalizationMethod Reference. 3) В Reference добавляются нужные для смэв трансформы (эксклюзивная каноникализация и смэвовский трансформ) и ссылка на подписываемый элемент, алгоритм хэша. 4) над результатом первого шага проводятся указанные трансформы 5) от результата шага 4 вычисляется хэш, значение хэша в base64 добавляется в Reference 6) С первым референс закончили. При необходимости добавляется Reference для расширения xades по аналогии шагов 3-5. Само расширение вкладывается в подузел Object узла Signature, проставляются необходимые ID и ссылки на них в URI. 7) после добавления всех Reference значение SignedInfo фиксируется (больше изменять нельзя!) и получается как поток байтов в UTF-8 8) к результату 7 применяется CanonicalizationMethod 9) от результата 8 вычисляется "голая" подпись по алгоритму SignatureMethod, в base64 кодировке записывается в SignatureValue. 10) заполняется информация о сертификате в KeyInfo, обычно это сам сертификат в base64 кодировке в KeyInfo/ X509Data/ X509Certificate. Подробнее есть в документации СМЭВ или http://minichden.narod.ru/articles/xmldsig.htm (тут про xmldsig вообще, не для гост и смэв, но для понимания точной последовательности действий пойдет)
Про первый фрагмент кода ничего сказать не могу, но выглядит правдоподобно. Во втором фрагменте кода просто подписывается cadescom какой-то фрагмент текста, совсем не похоже на кучу шагов xmldsig. Как Вы предлагаете пример проверить без сертификата? Пример в одном представлении, хэш в другом, подпись снова в первом. Ваш пример не декодировал - это предполагается результат шага 4 или шага 8? Если шага 4, то делаете неправильно (хэш от данных не подписывается, подписывается SignedInfo), если шага 8, то нет исходных данных чтобы проверить хэши в SignedInfo. Значение подписи (шаг 9): для гост-2001 и гост-2012 256 верная длина 64 байта двоичных, в base64 будет 88 символов. У Вас что-то длинновата 130 символов. Для гост-2012 512 наоборот коротковата. Итого, у Вас значение подписи с обертками, смэв его не примет. Отредактировано пользователем 30 июля 2019 г. 13:09:42(UTC)
| Причина: Не указана
|
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 05.03.2019(UTC) Сообщений: 12  Сказал(а) «Спасибо»: 1 раз
|
Откатился до предыдущей кодовой базы, там хотя бы была правильная длина подписи. На Java 7 поставлена JCP 2.0, из папки ext удалён артефакт JCPxml и вместе с xmlsec добавлен в зависимости проекта: Код:<dependency>
<groupId>JCPxml</groupId>
<artifactId>JCPxml</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.santuario</groupId>
<artifactId>xmlsec</artifactId>
<version>1.5.8</version>
</dependency>
0) Инициализация + регистрация алгоритма: Код:private static void initXmlSec() throws Exception {
// При формировании элемента Signature будут убраны все разрывы между элементами.
System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true");
//Добавил инициализацию из документации jsp : jcp-build-2.0.37027
//Перед началом использования классов из библиотеки XML Security необходимо зарегистрировать ГОСТ алгоритмы.
// Регистрируем реализации алгоритмов в xmlsec.
if (!JCPXMLDSigInit.isInitialized()) {
JCPXMLDSigInit.init();
}
// Реализация дополнительной трансформации.
Transform.register(SmevTransformSpi.ALGORITHM_URN, SmevTransformSpi.class.getName());
hackXmlsecIgnoreLineBreaks();
}
private static void hackXmlsecIgnoreLineBreaks() throws PrivilegedActionException {
AccessController.doPrivileged(new PrivilegedExceptionAction < Boolean > () {
@Override
public Boolean run() throws Exception {
Field f = XMLUtils.class.getDeclaredField("ignoreLineBreaks");
f.setAccessible(true);
f.set(null, true);
return false;
}
});
}
1) Беру кусок конверта из тестового смэв3 конверта и формирую для него док: Код:final String xml = "<ns1:BreachRequest xmlns:ns1=\"urn://x-artefacts-gibdd-gov-ru/breach/root/1.0\" xmlns:ns2=\"urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0\" xmlns:ns3=\"urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1\" xmlns:ns4=\"xml:id\" Id=\"PERSONAL_SIGNATURE\"><ns1:RequestedInformation><ns2:RegPointNum>Т785ЕС57</ns2:RegPointNum></ns1:RequestedInformation><ns1:Governance><ns2:Name>ГИБДД РФ</ns2:Name><ns2:Code>GIBDD</ns2:Code><ns2:OfficialPerson><ns3:FamilyName>Загурский</ns3:FamilyName><ns3:FirstName>Андрей</ns3:FirstName><ns3:Patronymic>Петрович</ns3:Patronymic></ns2:OfficialPerson></ns1:Governance></ns1:BreachRequest>";
final Element doc = ru.it.poltava.xml.XMLTransformHelper.buildDocumentFromString(xml).getDocumentElement();
2) Получение хэша для подписи: Код:public String buildHashForSignByBusinessContent() throws XMLSecurityException {
// Формируем с заполненными трасформ алгоритмами объект SignedInfo со сгенерированным DigestValue,
XMLSignature xmlSignature = buildXMLSignatureTemplate(doc);
// получаем массив byte[] с канокализированным значением SignedInfo
byte[] canonicalizeOctetStream = xmlSignature.getSignedInfo().getCanonicalizedOctetStream();
// необходимо посчитать хэш по алгоритму гост и закодировать его в шеснадцатерично-десятичном формате.
String hash3411Base64 = CryptoUtil.buildHash3411Base64(canonicalizeOctetStream);
return CryptoUtil.getHexadecimalHash(hash3411Base64);
}
private XMLSignature buildXMLSignatureTemplate() throws XMLSecurityException {
Document document = doc.getOwnerDocument();
XMLSignature xmlSignature = new XMLSignature(document, "", XMLDSIG_SIGN_METHOD, Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
Transforms transforms = new Transforms(document);
transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
transforms.addTransform(SmevTransformSpi.ALGORITHM_URN);
String refURI = document.getDocumentElement().getAttribute("Id");
if (!refURI.isEmpty() && !refURI.startsWith("#")) {
refURI = "#" + refURI;
}
xmlSignature.addDocument(refURI, transforms, DIGEST_METHOD);
xmlSignature.getSignedInfo().generateDigestValues();
return xmlSignature;
}
static String buildHash3411Base64(byte[] data) {
byte[] hash = buildHash3411(data);
return hash != null ? Base64.encodeBase64String(data) : "";
}
static String getHexadecimalHash(String hashInBase64) {
String hexadecimalHash = "";
try {
byte[] encodedBytes = Base64.decodeBase64(hashInBase64);
hexadecimalHash = toHex(encodedBytes);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, null, e);
}
return hexadecimalHash;
}
3) Полученное в результате buildXMLSignatureTemplate отправляю на клиент для подписи: Код:function signHashRawAndGetCertificate_Async(certListBoxId, handleFunction, args) {
cadesplugin.async_spawn(function*(arg) {
var CAPICOM_ENCODE_BASE64 = 0;
var oCertificate;
var certData;
var oHashedData;
var oRawSignature;
var sRawSignature;
var e = document.getElementById(arg[0]);
var selectedCertID = e.selectedIndex;
if (selectedCertID == -1) {
alert("Select certificate");
return;
}
var thumbprint = e.options[selectedCertID].value.split(" ").reverse().join("").replace(/\s/g, "").toUpperCase();
try {
var oStore = yield cadesplugin.CreateObjectAsync("CAdESCOM.Store");
yield oStore.Open();
} catch (err) {
alert('Failed to create CAdESCOM.Store: ' + err.number);
return;
}
var all_certs = yield oStore.Certificates;
var oCerts = yield all_certs.Find(cadesplugin.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, thumbprint);
if ((yield oCerts.Count) == 0) {
alert("Certificate not found");
return;
}
oCertificate = yield oCerts.Item(1);
try{
// Создаем объект CAdESCOM.HashedData
oHashedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.HashedData");
// Инициализируем объект заранее вычисленным хэш-значением
// Алгоритм хэширования нужно указать до того, как будет передано хэш-значение
oHashedData.Algorithm = cadesplugin.CADESCOM_HASH_ALGORITHM_CP_GOST_3411; // ГОСТ Р 34.11-94
oHashedData.SetHashValue(args.toSign);
if (args.toSign) {
// Создаем объект CAdESCOM.RawSignature
oRawSignature = yield cadesplugin.CreateObjectAsync("CAdESCOM.RawSignature");
// Вычисляем значение подписи
try {
sRawSignature = yield oRawSignature.SignHash(oHashedData, oCertificate);
} catch (err) {
alert("Failed to create signature. Error: " + cadesplugin.getLastError(err));
return;
}
try {
oRawSignature.VerifyHash(oHashedData, oCertificate, sRawSignature);
} catch (err) {
alert("Failed to verify signature. Error: " + cadesplugin.getLastError(err));
}
certData = yield oCertificate.Export(CAPICOM_ENCODE_BASE64);
}
args.sig = sRawSignature;
args.cert = certData;
handleFunction(args);
}catch(err){
alert(err);
}
}, certListBoxId); //cadesplugin.async_spawn
}
4) Обработка результата от плагина: Код:public String buildXmlSigDetached(String cspSignHexadecimal, String x509certificateBase64) throws Exception {
String signatureValue = buildSignatureValueByCspSignHexadecimal(cspSignHexadecimal);
Element personalSignature = buildSignatureTemplateByBusinessContent(doc, x509certificateBase64);
personalSignature.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "SignatureValue")
.item(0).setTextContent(signatureValue);
return XMLTransformHelper.elementToString(personalSignature);
}
private String buildSignatureValueByCspSignHexadecimal(String cspSignHexadecimal) throws DecoderException {
byte[] signBytes = Hex.decodeHex(cspSignHexadecimal.toCharArray());
ArrayUtils.reverse(signBytes);
return new Base64().encodeAsString(signBytes);
}
private Element buildSignatureTemplateByBusinessContent(String x509certificateBase64) throws XMLSecurityException, CertificateException, IOException {
XMLSignature xmlSignature = buildXMLSignatureTemplate(doc);
X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(Base64.decodeBase64(x509certificateBase64)));
xmlSignature.addKeyInfo(certificate);
return xmlSignature.getElement();
}
Далее подпись вставляю в конверт
|
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 05.03.2019(UTC) Сообщений: 12  Сказал(а) «Спасибо»: 1 раз
|
Полученный конверт: Код:<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1">
<S:Body>
<ns2:SendRequestRequest xmlns:ns3="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/faults/1.1" xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1">
<ns:SenderProvidedRequestData Id="signed" xmlns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns:ns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1">
<ns:MessageID>db0486d0-3c08-11e5-95e2-d4c9eff07b77</ns:MessageID>
<ns2:MessagePrimaryContent>
<ns1:BreachRequest xmlns:ns1="urn://x-artefacts-gibdd-gov-ru/breach/root/1.0" xmlns:ns2="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0" xmlns:ns3="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1" xmlns:ns4="xml:id" Id="PERSONAL_SIGNATURE"><ns1:RequestedInformation><ns2:RegPointNum>Т785ЕС57</ns2:RegPointNum></ns1:RequestedInformation><ns1:Governance><ns2:Name>ГИБДД РФ</ns2:Name><ns2:Code>GIBDD</ns2:Code><ns2:OfficialPerson><ns3:FamilyName>Загурский</ns3:FamilyName><ns3:FirstName>Андрей</ns3:FirstName><ns3:Patronymic>Петрович</ns3:Patronymic></ns2:OfficialPerson></ns1:Governance></ns1:BreachRequest>
</ns2:MessagePrimaryContent>
<ns:TestMessage />
</ns:SenderProvidedRequestData>
<ns2:CallerInformationSystemSignature>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/><ds:Reference URI="#PERSONAL_SIGNATURE"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:Transform Algorithm="urn://smev-gov-ru/xmldsig/transform"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/><ds:DigestValue>AUGmtYkL7MD5MqwxwcQULupXi6FtvCrsHED26tKroC0=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>2+j/iappX7sUT6rqnQqw++kjehfSTgZLx8ZrJM3wsoT55PyKYPjHTbGMTnoCm2VE4TtuqZTRileVF8tx7HgVaQ==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIDrjCCA12gAwIBAgITEgA5SE8SyPDSnsGuvQABADlITzAIBgYqhQMCAgMwfzEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBjcnlwdG9wcm8ucnUxCzAJBgNVBAYTAlJVMQ8wDQYDVQQHEwZNb3Njb3cxFzAVBgNVBAoTDkNSWVBUTy1QUk8gTExDMSEwHwYDVQQDExhDUllQVE8tUFJPIFRlc3QgQ2VudGVyIDIwHhcNMTkwNzMxMDUxNDA0WhcNMTkxMDMxMDUyNDA0WjCBtjEiMCAGCSqGSIb3DQEJARYTcGVuZHJhZ29uQGdtYWlsLmNvbTE3MDUGA1UEAwwu0J/QtdC90LTRgNCw0LPQvtC9INCc0LDRgNC40Y8g0KPRgtC10YDQvtCy0L3QsDEVMBMGA1UECwwMQ2lyY2xlIFRhYmxlMRAwDgYDVQQKDAdDYW1lbG90MQ8wDQYDVQQHDAZMb25kb24xEDAOBgNVBAgMB0NhbWVsb3QxCzAJBgNVBAYTAlVLMGMwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwICHgEDQwAEQO3zup3Nt6/tcaJdLVmapDorHWqo06AiSDwkhcWvKG2FhtbprMWEe4f2Ba+s6y2iyOVwlUqcXjxQrWQbzIHCJSSjggF2MIIBcjAOBgNVHQ8BAf8EBAMCBPAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0OBBYEFBiGzaG71oeHaUZGKl7R1UtIwsJcMB8GA1UdIwQYMBaAFE6DPhRp7+xdepUrXxH+NzIWSVUrMFwGA1UdHwRVMFMwUaBPoE2GS2h0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L0NlcnRFbnJvbGwvQ1JZUFRPLVBSTyUyMFRlc3QlMjBDZW50ZXIlMjAyKDEpLmNybDCBrAYIKwYBBQUHAQEEgZ8wgZwwZAYIKwYBBQUHMAKGWGh0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L0NlcnRFbnJvbGwvdGVzdC1jYS0yMDE0X0NSWVBUTy1QUk8lMjBUZXN0JTIwQ2VudGVyJTIwMigxKS5jcnQwNAYIKwYBBQUHMAGGKGh0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L29jc3Avb2NzcC5zcmYwCAYGKoUDAgIDA0EACyrLCzVM5fU9bOlylTkUcye5tFj96bVAA0dKD8xmho++bYgjxm23L96BWGN/a+Y5zMeQShG1lPvkQDriIiE8BQ==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>
</ns2:CallerInformationSystemSignature>
</ns2:SendRequestRequest>
</S:Body>
</S:Envelope>
|
|
|
|
|
|
Статус: Эксперт
Группы: Участники
Зарегистрирован: 05.03.2015(UTC) Сообщений: 1,602  Откуда: Иркутская область Сказал(а) «Спасибо»: 110 раз Поблагодарили: 398 раз в 367 постах
|
По конверту: моя программа показывает совпадение DigestValue, но ошибку в SignatureValue. На клиент передается только хэш от signedInfo? Похоже неправильно срабатывает обмен с клиентом или клиент - либо подписано другим сертификатом либо хэш SignedInfo от которого вычислено значение подписи отличается от хэша SignedInfo в конверте (например, getCanonicalizedOctetStream использует не эксклюзивный вариант каноникализации, а в подписи указан эксклюзивный или какие-то символы потерялись при копировании на форум). По мелочам - интересно видеть рефененс на #PERSONAL_SIGNATURE в CallerInformationSystemSignature. Ну положение это конечно мелочи, которые можно и потом отладить, но имейте в виду что в Вашем конверте CallerInformationSystemSignature должна быть от #signed, а от #PERSONAL_SIGNATURE действительно должно быть в PersonalSignature. Сертификат поднял настроение, спасибо. Отредактировано пользователем 31 июля 2019 г. 13:05:33(UTC)
| Причина: getCanonicalizedOctetStream
|
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 05.03.2019(UTC) Сообщений: 12  Сказал(а) «Спасибо»: 1 раз
|
Распечатал каноникализированный SignedInfo: Код:byte[] canonicalizeOctetStream = xmlSignature.getSignedInfo().getCanonicalizedOctetStream();
LOGGER.info(new String(canonicalizeOctetStream));
Код:<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"></ds:SignatureMethod><ds:Reference URI="#PERSONAL_SIGNATURE"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform><ds:Transform Algorithm="urn://smev-gov-ru/xmldsig/transform"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"></ds:DigestMethod><ds:DigestValue>AUGmtYkL7MD5MqwxwcQULupXi6FtvCrsHED26tKroC0=</ds:DigestValue></ds:Reference></ds:SignedInfo>
И то, что приходит плагину на подпись: Код:3C 64 73 3A 53 69 67 6E 65 64 49 6E 66 6F 20 78 6D 6C 6E 73 3A 64 73 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 32 30 30 30 2F 30 39 2F 78 6D 6C 64 73 69 67 23 22 3E 3C 64 73 3A 43 61 6E 6F 6E 69 63 61 6C 69 7A 61 74 69 6F 6E 4D 65 74 68 6F 64 20 41 6C 67 6F 72 69 74 68 6D 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 32 30 30 31 2F 31 30 2F 78 6D 6C 2D 65 78 63 2D 63 31 34 6E 23 22 3E 3C 2F 64 73 3A 43 61 6E 6F 6E 69 63 61 6C 69 7A 61 74 69 6F 6E 4D 65 74 68 6F 64 3E 3C 64 73 3A 53 69 67 6E 61 74 75 72 65 4D 65 74 68 6F 64 20 41 6C 67 6F 72 69 74 68 6D 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 32 30 30 31 2F 30 34 2F 78 6D 6C 64 73 69 67 2D 6D 6F 72 65 23 67 6F 73 74 72 33 34 31 30 32 30 30 31 2D 67 6F 73 74 72 33 34 31 31 22 3E 3C 2F 64 73 3A 53 69 67 6E 61 74 75 72 65 4D 65 74 68 6F 64 3E 3C 64 73 3A 52 65 66 65 72 65 6E 63 65 20 55 52 49 3D 22 23 50 45 52 53 4F 4E 41 4C 5F 53 49 47 4E 41 54 55 52 45 22 3E 3C 64 73 3A 54 72 61 6E 73 66 6F 72 6D 73 3E 3C 64 73 3A 54 72 61 6E 73 66 6F 72 6D 20 41 6C 67 6F 72 69 74 68 6D 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 32 30 30 31 2F 31 30 2F 78 6D 6C 2D 65 78 63 2D 63 31 34 6E 23 22 3E 3C 2F 64 73 3A 54 72 61 6E 73 66 6F 72 6D 3E 3C 64 73 3A 54 72 61 6E 73 66 6F 72 6D 20 41 6C 67 6F 72 69 74 68 6D 3D 22 75 72 6E 3A 2F 2F 73 6D 65 76 2D 67 6F 76 2D 72 75 2F 78 6D 6C 64 73 69 67 2F 74 72 61 6E 73 66 6F 72 6D 22 3E 3C 2F 64 73 3A 54 72 61 6E 73 66 6F 72 6D 3E 3C 2F 64 73 3A 54 72 61 6E 73 66 6F 72 6D 73 3E 3C 64 73 3A 44 69 67 65 73 74 4D 65 74 68 6F 64 20 41 6C 67 6F 72 69 74 68 6D 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 32 30 30 31 2F 30 34 2F 78 6D 6C 64 73 69 67 2D 6D 6F 72 65 23 67 6F 73 74 72 33 34 31 31 22 3E 3C 2F 64 73 3A 44 69 67 65 73 74 4D 65 74 68 6F 64 3E 3C 64 73 3A 44 69 67 65 73 74 56 61 6C 75 65 3E 41 55 47 6D 74 59 6B 4C 37 4D 44 35 4D 71 77 78 77 63 51 55 4C 75 70 58 69 36 46 74 76 43 72 73 48 45 44 32 36 74 4B 72 6F 43 30 3D 3C 2F 64 73 3A 44 69 67 65 73 74 56 61 6C 75 65 3E 3C 2F 64 73 3A 52 65 66 65 72 65 6E 63 65 3E 3C 2F 64 73 3A 53 69 67 6E 65 64 49 6E 66 6F 3E
|
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 05.03.2019(UTC) Сообщений: 12  Сказал(а) «Спасибо»: 1 раз
|
Автор: two_oceans  На клиент передается только хэш от signedInfo? Да. Сертификат точно тот, подтверждал
|
|
|
|
|
|
Статус: Эксперт
Группы: Участники
Зарегистрирован: 05.03.2015(UTC) Сообщений: 1,602  Откуда: Иркутская область Сказал(а) «Спасибо»: 110 раз Поблагодарили: 398 раз в 367 постах
|
SignedInfo на взгляд совпало с выведенным у меня в программе. А вот что приходит плагину на подпись и близко не похоже на хэш: длина 2150 символов+1(пробел) /3 (2 шестнадцатиричных символа + пробел) = 717 декодированных байт. Вспоминаем для гост-2001 длина хэша 32 байта, а 717 символов это длина самого стрима от SignedInfo. Начинаем декодировать выходит "<ds:SignedInfo xmlns:"... В итоге получается на клиент приходит не хэш, а само значение SignedInfo (вероятно неправильно срабатывает buildHash3411 возвращая входное значение без изменений), но похоже клиент считает что пришел хэш и загружает как хэш. UPD: Вот значение хэша от SignedInfo идущего на проверку из моей программы (в разных endian в шестнадцатиричном виде и в Base64). Какой где endian я уже немного запутался, кажется сначала 2 строки little, потом 2 строки big. Код:3712 69C2 0FD3 263C 60F1 F6FF 72C9 D50F 3FF7 7AEA 0421 CC22 D417 E2D1 23BB 9502
NxJpwg/TJjxg8fb/csnVDz/3euoEIcwi1Bfi0SO7lQI=
0295 BB23 D1E2 17D4 22CC 2104 EA7A F73F 0FD5 C972 FFF6 F160 3C26 D30F C269 1237
ApW7I9HiF9QizCEE6nr3Pw/VyXL/9vFgPCbTD8JpEjc=
Отредактировано пользователем 1 августа 2019 г. 6:24:58(UTC)
| Причина: Не указана
|
 1 пользователь поблагодарил two_oceans за этот пост.
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 05.03.2019(UTC) Сообщений: 12  Сказал(а) «Спасибо»: 1 раз
|
Попробовал сделать следующее: 0) Посчитал хэш от пустой строки с помощью плагина Код:var objHashedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.HashedData");
objHashedData.Algorithm = cadesplugin.CADESCOM_HASH_ALGORITHM_CP_GOST_3411; // ГОСТ Р 34.11-94
objHashedData.Hash("");
var hashValue = yield objHashedData.Value;
console.log("Hash from empty string: " + hashValue);
получил Код:981E5F3CA30C841487830F84FB433E13AC1101569B9C13584AC483234CD656C0
Если верить статье https://habr.com/ru/post/189596/, он правильный. Цитата:Для GOST3411 это следующие значения: base64: mB5fPKMMhBSHgw+E+0M+E6wRAVabnBNYSsSDI0zWVsA= hex: 98 1e 5f 3c a3 0c 84 14 87 83 0f 84 fb 43 3e 13 ac 11 01 56 9b 9c 13 58 4a c4 83 23 4c d6 56 c0 1) Передал каноникализированный SignedInfo на клиент в base64 (CryptoUtil.buildHash3411Base64 и CryptoUtil.getHexadecimalHash удалил) 2) Посчитал от него хэш: Код:var objHashedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.HashedData");
objHashedData.Algorithm = cadesplugin.CADESCOM_HASH_ALGORITHM_CP_GOST_3411; // ГОСТ Р 34.11-94
objHashedData.DataEncoding = cadesplugin.CADESCOM_BASE64_TO_BINARY;
objHashedData.Hash(args.toSign);
var hashValue = yield objHashedData.Value;
console.log("Hash from args.toSign: " + hashValue);
получил Код:017ECC86FA1E9D463578987C3878C4E08A82C36E20F2481468EB8F698D310F70
3) И от него же, предварительно раскодировав: Код:var objHashedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.HashedData");
objHashedData.Algorithm = cadesplugin.CADESCOM_HASH_ALGORITHM_CP_GOST_3411; // ГОСТ Р 34.11-94
tempHashedData2.Hash(Base64.decode(args.toSign));
var hashValue = yield objHashedData.Value;
console.log("Hash from decode string: " + hashValue);
получил Код:CCE9DCB34BB3EA4B943C23B532821ADE52E4E5762B966F581B1FCD29C51253AA
Ни одно полученное значение с Вашим не совпадает  Я как-то неправильно его считаю?
|
|
|
|
|
|
Статус: Эксперт
Группы: Участники
Зарегистрирован: 05.03.2015(UTC) Сообщений: 1,602  Откуда: Иркутская область Сказал(а) «Спасибо»: 110 раз Поблагодарили: 398 раз в 367 постах
|
Хм, вопрос конечно интересный: Доказательный эксперимент при помощи утилиты от КриптоПро без написанного нами кода. Сохранил каноникализированное значение SignedInfo которое Вы в одном из прошлых сообщений указывали в файл 8_si.xml без всяких символов в начале и конце, 717 байт в UTF-8 без BOM (перепроверил в Far). Файл null.txt пустой. Выполнил командный файл следующего содержания: Код:@echo off
echo GR3411
"C:\Program Files (x86)\Crypto Pro\CSP\cpverify.exe" -mk -alg GR3411 null.txt -inverted_halfbytes 0
"C:\Program Files (x86)\Crypto Pro\CSP\cpverify.exe" -mk -alg GR3411 8_si.xml -inverted_halfbytes 0
pause
Вывод консоли: Код:GR3411
981E5F3CA30C841487830F84FB433E13AC1101569B9C13584AC483234CD656C0
371269C20FD3263C60F1F6FF72C9D50F3FF77AEA0421CC22D417E2D123BB9502
Для продолжения нажмите любую клавишу . . .
Как видите эталонное значение совпадает с хабром и Вашим значением, а от SignedInfo хэш совпадает с тем, что вывела моя программа. Полагаю, у Вас какие-то другие данные на хэширование идут. Отредактировано пользователем 1 августа 2019 г. 10:52:19(UTC)
| Причина: Не указана
|
|
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close