Ключевое слово в защите информации
ключевое слово
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход. Новые регистрации запрещены.

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline Kovalenko Nikita  
#1 Оставлено : 30 июля 2019 г. 11:15:34(UTC)
Kovalenko Nikita

Статус: Участник

Группы: Участники
Зарегистрирован: 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=

ЧЯДНТ?
Offline two_oceans  
#2 Оставлено : 30 июля 2019 г. 12:54:56(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 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:

Про первый фрагмент кода ничего сказать не могу, но выглядит правдоподобно.
Во втором фрагменте кода просто подписывается cadescom какой-то фрагмент текста, совсем не похоже на кучу шагов xmldsig.

Как Вы предлагаете пример проверить без сертификата? Пример в одном представлении, хэш в другом, подпись снова в первом. Ваш пример не декодировал - это предполагается результат шага 4 или шага 8? Если шага 4, то делаете неправильно (хэш от данных не подписывается, подписывается SignedInfo), если шага 8, то нет исходных данных чтобы проверить хэши в SignedInfo.

Значение подписи (шаг 9): для гост-2001 и гост-2012 256 верная длина 64 байта двоичных, в base64 будет 88 символов. У Вас что-то длинновата 130 символов. Для гост-2012 512 наоборот коротковата. Итого, у Вас значение подписи с обертками, смэв его не примет.

Отредактировано пользователем 30 июля 2019 г. 13:09:42(UTC)  | Причина: Не указана

Offline Kovalenko Nikita  
#3 Оставлено : 31 июля 2019 г. 11:00:07(UTC)
Kovalenko Nikita

Статус: Участник

Группы: Участники
Зарегистрирован: 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();
}


Далее подпись вставляю в конверт
Offline Kovalenko Nikita  
#4 Оставлено : 31 июля 2019 г. 11:01:02(UTC)
Kovalenko Nikita

Статус: Участник

Группы: Участники
Зарегистрирован: 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>
Offline two_oceans  
#5 Оставлено : 31 июля 2019 г. 11:47:11(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 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

Offline Kovalenko Nikita  
#6 Оставлено : 31 июля 2019 г. 14:06:46(UTC)
Kovalenko Nikita

Статус: Участник

Группы: Участники
Зарегистрирован: 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

Offline Kovalenko Nikita  
#7 Оставлено : 31 июля 2019 г. 14:16:21(UTC)
Kovalenko Nikita

Статус: Участник

Группы: Участники
Зарегистрирован: 05.03.2019(UTC)
Сообщений: 12
Российская Федерация

Сказал(а) «Спасибо»: 1 раз
Автор: two_oceans Перейти к цитате
На клиент передается только хэш от signedInfo?

Да. Сертификат точно тот, подтверждал
Offline two_oceans  
#8 Оставлено : 1 августа 2019 г. 5:58:44(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 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)  | Причина: Не указана

thanks 1 пользователь поблагодарил two_oceans за этот пост.
Kovalenko Nikita оставлено 01.08.2019(UTC)
Offline Kovalenko Nikita  
#9 Оставлено : 1 августа 2019 г. 10:13:45(UTC)
Kovalenko Nikita

Статус: Участник

Группы: Участники
Зарегистрирован: 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


Ни одно полученное значение с Вашим не совпадает Think Я как-то неправильно его считаю?
Offline two_oceans  
#10 Оставлено : 1 августа 2019 г. 10:49:13(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 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)  | Причина: Не указана

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.