Электронная подпись ГОСТ Р 34.10 документов формата PDF в офисном пакете LibreOffice

    Пришла пора, несмотря на все пожары, исполнить свой гражданский долг – заплатить налоги. Платить налоги мы будем через портал Госуслуги. В личный кабинет портала Госуслуг будем входить с помощью электронной подписи (терминология портала Госуслуг ), т.е. имея на руках сертификат, полученный в аккредитованном удостоверяющем центре (УЦ), и закрытый ключ. И то и другое я храню на токене PKCS#11 с поддержкой российской криптографии:



    И вот, выполнив свой гражданский долг, я решил еще раз проверить работу электронной подписи в офисном пакете libreoffice.

    Почему я решил это сделать? Для доступа к порталу Госуслуг я использую ОС Linux и браузер Redfox, который представляет собой доработанный с учетом поддержки российской криптографии браузер Mozilla Firefox. Как известно, офисный пакет libreoffice в качестве хранилища сертификатов также использует хранилище NSS.

    Браузер Redfox-52 был установлен в папку /usr/local/lib64/firefox-52.

    Для подключения библиотек пакета NSS (Network Security Services) с поддержкой ГОСТ-алгоритмов устанавливаем значение переменной LD_LIBRARY_PATH следующим образом:

    $export LD_LIBRARY_PATH=/usr/local/lib64/firefox-52:$LD_LIBRARY_PATH
    $

    В качестве хранилища сертификатов в libreoffice как правило используется хранилище сертификатов из браузера Firefox, почтового клиента Thunderbird или интегрированного пакета Seamonkey. Ничто не мешает использовать хранилище сертификатов браузеров GoogleChrome/Cromium или создать свое независмое хранилище (Сервис->Параметры->Безопасность->Сертификат):



    После того как выбрано хранилище, подключены библиотеки, запускаем libreoffice, создаем файл формата odt и пытаемся его подписать (Файл->Цифровые подписи->Цифровые подписи).

    Сертификаты в хранилище Firefox/NSS успешно отображаются и проверяются:



    Однако, подпись после выбора сертификата и нажатия кнопки «ОК» не формируется:



    Похоже libreoffice не хочет понимать российские криптоалгоритмы, несмотря на то, что используется NSS из браузера Redfox, который понимает ГОСТ-овые алгоритмы, что подтверждается успешной проверкой сертификатов.

    Делаем вторую попытку: на этот раз попытаемся подписать PDF-файл. Для этого подготовленный документ экспортируем в PDF-формат. Для подписания PDF-файла его, естественно, необходимо загрузить (Файл->Цифровые подписи->Подписать PDF). После его загрузки пытаемся его подписать (Файл->Цифровые подписи->Цифровые подписи) (см.выше, выбираем сертификат, прописываем, например, цель подписания документа):



    И подпись формируется!!! Мы видим, что подпись, сформирования на базе сертификата «Test 12 512» с ключом ГОСТ Р 34.10-2012 512 бит. Подпись верна.

    Выходим из libreoffice. Снова запускаем libreoffice, загружаем подписанный pdf-файл, проверяем подписи. Все ОК. Просматривает сертификаты подписантов. Все ОК. Чудеса! Подпись PDF-файлов работает. Ставим вторую, третью подпись… Все работает. Но что-то не дает покоя. Делаем дополнительную проверку.

    Открываем подписанный PDF-файл (я использовал встроенный редактор от mc – Midnight Commander — консольный файловый менеджер для Linux). Находим электронную подпись (/Type/Sig/ ):



    Как видим, подпись хранится в символьном шестнадцатеричном виде. Копируем ее и сохраняем в файле. Для конвертации файла в бинарный вид (DER-кодировка) воспользуемся утилитой xxd:

    $xxd –p –r <файл с подписью из PDF>  > <файл>.der 
    $

    Полученный файл содержит отсоединенную подпись формата PKCS#7 в DER-кодировке. Теперь это подпись можно просмотреть любым asn1-prase-ом, например, утилитой openssl. Но поскольку мы говорим о пакете NSS, то воспользуемся утилитой derdump или утилитой pp:

    $pp –t p7 –u –i pkcs7_detach.p7
    PKCS #7 Content Info:
        PKCS #7 Signed Data:
            Version: 1 (0x1)
            Digest Algorithm List:
                Digest Algorithm (1): SHA-256
            Content Information:
                PKCS #7 Data:
                    <no content>
            Certificate List:
                Certificate (1):
                    Data:
                        Version: 3 (0x2)
                        Serial Number: 4107 (0x100b)
                        Signature Algorithm: GOST R 34.10-2012 signature with GOST R 34.11-2012-512
                        Issuer: "E=ca_12_512@lissi.ru,OGRN=1234567890123,INN=1234
                            56789012,CN=УЦ 12_512,O=УЦ 12_512,L=GnuPG ГОСТ
                            -2012-512,ST=Московская область,C=RU"
                        Validity:
                            Not Before: Sat Sep 08 07:17:56 2018
                            Not After : Tue Sep 12 07:17:56 2023
                        Subject: "C=RU,ST=Московская область,CN=Ф
                             И О,SN=Фам,givenName=И О,E=xx@xx.ru,L=Город
                            ,STREET=Улица,INN=123456789012,SNILS=12345678901"
                        Subject Public Key Info:
                            Public Key Algorithm: GOST R 34.10-2012 512 Public Key:
    .  .  .
                    Digest Encryption Algorithm: GOST R 34.10-2012 Key 512
                    Encrypted Digest:
                        34:9d:6f:37:e6:60:00:ed:fe:ef:f7:96:db:52:66:e1:
                        47:4c:5d:da:7f:9f:f3:20:50:ac:73:6c:97:db:f9:8d:
                        43:9b:8f:40:61:99:d3:4b:17:08:b8:34:e3:1e:92:76:
                        b1:0c:dd:37:01:1e:2a:30:45:68:06:af:3d:33:5e:2f:
                        71:c8:17:b3:a9:8a:6b:2f:78:9e:e4:b2:00:59:6f:5a:
                        a0:c5:9e:be:1e:4b:ca:d5:64:25:50:1a:6f:f9:55:b8:
                        3a:cf:37:a0:04:eb:89:b4:6c:39:77:27:92:de:61:c7:
                        b1:d3:a5:2f:ef:66:9b:f5:71:42:77:0a:d2:10:7f:50
    $

    И тут стало понятно, что не все так хорошо. Да, алгоритм подписи Digest Encryption Algorithm: GOST R 34.10-2012 Key 512 в соответствии с выбранным для подписи сертификатом, но подпись формируется от хэша, посчитанному по алгоритму SHA-256 (Digest Algorithm (1): SHA-256). А это неправильно с точки: хэш для GOST R 34.10-2012 Key 512 должен считаться по алгоритму ГОСТ Р 34.11-2012-512.

    Приступаем а анализу исходного кода libreoffice: не так страшен черт как его малюют. В данной статье мы рассматриваем использование пакета NSS для формирования электронной подписи. Если кто предпочитает на платформе MS Windows, использовать CryptoAPI (и, соответственно, ГОСТ-CSP), может по аналогии с данным материалом сделать соответствующую доработку.

    Анилиз показал, что правки придется внести всего в два файла:
    ~/libreoffice-5.3.7.2/vcl/source/gdi/pdfwriter_impl.cxx
    ~/libreoffice-5.3.7.2/xmlsecurity/source/pdfio/pdfdocument.cxx

    Эти изменения связаны с правильным выбором хэш-функции для ГОСТ-овых сертификатов. Выбор хэш-функции будем определять в зависимости от типа ключа сертификата. Выбор хэш-алгоритма, например, в PDFWriter::Sign (файл pdfwriter_impl.cxx) будет выглядеть так:

    bool PDFWriter::Sign(PDFSignContext& rContext)
    {
    #ifndef _WIN32
    /*Добавленные переменные*/
        SECKEYPublicKey *pubk = NULL;
        SECOidTag hashAlgTag;
        HASH_HashType hashType;
        int hashLen;
    
        CERTCertificate *cert = CERT_DecodeCertFromPackage(reinterpret_cast<char *>(rContext.m_pDerEncoded), rContext.m_nDerEncoded);
    
        if (!cert)
        {
            SAL_WARN("vcl.pdfwriter", "CERT_DecodeCertFromPackage failed");
            return false;
        }
    /*Получаем из сертификата открытый ключ*/
        pubk = CERT_ExtractPublicKey(cert);
        if (pubk == NULL)
    	return NULL;
    /*Проверяем тип открытого ключа*/
        switch(pubk->keyType){
    	case gost3410Key:
    	    hashAlgTag = SEC_OID_GOSTHASH;
    	    hashType = HASH_AlgGOSTHASH;
    	    hashLen = SHA256_LENGTH;
    	    break;
    	case gost3410Key_256:
    	    hashAlgTag = SEC_OID_GOST3411_2012_256;
    	    hashType = HASH_AlgGOSTHASH_12_256;
    	    hashLen = SHA256_LENGTH;
    	    break;
    	case gost3410Key_512:
    	    hashAlgTag = SEC_OID_GOST3411_2012_512;
    	    hashLen = SHA256_LENGTH * 2;
    	    hashType = HASH_AlgGOSTHASH_12_512;
    	    break;
    	default:
    	    hashAlgTag = SEC_OID_SHA256;
    	    hashType = HASH_AlgSHA256;
    	    hashLen = SHA256_LENGTH;
    	    break;
        }
    /*Вычисление хэш*/
        HashContextScope hc(HASH_Create(hashType));
    . .  .
    }

    Остальные изменения по логике аналогичны этим. Патч для файла ~/libreoffice-5.3.7.2/vcl/source/gdi/pdfwriter_impl.cxx находится

    здесь:
    --- pdfwriter_impl_ORIG.cxx	2017-10-25 17:25:39.000000000 +0300
    +++ pdfwriter_impl.cxx	2018-10-31 19:48:32.078482227 +0300
    @@ -6698,6 +6698,9 @@
                                     CERTCertificate *cert,
                                     SECItem *digest)
     {
    +    SECKEYPublicKey *pubk = NULL;
    +    SECOidTag hashAlgTag;
    +
         NSSCMSMessage *result = NSS_CMSMessage_Create(nullptr);
         if (!result)
         {
    @@ -6732,8 +6735,31 @@
             NSS_CMSMessage_Destroy(result);
             return nullptr;
         }
    -
    +    pubk = CERT_ExtractPublicKey(cert);
    +    if (pubk == NULL)
    +	return NULL;
    +    switch(pubk->keyType){
    +	case gost3410Key:
    +	    hashAlgTag = SEC_OID_GOSTHASH;
    +fprintf(stderr, "CreateCMSMessage: gost3410Key Use HASH_AlgGOSTHASH_=%d\n", hashAlgTag);
    +	    break;
    +	case gost3410Key_256:
    +	    hashAlgTag = SEC_OID_GOST3411_2012_256;
    +fprintf(stderr, "CreateCMSMessage: gost3410Key_256 Use HASH_AlgGOSTHASH_=%d\n", hashAlgTag);
    +	    break;
    +	case gost3410Key_512:
    +	    hashAlgTag = SEC_OID_GOST3411_2012_512;
    +fprintf(stderr, "CreateCMSMessage: gost3410Key_512  Use HASH_AlgGOSTHASH_=%d\n", hashAlgTag);
    +	    break;
    +	default:
    +	    hashAlgTag = SEC_OID_SHA256;
    +	    break;
    +    }
    +/*
         *cms_signer = NSS_CMSSignerInfo_Create(result, cert, SEC_OID_SHA256);
    +*/
    +    *cms_signer = NSS_CMSSignerInfo_Create(result, cert, hashAlgTag);
    +
         if (!*cms_signer)
         {
             SAL_WARN("vcl.pdfwriter", "NSS_CMSSignerInfo_Create failed");
    @@ -6773,8 +6799,8 @@
             NSS_CMSMessage_Destroy(result);
             return nullptr;
         }
    +    if (NSS_CMSSignedData_SetDigestValue(*cms_sd, hashAlgTag, digest) != SECSuccess)
     
    -    if (NSS_CMSSignedData_SetDigestValue(*cms_sd, SEC_OID_SHA256, digest) != SECSuccess)
         {
             SAL_WARN("vcl.pdfwriter", "NSS_CMSSignedData_SetDigestValue failed");
             NSS_CMSSignedData_Destroy(*cms_sd);
    @@ -6982,6 +7008,10 @@
     bool PDFWriter::Sign(PDFSignContext& rContext)
     {
     #ifndef _WIN32
    +    SECKEYPublicKey *pubk = NULL;
    +    SECOidTag hashAlgTag;
    +    HASH_HashType hashType;
    +    int hashLen;
     
         CERTCertificate *cert = CERT_DecodeCertFromPackage(reinterpret_cast<char *>(rContext.m_pDerEncoded), rContext.m_nDerEncoded);
     
    @@ -6990,8 +7020,33 @@
             SAL_WARN("vcl.pdfwriter", "CERT_DecodeCertFromPackage failed");
             return false;
         }
    +    pubk = CERT_ExtractPublicKey(cert);
    +    if (pubk == NULL)
    +	return NULL;
    +    switch(pubk->keyType){
    +	case gost3410Key:
    +	    hashAlgTag = SEC_OID_GOSTHASH;
    +	    hashType = HASH_AlgGOSTHASH;
    +	    hashLen = SHA256_LENGTH;
    +	    break;
    +	case gost3410Key_256:
    +	    hashAlgTag = SEC_OID_GOST3411_2012_256;
    +	    hashType = HASH_AlgGOSTHASH_12_256;
    +	    hashLen = SHA256_LENGTH;
    +	    break;
    +	case gost3410Key_512:
    +	    hashAlgTag = SEC_OID_GOST3411_2012_512;
    +	    hashLen = SHA256_LENGTH * 2;
    +	    hashType = HASH_AlgGOSTHASH_12_512;
    +	    break;
    +	default:
    +	    hashAlgTag = SEC_OID_SHA256;
    +	    hashType = HASH_AlgSHA256;
    +	    hashLen = SHA256_LENGTH;
    +	    break;
    +    }
    +    HashContextScope hc(HASH_Create(hashType));
     
    -    HashContextScope hc(HASH_Create(HASH_AlgSHA256));
         if (!hc.get())
         {
             SAL_WARN("vcl.pdfwriter", "HASH_Create failed");
    @@ -7005,15 +7060,18 @@
         HASH_Update(hc.get(), static_cast<const unsigned char*>(rContext.m_pByteRange2), rContext.m_nByteRange2);
     
         SECItem digest;
    -    unsigned char hash[SHA256_LENGTH];
    +    unsigned char hash[SHA256_LENGTH * 2];
    +
         digest.data = hash;
    -    HASH_End(hc.get(), digest.data, &digest.len, SHA256_LENGTH);
    +    HASH_End(hc.get(), digest.data, &digest.len, hashLen);
    +
         hc.clear();
     
     #ifdef DBG_UTIL
         {
             FILE *out = fopen("PDFWRITER.hash.data", "wb");
    -        fwrite(hash, SHA256_LENGTH, 1, out);
    +        fwrite(hash, hashLen, 1, out);
    +
             fclose(out);
         }
     #endif
    @@ -7078,8 +7136,8 @@
                 fclose(out);
             }
     #endif
    +        HashContextScope ts_hc(HASH_Create(hashType));
     
    -        HashContextScope ts_hc(HASH_Create(HASH_AlgSHA256));
             if (!ts_hc.get())
             {
                 SAL_WARN("vcl.pdfwriter", "HASH_Create failed");
    @@ -7090,16 +7148,19 @@
             HASH_Begin(ts_hc.get());
             HASH_Update(ts_hc.get(), ts_cms_signer->encDigest.data, ts_cms_signer->encDigest.len);
             SECItem ts_digest;
    -        unsigned char ts_hash[SHA256_LENGTH];
    +        unsigned char ts_hash[SHA256_LENGTH * 2];
    +
             ts_digest.type = siBuffer;
             ts_digest.data = ts_hash;
    -        HASH_End(ts_hc.get(), ts_digest.data, &ts_digest.len, SHA256_LENGTH);
    +        HASH_End(ts_hc.get(), ts_digest.data, &ts_digest.len, hashLen);
    +
             ts_hc.clear();
     
     #ifdef DBG_UTIL
             {
                 FILE *out = fopen("PDFWRITER.ts_hash.data", "wb");
    -            fwrite(ts_hash, SHA256_LENGTH, 1, out);
    +            fwrite(ts_hash, hashLen, 1, out);
    +
                 fclose(out);
             }
     #endif
    @@ -7111,7 +7172,8 @@
     
             src.messageImprint.hashAlgorithm.algorithm.data = nullptr;
             src.messageImprint.hashAlgorithm.parameters.data = nullptr;
    -        SECOID_SetAlgorithmID(nullptr, &src.messageImprint.hashAlgorithm, SEC_OID_SHA256, nullptr);
    +        SECOID_SetAlgorithmID(nullptr, &src.messageImprint.hashAlgorithm, hashAlgTag, nullptr);
    +
             src.messageImprint.hashedMessage = ts_digest;
     
             src.reqPolicy.type = siBuffer;
    @@ -7340,11 +7402,13 @@
         // Write ESSCertIDv2.hashAlgorithm.
         aCertID.hashAlgorithm.algorithm.data = nullptr;
         aCertID.hashAlgorithm.parameters.data = nullptr;
    -    SECOID_SetAlgorithmID(nullptr, &aCertID.hashAlgorithm, SEC_OID_SHA256, nullptr);
    +    SECOID_SetAlgorithmID(nullptr, &aCertID.hashAlgorithm, hashAlgTag, nullptr);
    +
         // Write ESSCertIDv2.certHash.
         SECItem aCertHashItem;
    -    unsigned char aCertHash[SHA256_LENGTH];
    -    HashContextScope aCertHashContext(HASH_Create(HASH_AlgSHA256));
    +    unsigned char aCertHash[SHA256_LENGTH*2];
    +    HashContextScope aCertHashContext(HASH_Create(hashType));
    +
         if (!aCertHashContext.get())
         {
             SAL_WARN("vcl.pdfwriter", "HASH_Create() failed");
    @@ -7354,7 +7418,8 @@
         HASH_Update(aCertHashContext.get(), reinterpret_cast<const unsigned char *>(rContext.m_pDerEncoded), rContext.m_nDerEncoded);
         aCertHashItem.type = siBuffer;
         aCertHashItem.data = aCertHash;
    -    HASH_End(aCertHashContext.get(), aCertHashItem.data, &aCertHashItem.len, SHA256_LENGTH);
    +    HASH_End(aCertHashContext.get(), aCertHashItem.data, &aCertHashItem.len, hashLen);
    +
         aCertID.certHash = aCertHashItem;
         // Write ESSCertIDv2.issuerSerial.
         IssuerSerial aSerial;


    Патч для файла ~/libreoffice-5.3.7.2/xmlsecurity/source/pdfio/pdfdocument.cxx находится

    здесь:
    --- pdfdocument_ORIG.cxx	2017-10-25 17:25:39.000000000 +0300
    +++ pdfdocument.cxx	2018-10-31 19:49:34.174485641 +0300
    @@ -2400,6 +2400,19 @@
         case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
             eOidTag = SEC_OID_SHA512;
             break;
    +    case SEC_OID_GOST3410_SIGN_256:
    +    case SEC_OID_GOST3411_2012_256:
    +        eOidTag = SEC_OID_GOST3411_2012_256;
    +	break;
    +    case SEC_OID_GOST3410_SIGN_512:
    +    case SEC_OID_GOST3411_2012_512:
    +        eOidTag = SEC_OID_GOST3411_2012_512;
    +	break;
    +    case SEC_OID_GOST3410_SIGNATURE:
    +    case SEC_OID_GOSTHASH:
    +        eOidTag = SEC_OID_GOSTHASH;
    +	break;
    +
         default:
             break;
         }
    @@ -2453,6 +2466,16 @@
         case SEC_OID_SHA512:
             nMaxResultLen = msfilter::SHA512_HASH_LENGTH;
             break;
    +    case SEC_OID_GOST3411_2012_256:
    +        nMaxResultLen = msfilter::SHA256_HASH_LENGTH;
    +	break;
    +    case SEC_OID_GOST3411_2012_512:
    +        nMaxResultLen = msfilter::SHA512_HASH_LENGTH;
    +	break;
    +    case SEC_OID_GOSTHASH:
    +        nMaxResultLen = msfilter::SHA256_HASH_LENGTH;
    +	break;
    +
         default:
             SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: unrecognized algorithm");
             return false;


    После внесения изменений проводим сборку пакета libreoffice. Внесенные изменения коснулись трех библиотек (/usr/lib64/libreoffice/program):

    • libvcllo.so;
    • libxmlsecurity.so;
    • libxsec-xmlsec.so

    Именно эти три библиотеки были заменены в установленном дистрибутиве libreoffice (/usr/lib64/libreoffice/program).

    После этого подписание и проверка ГОСТ-подписи в PDF-файлах прошла без сучка и задоринки. И тут на одном из сайтов попадается на глаза такая выдержка:
    У Федеральной налоговой службы есть отличный сервис для получения выписки из ЕГРЮЛ для любого юридического лица, причем абсолютно бесплатно. Выписку можно получить в виде документа формата PDF, подписанном квалифицированной электронной подписью. И такую выписку можно отправить в коммерческий банк, госучреждение, и с вас не попросят ее в бумажном виде. В общем, очень удобно.
    Заказываем, получаем и проверяем:



    Стоит напомнить, что не следует забывать устанавливать в хранилище цепочку доверенных сертификатов для сертификата подписанта. Но это естественно.

    Все, теперь есть возможность использования электронной подписи (одной или несколько) в PDF-файлах. Это очень удобно как при согласовании документов, так и хранении документов.

    А если кто привык работать с классической электронной подписью в формате PKCS#7 как присоединенной, так и отсоединенной, то для них подготовлена обновленная версия (для платформы Linux и Windows) графического пакета GUINSSPY:



    Разработка велась на Python3 и если на платформе Linux проблем не было, то на MS Windows пришлось попотеть с кодировками. Фактически это была отдельная разработка и это требует отдельной статьи. Все эти нюансы можно увидеть в исходном коде.

    С помощью этой утилиты можно создать хранилище сертификатов для libreoffice, управлять сертификатами, подписывать файлы и т.д.:



    Утилита также позволяет создать запрос на сертификат с генерацией ключевой пары, который затем можно передать в удостоверяющий центр, а полученный сертификат установить в хранилище:



    И вот если производители отечественных форков Linux доработали различные пакеты (NSS, Firefox, Thunderbiird, GnuPG/SMIME, SSH, KMail, Kleopatra, LibreOffice, OpenSSL, и т.д и т.п.) для работы с российской криптографией, то тогда можно было бы говорить об импортозамещении в области криптографии.
    Поделиться публикацией

    Похожие публикации

    Комментарии 51
      +3
      Любопытно, упомянутый сайт soft.lissi.ru принципиально не использует HTTPS? Чтобы, например, проще было подменить ответ сервера при скачивании софта и прочего?
        +3

        Нет, конечно, никакого принципа нет. HTTPS на ГОСТ защищает УЦ.
        Вы думаете есть желающие подменить? Надо будет сказать, чтобы все же подключили https.

          +2
          Вряд ли такая гора желающих, просто выглядит странно — сайт по вопросам безопасности и всего такого, на чистом HTTP.
            –2

            Дело еше в том, если закрыть сайт HTTPS-ом, но ГОСТ-овым, то нанего мало кто попадет (понятно почему). А защищать сайт не ГОСТ-овым https, как-то некрасиво — проповедуете ГОСТ, а тут… Хотя все наши государственные сайты/порталы в своем большинстве, даже tk26, защищены не ГОСТ-ом:



            Я думаю этот недочет устраним.

              +3
              Полагаю, что если выбор стоит между «вообще не защищать передачу от перехвата» и «использовать HTTPS, поддерживаемый самыми используемыми браузерами», ответ скорее в пользу второго.

              Тем более, что те же госуслуги используют международно принятый HTTPS (сертификат от COMODO CA Limited).
                +1

                Так-то оно так! COMODO хорошо. Но те же Госуслуги и ФНС выдают услуги по ГОСТ-сертификату. Получаются двойные стандарты.
                Может проще перейти на международно принятую криптографию?
                Вообще-то это нонсенс получать SSL-сертификат для ГОСУСЛУГ России где-то на Западе!

                  +1
                  Согласен. Или уж тогда разрешать только браузеры, понимающие криптографию по ГОСТу, или использовать международные стандарты.
                +1
                Это не та ситуация, когда нужно делать выбор между крестиком или трусами )
        +3
        И вот если производители отечественных форков Linux доработали различные пакеты


        А Вы не хотели бы внести указанные правки в LibreOffice самостоятельно? Достаточно отправить Code Contributor Statement, и разместить патч в геррит.
          +4

          А разве я несамостоятельно разбираюсь в коде LibreOffice или GnuPG и предлагаю правки?
          А чтоже делают наши производители "отечественных форков Linux" кроме капипаста? Сколько раз я им предлагал просто исправить ошибки (причем самые простые ), а в ответ ...


          А за наводку Спасибо.

            +2
            Насколько я знаю, предлагать правки в своём блоге или по почте чаще всего бессмысленно (хотя у некоторых проектов есть политика приёма патчей по почте). У проектов обычно есть своя политика приёма правок, и у многих это именно размещение патча в системе peer review. Поэтому как бы ни были хороши намерения, если не следовать установленным в проекте правилам, все полезные предложения могут оказаться потерянными в непредназначенном для этого канале.
              0

              Конечно вы правы. Но прояснить откуда и зачем появляются эти правки все же надо.
              Да, а сами патчи отправить по назначению.

                +5
                Конкретно в случае ЛО практика такова:

                1. Создаётся багрепорт с описанием проблемы на английском языке («не работает подписание с использованием алгоритма такого-то; шаги для воспроизведения: 1, 2, 3...»).
                2. Отправляется патч в геррит, commit message которого в первой строке имеет тег tdf#XXXX, где XXXX — номер багрепорта. Ну, и конечно, commit message будет содержать достаточный объём информации (при необходимости — хоть «войну и мир»).

                Это позволяет привязать патч к объяснению «откуда и зачем», расширить обсуждение при необходимости (в баге или в геррите), и сохранить это обсуждение для «последующих поколений», которым понадобится контекст при будущих правках. Никакие нестандартные каналы не могут обеспечить такой преемственности.
                  0

                  Огромное спасибо. Беру на проработку.

            0
            Не примут. В хедерах, которыми пользуется весь остальной мир, нету деклараций ГОСТовых констант, которые использует автор.
              0

              Вообще у нас есть ТК-26, который выпускает рекомендации по хедерам, в частности по PKCS#11 v.2.40. И я так понимаю он должен заботиться о признание наших алгоритмов и хеверов в мировом сообществе. Но, к сожалению, это пока удалось сделать только для ГОСТ З 34.10-2001, а он у нас уже вроде бы как и отменен.

                +1
                Не признают их, они все верещат про attack surface и, вероятно, есть поводы сомневаться. По крайней мере ТК-26 ничего не делает для того, чтобы эти сомнения развеять.
                  +1

                  Раз ничего не делается, то и приходится крутиться как-то так. Спасибо.

                  +1
                  ГОСТ З 34.10-2001, а он у нас уже вроде бы как и отменен.

                  Не отменён, снова продлили действие на год: «Уведомление об организации перехода на использование схемы электронной подписи по ГОСТ Р 34.10-2012...».

                    0

                    У нас всегда так. Если бы вы знали сколько сил и средств (в прямом смысле) было затрачено на этот переход! И бам, мы пошутили в угоду кому-то.

                      0
                      Лично мы сделали аж две независимые реализации Стрибога в январе 2013-го, обнаружив после новогодних каникул факт принятия стандартов. Вот с 34.10 хуже — пришлось ждать OIDы от Крипто-Про и ТК26 (и параметры кривой для 512).
                        0

                        Тягаться я думаю не стоит. Мы сделали базовую библиотеку в далеком 2012 году, называлась она LCC2012. По мере уточнения в ТК-26 она развивалась и стала LCC2016. Я не понимаю что такое ждать от КриптоПро! Мы говорим о Гусударственных Стандартов и опираться можно и нужно только на них и разъяснения/рекомендации уполномоченных органов, а это ФСБ России и ТК-26. Я не знаю, может КриптоПро это структура ФСБ, но вряд ли. Мне ничего не известно.
                        А что случилось после Новогодних каникул?

                          0
                          Тягаться я думаю не стоит.

                          Суть замечания была не в этом, а в том, что с точки зрения разработки сил то не много нужно было.


                          А вот теперь, посмотрев на ссылку под статьёй и в комментарии я по-другому перечитал комментируемый комментарий («сил и средств»).


                          У нас не было задачи сертифицировать СКЗИ, у нас МЭ и работы, основанные на нём, где было прописано только «использование российской криптографии». Понадобилась поддержка новых алгоритмов — реализовали быстро.


                          P.S. Посмотрел историю: ТК26 OIDы для 34.11-2012 у нас добавлены через неделю после собственно 34.11-2012 в один день с добавлением 34.10-2012, а вот 34.10-2012-512 парамсеты от ТК26 на пару месяцев позже.


                          UPD: А вот и проект рекомендации ТК26 по данному вопросу — первая редакция от апреля 2014-го… Вот такие документы, по-моему, должны выпускаться одновременно с принятием нового стандарта, пакетом.

                            0
                            такие документы, по-моему, должны выпускаться одновременно с принятием нового стандарта, пакетом.

                            Конечно должны в один день и без ошибок или опечаток или двоякого толкования. А то после опубликования ох как долго все притирается.

              0
              Последние скриншоты показывают проблемы со шрифтами. Во-первых, зачем шрифт с серифами (засечками) в интерфейсе? Серифы обычно используются на текстах для чтения, а не в навигации.

              Второе: почему такое количество шрифтов? Разве один шрифт в разных начертаниях не был бы лучше?

              … Всё даже страшнее, чем я думал. Одни и те же элементы управления могут показывать как штрифты с засечками, так и без. (кнопки «Отмена» и «завершаем», например).
                +1

                Почему страшнее?


                Несколько десятков лет в научных и типографических кругах не утихают споры, на первый взгляд, по незначительному вопросу: является ли шрифт с засечками более разборчивым, а шрифт без засечек, соответственно, менее четким для восприятия?
                По сей день никто не предоставил окончательного неоспоримого ответа на этот вопрос.

                Еще вопрос


                Второе: почему такое количество шрифтов?

                Только в учебных целях — показать как управлять шрифтами.


                Разве один шрифт в разных начертаниях не был бы лучше?

                Может и так, дело вкуса. Если вы запустили утилиту guinsspy (интересно на какой платформе windows или linux), значит вы получили и доступ к исходному коду утилиты и вам не составит труда выбрать шрифты по вашему вкусу. Спасибо.

                  –2
                  Только в учебных целях — показать как управлять шрифтами.
                  А кому именно тут показывается, как управлять шрифтами?
                +1
                Интересно, что вы делаете switch по keyType и ваши правки не содержат деклараций gost3410Key сотоварищи. Значит эти декларации доступны в существующих хедерах? А для чего они там, если libnss из коробки не поддерживает ГОСТ? Вопрос из праздного любопытства.
                  0

                  Почему из праздного любопытства? Вопрос по существу и в лоб. Конечно nss из коробки, к сожалению,, не поддерживает ГОСТ-ы, но сегодня уже поддерживает EC, а это уже близко к ГОСТ-у. Где взять библиотеки nss с ГОСТ-ами в статье указано (скачать Redfox). Более того, они включены также в дистрибутив утилиты guinsspy для платформы Windows (вместе с утилитами). А хэдеры могу выложить или прислать:
                  /Файл ~/lib/cryptohi/keythi.h/


                  ...
                  typedef enum {
                      nullKey = 0,
                      rsaKey = 1,
                      dsaKey = 2,
                      fortezzaKey = 3, /* deprecated */
                      dhKey = 4,
                      keaKey = 5, /* deprecated */
                      ecKey = 6,
                      rsaPssKey = 7,
                      rsaOaepKey = 8,
                  /*ГОСТ Р 34.10-2001*/
                      gost3410Key = 9,
                  /*ГОСТ Р 34.10-2012-256*/
                      gost3410Key_256 = 10,
                  /*ГОСТ Р 34.10-2012-256*/
                      gost3410Key_512 = 11
                  } KeyType;
                  ...
                    0
                    Тогда советы ораторов выше о том, что этот патч вам надо заслать в LO, не применимы — ведь у разрабов LO нету этих деклараций в их хедерах.

                    Интересно ещё вот что спросить. Почему, например, декларации для rsa никак не зависят от длины ключа, а ГОСТ отхватывает сразу три позиции в енуме?
                      0

                      Как же RSA не зависит от длины, еще как:



                      "ГОСТ отхватывает сразу три позиции в енуме
                      " в силу того, что используются разные механизмы (для PKCS#11 это CKM_GOSTR3410_KEY_PAIR_GEN для алгоритма ГОСТ Р 34.10-2001 и CKM_GOSTR3410_KEY_512_PAIR_GEN для алгоритма ГОСТ Р 34.10-2012).
                      А ключи ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2012-256 байт используют один и тот же алгоритм, но у них разные параметры (curve).
                      И вот чтобы было попроще разбираться в этих ГОСТ-овых хитросплетениях и введены три позиции. Где-то так

                        0
                        Я не утверждал что rsa не зависит от длины. Я как раз утверждал обратное, что тот факт, что rsa бывает разных длин, никак не находит отражение в енуме.
                          0

                          Естественно, алгоритм-то один и тот же.

                          +1
                          А ключи ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2012-256 байт используют один и тот же алгоритм, но у них разные параметры (curve).

                          Они могут использовать одинаковые параметры эллиптики и, de facto, используют одинаковые параметры эллиптики: достаточно посмотреть в текст соответствующих стандартов — там даже примеры абсолютно совпадают. И используемые на практике параметры от Крипто-Про также идентичны, см. RFC 7836, п. 5.1:


                          In case of elliptic curves with 256-bit prime moduli, the parameters defined in [RFC4357] are proposed for use.

                          Что у них разное, дак это алгоритм хеша.

                            0

                            Спасибо, конечно я не прав:


                            А ключи ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2012-256 байт используют один и тот же алгоритм, но у них разные параметры (curve).

                            Даже сам удивляюсь куда занесло! Конечно один и тот же. Поэтому и аппаратная поддержка быстро появилась в отличии от ГОСТ Р 34.10-2012-512


                            А отличаются хэшами.
                            БОЛЬШОЕ СПАСИБО!

                          0

                          Даже более, скорее всего, ни одна из этих новых констант не нужна: если ecKey это то, что используется для ECDSA, то там всё уже есть — параметры кривых можно задавать в том же формате, поле для параметризации по алгоритму хеширования тоже должно быть.


                          Но, в то же время, ECDSA, ECKDSA и ECGOST (и ещё какой-то европейский стандартный алгоритм) хоть и используют одинаковую математику на эллиптических кривых, но процедуры вычисления и проверки подписи у них разные.


                          UPD: «Какой-то европейский», скорее всего, ECGDSA от Siemens.

                            0

                            А взгляните повнимательней на константы и вы увидите целых три константы для RSA, например:
                            rsaKey = 1,
                            rsaPssKey = 7,
                            rsaOaepKey = 8,

                              0

                              Да, тут для разных схем выделили по идентификатору. Только вот конкретно в нашем случае у нас схема одна и та же (мы говорим про 34.10).


                              Более того, описываемое решение некорректно: тот же алгоритм хеширования задан в параметрах алгоритма подписи в SubjectPublicKeyInfo и должен быть прочитан и содержаться внутри SECKEYPublicKey к моменту возврата из CERT_ExtractPublicKey.


                              Кроме него есть и параметры эллиптической кривой (минимум пять больших чисел), в случае 34.11-94 ещё и S-Box, а для любого хеша, вообще говоря, можно ещё и альтернативный IV задавать.


                              И мы никак это не запихаем в идентификаторы перечисления.


                              Вот для ECDSA, ECKDSA, ECGOST и ECGDSA можно и имеет смысл выделить по отдельному идентификатору (имя KeyType тут прямо об этом и просит).


                              Так что, думаю, нужно сначала научить CERT_ExtractPublicKey проверять параметры ключа, как минимум, определять функцию хеширования. Заменить жёстко прописанное использование SHA2 так, как это делается здесь. А потом добавить уже поддержку ГОСТовых алгоритмов в CERT_ExtractPublicKey.


                              P.S. А ещё PKIX не мешает нам использовать 34.11 с ECDSA и SHA-* с ECGOST. Да, ни одна из таких схем не пройдёт сертификацию ни FIPS, ни ФСБ на СКЗИ, но подавляющему большинству такая сертификация и не нужна.

                                +1
                                Заменить жёстко прописанное использование SHA2

                                Это где надо заменить? В NSS такого нет, там алгоритм задается. Если говорить про LibreOffice, то здесь это и предлагается.
                                То что гостовую подпись можно получить от любого хэша — понятно. С этого и началась статья. Но в ГОСТ-ах у нас прописан другая схема получения подписи.
                                Поддержка ГОСТ-ов в CERT_ExtractPublicKey естественно есть с полным разбором ключей. Иначе бы ничего не работало!

                                  0
                                  Поддержка ГОСТ-ов в CERT_ExtractPublicKey естественно есть с полным разбором ключей. Иначе бы ничего не работало!

                                  Тогда зачем мы вычисляем хаком тип хеш-функции вместо получения его непосредственно из параметра ключа, где он есть (явно или не явно)?


                                  Я про switch(pubk->keyType) для вычисления hashType (и прочих параметров) — вот последний и нужно извлекать непосредственно из pubk, а не гадать.


                                  То что гостовую подпись можно получить от любого хэша — понятно. С этого и началась статья.

                                  Эм, нет, там всё хуже:


                                               Digest Algorithm (1): SHA-256
                                                      Signature Algorithm: GOST R 34.10-2012 signature with GOST R 34.11-2012-512

                                  — Это не ECGOST + SHA2, а диназавробегемот — в одном месте SHA2, в другом необрезанный Стрибог.


                                  UPD: Если извлекать алгоритм хеша из pubk, то у нас и ECDSA+SHA3 заработает в LibreOffice, и ECKDSA с ECGDSA, если (или когда) они будут реализованы в NSS.

                                    0

                                    Так все и посвящено тому, чтобы "диназавробегемот" превратился в прекрасного принца:


                                    PKCS #7 Content Info:
                                        PKCS #7 Signed Data:
                                            Version: 1 (0x1)
                                            Digest Algorithm List:
                                               Digest Algorithm (1): GOST R 34.11-2012 512
                                            Content Information:
                                    . . .
                                                   Digest Encryption Algorithm: GOST R 34.10-2012 Key 512
                                                    Encrypted Digest:
                                                        5e:d8:eb:a9:81:43:45:f4:81:c3:af:5f:74:b8:92:64:
                                                        e0:7c:02:b7:1a:09:e5:af:a5:dc:bd:d9:6f:e2:f3:d9:
                                                        e8:8e:df:67:d3:4a:f6:f6:b1:37:b4:31:6c:ee:69:53:
                                                        ba:79:dc:e5:c1:d3:2b:7d:7b:23:51:43:4d:ee:c4:8d:
                                                        d9:a8:f7:bf:7f:68:7d:c1:a4:06:80:32:9e:66:80:5e:
                                                        f2:3f:8d:9a:7a:3f:b1:75:1d:61:a2:2b:f0:b8:bd:0d:
                                                        51:4e:d2:7c:c0:e5:1f:06:1d:b9:b2:0f:16:e1:09:aa:
                                                        24:79:36:74:79:34:44:be:f4:58:39:87:7b:b4:e1:c7
                                      0
                                      Я про switch(pubk->keyType) для вычисления hashType (и прочих параметров) — вот последний и нужно извлекать непосредственно из pubk, а не гадать.

                                      Ника не могу понять — где в операторе switch(pubk->keyType) гадание?
                                      Извлекаем тип ключа, а значит и тип хэша! Что за гадание и где? Или вы предлагаете написать новый NSS по вашим рассуждениям? Можно, попробуйте.

                        0

                        А как собирались дистрибутивы утилиты guinss?

                          0

                          Утилита писалась на python3. Для получения полностью независимого дистрибутива и на платформе Windows и на Linux для сборки дистрибутива использовался пакет pyinstaller:


                          $pyinstaller --noconsole -F guinsspy.py
                            0
                            А GUI это действительно Motif или стилизация под него?
                            А то аж на ностальгическую слезу прошибло при виде такого интерфейса.
                              0

                              Цель достигнута — я тоже порой ностальгирую. GUI написан на Tkinter, т.е. на Tk. Отсюда (при использовании настроек по умолчанию ) и ощущения Motif.

                          +2
                          > /usr/lical

                          Чем-то напомнило:

                          ains mein(inт argc char** argv)
                          {
                              kaut << "hilo word";
                              eksit(0;
                          ]


                            +1

                            Вы правы. Спавибо, поправил.

                              +1
                              Наверное вы имели ввиду
                              СПАСИБО!
                                0

                                Конечно, СПАСИБО!!!

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое