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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Павел Богатырёв  
#1 Оставлено : 10 июня 2021 г. 14:27:58(UTC)
Павел Богатырёв

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

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

Добрый день, возникает проблема при проверки подписи именно в 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'. Вот подробный лог:



Проверку вызываем следующим образом:

Код:

   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)  | Причина: Не указана

Offline Санчир Момолдаев  
#2 Оставлено : 12 июня 2021 г. 0:35:40(UTC)
Санчир Момолдаев

Статус: Сотрудник

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

Сказал(а) «Спасибо»: 88 раз
Поблагодарили: 223 раз в 211 постах
Добрый день!
как мне кажется вы в JS не правильно считаете длину для короткого имени.
см msdn
в конце есть ссылка на объяснение TLV
как мне кажется эта строка лишняя
Код:
128 + 1, // length помещается в один байт


т.е. если смотреть в HEX то у вас:
0c 81 09
должно быть
0с 09

81 (hex) это 128+1 (dec)


для анализа нужны несколько подписей:
1. файл подписи "по старинке"
2. файл подписи с коротким именем с учетом вышеуказанных измений
3. файл подписи с длинным именем

плюс укажите используемую версию jcp
Техническую поддержку оказываем тут
Наша база знаний
Offline Павел Богатырёв  
#3 Оставлено : 22 июня 2021 г. 11:08:21(UTC)
Павел Богатырёв

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

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

Согласен, что строчка лишняя, убрали. Версия JCP jcp-2.0.41987-A

SignaturesFillesCertificate 22.06.2021.zip (25kb) загружен 1 раз(а).
Offline Санчир Момолдаев  
#4 Оставлено : 24 июня 2021 г. 0:54:28(UTC)
Санчир Момолдаев

Статус: Сотрудник

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

Сказал(а) «Спасибо»: 88 раз
Поблагодарили: 223 раз в 211 постах
Автор: Павел Богатырёв Перейти к цитате
Согласен, что строчка лишняя, убрали. Версия JCP jcp-2.0.41987-A

SignaturesFillesCertificate 22.06.2021.zip (25kb) загружен 1 раз(а).


Да, теперь проверяется короткая как и старая. а вот длинной подписи в архиве нет
Техническую поддержку оказываем тут
Наша база знаний
Offline Павел Богатырёв  
#5 Оставлено : 24 июня 2021 г. 8:04:15(UTC)
Павел Богатырёв

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

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

Там длина имени меньше 255, но из-за русских символов длина строки большая:

LongName.zip (3kb) загружен 1 раз(а).

Screenshot_1.jpg (68kb) загружен 7 раз(а).
Offline Санчир Момолдаев  
#6 Оставлено : 24 июня 2021 г. 9:18:12(UTC)
Санчир Момолдаев

Статус: Сотрудник

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

Сказал(а) «Спасибо»: 88 раз
Поблагодарили: 223 раз в 211 постах
в java подпись проверку прошла.
в следующий раз старайтесь избегать длинных имен файлов в пути. их с наскоку не разархивировать
Техническую поддержку оказываем тут
Наша база знаний
Offline Павел Богатырёв  
#7 Оставлено : 6 августа 2021 г. 13:50:10(UTC)
Павел Богатырёв

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

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

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