| 
	Статус: Участник
 Группы: Участники
 Зарегистрирован: 10.06.2021(UTC) Сообщений: 16  Откуда: Орел | 
            
		      
                Добрый день, возникает проблема при проверки подписи именно в java-среде, в .NET все хорошо. Ошибка появляется, если в подпись, создаваемую через браузерный плагин, добавляется атрибут со значением в виде длинной строки (больше 255 байт). Для обработки таких строк при создании подписи в браузере мы сделали следующий код: Код:
function getBstrBase64(str: string) {
    let utf8 = toUTF8Array(str);
    let bstrUnit8Array: Uint8Array;
    // Если длина строки помещается в один байт
    if (utf8.length <= 255) {
        bstrUnit8Array = new Uint8Array([
            0x0C, 
            128 + 1, // length помещается в один байт
            utf8.length,
            ...utf8
        ]);        
    } else {
        bstrUnit8Array = new Uint8Array([
            0x0C, 
            128 + 2, // length помещается в два байта
            utf8.length >> 8, // первый байт length
            utf8.length & 0xFF, // второй байт length
            ...utf8
        ]);
    }
    return Base64.fromUint8Array(bstrUnit8Array);
}
function toUTF8Array(str: string) {
    let utf8 = [];
    for (let i = 0; i < str.length; i++) {
        let charcode = str.charCodeAt(i);
        if (charcode < 0x80) utf8.push(charcode);
        else if (charcode < 0x800) {
            utf8.push(0xc0 | (charcode >> 6),
                      0x80 | (charcode & 0x3f));
        } else if (charcode < 0xd800 || charcode >= 0xe000) {
            utf8.push(0xe0 | (charcode >> 12),
                      0x80 | ((charcode >> 6) & 0x3f),
                      0x80 | (charcode & 0x3f));
        } else { // surrogate pair
            i++;
            // UTF-16 encodes 0x10000-0x10FFFF by
            // subtracting 0x10000 and splitting the
            // 20 bits of 0x0-0xFFFFF into two halves
            charcode = 0x10000 + (((charcode & 0x3ff) << 10)
                      | (str.charCodeAt(i) & 0x3ff));
            utf8.push(0xf0 | (charcode >> 18),
                      0x80 | ((charcode >> 12) & 0x3f),
                      0x80 | ((charcode >> 6) & 0x3f),
                      0x80 | (charcode & 0x3f));
        }
    }
    return utf8;
}
 Раньше у нас был следующий код (адаптирован из https://www.cryptopro.ru...px?g=posts&t=13809),  с ним проблем не возникало: Код:
function getBstrBase64(str: string) {
    // Размер русских символов = символ * 2.
    let RussiansSymbolsLength = 0;
    let RussiansSymbols = str.match(/[А-яЁё]/g);
    if (RussiansSymbols !== null)
        RussiansSymbolsLength = RussiansSymbols.length;
    let bstr = String.fromCharCode(0x0C) + String.fromCharCode(str.length + RussiansSymbolsLength) + str;
    return Base64.encode(bstr);
}
 Значение атрибута потом добавляется так: Код:
info.Attributes.push(new EncryptedAttribute(this.DocumentNameOIDAttribute, getBstrBase64(fileInfo.fileName)));
// ...
Crypto.SignData(info, dataToSign, signType, tspService);
 То есть, пока мы использовали краткий формат BSTR, который допускает строки длиной меньше 255 байт все было хорошо. При переключении на длинный формат - в java-сервисе возникает ошибка Signature is invalid; error codes: [8] 'Signature is invalid'. Вот подробный лог:
 
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 a
 FINE: Draining the signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 a
 FINE: Extracting certificates from signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 a
 FINE: Extracting CRLs from signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 a
 FINE: Decoding signers of signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: %%% Decoding signature... %%%
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: Collecting signers...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.CAdESSignerFactory a
 FINE: New signer with type:  CAdES-X Long Type 1
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: Setting certificates ands CRL for archive-timestamp if need in future...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.CAdESSignerBESImpl b
 FINE: Decoding CAdES-BES signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.CAdESSignerPKCS7Impl b
 FINE: Decoding PKCS7 signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 decode
 FINE: Decoding CAdES-X Long Type 1 structures...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_5 decode
 FINE: Decoding CAdES-T structure...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_0 decode
 FINE: Decoding base signer structure...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_3 a
 FINE: Extracting signer certificate reference...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_3 a
 FINE: Extracting certificate reference...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_3 a
 FINE: Extract certificate reference by using current standard V2.
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_0 b
 FINE: Extracting existing certificate-values...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_5 b
 FINE: Extracting timestamps...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 b
 FINE: Extracting complete-certificate-references...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 e
 FINE: Extracting complete-revocation-references...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 f
 FINE: Extracting certificate-values...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 g
 FINE: Extracting revocation-values...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_5 b
 FINE: Extracting timestamps...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: %%% Signature has been decoded %%%
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 a
 FINE: Extracting certificates from signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 a
 FINE: Extracting CRLs from signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 a
 FINE: Decoding signers of signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: %%% Decoding signature... %%%
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: Collecting signers...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.CAdESSignerFactory a
 FINE: New signer with type:  Enhanced signature timestamp (internal)
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: Setting decoded content for timestamp...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.CAdESSigner a
 FINE: Extracting timestamp generation date...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: Setting buffered signed content
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: Setting certificates ands CRL for archive-timestamp if need in future...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.CAdESSignerBESImpl b
 FINE: Decoding CAdES-BES signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.CAdESSignerPKCS7Impl b
 FINE: Decoding PKCS7 signature...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 decode
 FINE: Decoding CAdES-X Long Type 1 structures...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_5 decode
 FINE: Decoding CAdES-T structure...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_0 decode
 FINE: Decoding base signer structure...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_3 a
 FINE: Extracting signer certificate reference...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_3 a
 FINE: Extracting certificate reference...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_3 a
 FINE: Extract certificate reference by using current standard V2.
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_0 b
 FINE: Extracting existing certificate-values...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_5 b
 FINE: Extracting timestamps...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 b
 FINE: Extracting complete-certificate-references...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 e
 FINE: Extracting complete-revocation-references...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 f
 FINE: Extracting certificate-values...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_7 g
 FINE: Extracting revocation-values...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.pc_0.pc_0.cl_5 b
 FINE: Extracting timestamps...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 decode
 FINE: %%% Signature has been decoded %%%
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 verify
 FINE: %%% Verifying signature... %%%
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.cl_1 verify
 FINE: Verifying signers, total: 1...
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.CAdESSignerXLT1Impl a
 FINE: %%% Verifying signer... %%%
 θών. 10, 2021 9:40:07 AM ru.CryptoPro.CAdES.CAdESSignerXLT1Impl a
 FINE: Verifying binary signature...
 Signature is invalid; error codes: [8] 'Signature is invalid',
 at ru.CryptoPro.CAdES.CAdESSignerRawImpl.verifyCryptographicSignature(Unknown Source)
 at ru.CryptoPro.CAdES.CAdESSignerXLT1Impl.a(Unknown Source)
 at ru.CryptoPro.CAdES.CAdESSignerXLT1Impl.verify(Unknown Source)
 at ru.CryptoPro.CAdES.cl_1.verify(Unknown Source)
 at ru.CryptoPro.CAdES.cl_1.verify(Unknown Source)
 at methods.SignatureInfoMethods.getTimestamps(SignatureInfoMethods.java:108)
 at methods.SignatureInfoMethods.getSignatureInfo(SignatureInfoMethods.java:42)
 at Crypto.TestFrame$14.actionPerformed(TestFrame.java:192)
 at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1967)
 at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2308)
 at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
 at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
 at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
 at java.desktop/java.awt.Component.processMouseEvent(Component.java:6635)
 at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
 at java.desktop/java.awt.Component.processEvent(Component.java:6400)
 at java.desktop/java.awt.Container.processEvent(Container.java:2263)
 at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5011)
 at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
 at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
 at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4918)
 at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4547)
 at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4488)
 at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2307)
 at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2772)
 at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
 at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
 at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
 at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
 at java.base/java.security.AccessController.doPrivileged(Native Method)
 at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
 at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
 at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
 at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
 at java.base/java.security.AccessController.doPrivileged(Native Method)
 at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
 at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
 at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
 at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
 at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
 at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
 at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
 at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
 
 
 Проверку вызываем следующим образом: Код:
   CAdESSignature signature = getCAdESSignature();
   signature.verify(null);
   ...
 В том что значение атрибута сформировано корректно убеждаемся на сайте https://lapo.it/asn1js,  если загрузить туда файл подписи, то видим значение атрибута (1.3.6.1.4.1.311.88.2.1). То есть, этот сайт успешно парсит нашу asn1 структуру, ошибок не выдает: Код:
            SEQUENCE (2 elem)
              OBJECT IDENTIFIER 1.3.6.1.4.1.311.88.2.1 capiComDocumentName (Microsoft attribute)
              SET (1 elem)
                UTF8String test.docx
 В .NET среде проверка у нас вызывается таким кодом, проходит успешно: Код:
            var signedData = new CadesSignedData();
            signedData.ContentEncoding = CADESCOM_CONTENT_ENCODING_TYPE.CADESCOM_BASE64_TO_BINARY;
            var signatureString = Convert.ToBase64String(signature);
            signedData.Content = Convert.ToBase64String(data.DataBytes);
            signedData.VerifyCades(signatureString, DigitalSignatureKindToCadesType(signatureKind), true);
 Файл, подпись и сертификат прикладываю (подпись detached)  Подскажите, в чем может быть дело?   fajjl,  podpis', sertifikat.zip (14kb) загружен 1 раз(а). Отредактировано пользователем 10 июня 2021 г. 14:33:42(UTC)
 | Причина: Не указана |