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

Уведомление

Icon
Error

2 Страницы<12
Опции
К последнему сообщению К первому непрочитанному
Offline Евгений Афанасьев  
#11 Оставлено : 7 июня 2021 г. 14:05:39(UTC)
Евгений Афанасьев

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

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Автор: Скобелев Дмитрий Перейти к цитате

можно ли отключить проверку/использование списка просроченных сертификатов?

В случае cades-подписи - нет. Так или иначе, цепочка сертификатов должна быть проверена. Вы, в принципе, можете оставить включенными параметры enableCRLDP: если есть доступ в сеть, то CRL будут скачаны, иначе - нет.
Автор: Скобелев Дмитрий Перейти к цитате

Пока не нашли ответа на начальный вопрос в ветке - как правильно подписать хэш https://docs.cryptopro.r...-samples-cades-sign-hash для андроид версии.

hashAlg в signHashData не надо перекодировать из base64, он уже перекодирован? Если хеш вычислен вами по данным с помощью MessageDigest, то попробуйте хешировать данные, как UTF-16LE.
https://support.cryptopr...etsja-v-kriptoarmcryptcp


Offline Скобелев Дмитрий  
#12 Оставлено : 16 июня 2021 г. 11:57:40(UTC)
Скобелев Дмитрий

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

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

Сказал(а) «Спасибо»: 1 раз
При подписи файла 1.txt (1kb) загружен 0 раз(а).
dataInBase64: 0LXRg9GL0LU=
получаем хэш ГОСТ Р 34.11-2012 256 - 8254466B9FE942F85BD6B8B243FE4D54966150E25BD3CE69D99462A698D9B5CB
при получении подписи хэша через cadesplugin

Код:
 signHash: function (sHashValue, hashAlg, certThumbprint) {
            const signHashByWebPlugin = function (sHashValue, hashAlg, certThumbprint) {
                return new Promise(function (resolve, reject) {
                    cadesplugin.async_spawn(function* (args) {
                        var oStore = yield cadesplugin.CreateObjectAsync("CAPICOM.Store");
                        yield oStore.Open(cadesplugin.CAPICOM_CURRENT_USER_STORE, cadesplugin.CAPICOM_MY_STORE,
                            cadesplugin.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

                        var oStoreCerts = yield oStore.Certificates;
                        var oCertificates = yield oStoreCerts.Find(
                            cadesplugin.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, certThumbprint);
                        var certsCount = yield oCertificates.Count;
                        if (certsCount === 0) {
                            err = "Certificate not found: " + certThumbprint;
                            console.error(err);
                            return args[1](err);
                        }
                        var oCertificate = yield oCertificates.Item(1);

                        var oSigner = yield cadesplugin.CreateObjectAsync("CAdESCOM.CPSigner");
                        yield oSigner.propset_Certificate(oCertificate);
                        yield oSigner.propset_CheckCertificate(true);
                        // Сохраняем всю цепочку сертификатов https://docs.microsoft.com/ru-ru/windows/win32/seccrypto/signer-options
                        yield oSigner.propset_Options(cadesplugin.CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN);


                        // Создаем объект CAdESCOM.HashedData
                        var oHashedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.HashedData");

                        // Инициализируем объект заранее вычисленным хэш-значением
                        // Алгоритм хэширования нужно указать до того, как будет передано хэш-значение
                        yield oHashedData.propset_Algorithm(hashAlg);
                        yield oHashedData.SetHashValue(sHashValue);

                        var oSignedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.CadesSignedData");
                        // Значение свойства ContentEncoding должно быть задано до заполнения свойства Content
                        //yield oSignedData.propset_ContentEncoding(cadesplugin.CADESCOM_BASE64_TO_BINARY);
                        //yield oSignedData.propset_Content(sHashValue);

                        var sSignedMessage = "";
                        try {
                            sSignedMessage = yield oSignedData.SignHash(oHashedData, oSigner, cadesplugin.CADESCOM_CADES_BES);
                            yield oStore.Close();
                        } catch (err) {
                            e = cadesplugin.getLastError(err);
                            console.error("Failed to create signature. Error: " + e);
                            yield oStore.Close();
                            return args[1](e);
                        }
                        return args[0](sSignedMessage);
                    }, resolve, reject);
                });
            };


получаем отсоединенную подпись 1server.txt.sig (3kb) загружен 1 раз(а). которую при сохранении как .sig можем проверить в CryptoTools

2021-06-16_153511.jpg (56kb) загружен 3 раз(а).

При попытке подписать этот же хеш этим же сертификатом, но через android

Код:
fun signHashData(hashData: String, hashAlg: String, currentAlias: String, pin: String?): String? {
        Logger.log("Load key container to sign data.")
        // Тип контейнера по умолчанию.
        val keyStoreType: String = KeyStoreType.currentType()
        Logger.log("Default container type: $keyStoreType")

        // Загрузка ключа и сертификата.
        if (pin != null) {
            load(
                false, keyStoreType,
                currentAlias, pin.toCharArray()
            )
        } else {
            load(
                true, keyStoreType,
                currentAlias, null
            )
        }
        if (privateKey == null) {
            Logger.log("Private key is null.")
            return null
        }

        // Формируем подпись.
        val chain = mutableListOf<X509Certificate>()

        if (certificates != null) {
            for (cert in certificates!!) {
                chain.add(cert as X509Certificate)
            }
        } else {
            chain.add(certificate!!)
        }
        var cAdESSignature = CAdESSignature(true, true)
        cAdESSignature.certificateStore =
            CollectionStore(mutableListOf(X509CertificateHolder(certificate!!.encoded)))

        val setCRL = getCRLsFromAssets()
        Logger.log(
            "Single signature type: " +
                    if (cAdESType == CAdESType.CAdES_BES) "CAdES-BES" else "CAdES-X Long Type 1"
        )
        Logger.log(
            "Add one signer: " +
                    certificate!!.subjectDN + "\n public key Alg  " + certificate!!.publicKey.algorithm
        )

        if (cAdESType == CAdESType.CAdES_BES) {
            cAdESSignature.addSigner(
                JCSP.PROVIDER_NAME, null,
                null, privateKey, chain, cAdESType, null, false, null, null, setCRL, true
            )
        } else {
            cAdESSignature.addSigner(
                JCSP.PROVIDER_NAME, null,
                null, privateKey, chain, cAdESType, CAdESSignVerifyPresenter.TSA_DEFAULT,
                false
            )
        }
        val signatureStream = ByteArrayOutputStream()
        Logger.log(
            "Compute signature for hash '" +
                    hashData + "\n" +
                    hashAlg
        )
        cAdESSignature.open(signatureStream)
        val encodedHash = toBase64(hashData.toByteArray())
        cAdESSignature.update(hashData.toByteArray())
        cAdESSignature.close()
        signatureStream.close()
        val sign = signatureStream.toByteArray()

        Logger.log(sign, true)

        // Проверяем подпись.
        Logger.log(
            "Verify CAdES signature of type: " +
                    if (cAdESType == CAdESType.CAdES_BES) "CAdES-BES" else "CAdES-X Long Type 1"
        )
        cAdESSignature = CAdESSignature(sign, hashData.toByteArray(), cAdESType, true)
        cAdESSignature.verify(chain, setCRL)
        Logger.log("CAdES signature has been created and verified (OK)")
        return toBase64(sign)
    }

получаем подпись, которая проходит проверку в данном методе, но не проходит проверку в CryptoTools - 1android.txt.sig (5kb) загружен 1 раз(а).
Screenshot_1623833118.jpg (322kb) загружен 1 раз(а).
2021-06-16_15351112.jpg (68kb) загружен 4 раз(а).

Пробовал перекодировать подписи из base64 и сравнить между собой, но видно только фрагменты данных
01.jpg (647kb) загружен 1 раз(а).
02.jpg (620kb) загружен 1 раз(а).

Пожалуйста, помогите разобраться.

Отредактировано пользователем 16 июня 2021 г. 12:00:17(UTC)  | Причина: Не указана

Offline Евгений Афанасьев  
#13 Оставлено : 29 июня 2021 г. 11:04:39(UTC)
Евгений Афанасьев

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

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Здравствуйте.
Я правильно понимаю, что основная проблема: вы делаете отделенную CAdES-подпись по хешу, но она не проверяется сторонним средством?
Offline Скобелев Дмитрий  
#14 Оставлено : 29 июня 2021 г. 13:55:27(UTC)
Скобелев Дмитрий

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

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

Сказал(а) «Спасибо»: 1 раз
Добрый день. Да.
Offline Евгений Афанасьев  
#15 Оставлено : 30 июня 2021 г. 17:45:44(UTC)
Евгений Афанасьев

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

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Сделал пример. Скорее всего, проблема в вашем случае в том, что неправильно подаются данные при проверке: для проверки подписи, выполненной по хешу, с тем же хешом, нужно вместо подписанных данных подавать тот же хеш. Или выбрать другой способ проверки - ниже проверка выполняется двумя способами.
Код:

import ru.CryptoPro.AdES.AdESConfig;
import ru.CryptoPro.CAdES.CAdESSignature;
import ru.CryptoPro.CAdES.CAdESType;
import ru.CryptoPro.JCP.JCP;
import ru.CryptoPro.JCP.KeyStore.JCPPrivateKeyEntry;
import ru.CryptoPro.JCP.params.JCPProtectionParameter;
import ru.CryptoPro.JCP.tools.Encoder;
import ru.CryptoPro.JCSP.JCSP;

import java.io.ByteArrayOutputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

public class RawCAdESExample {

    /**
    * Используется ГОСТ 2012 (256).
    */
    public static void main(String[] args) throws Exception {

        System.setProperty("com.sun.security.enableCRLDP", "true"); // используем CRL из CRL DP сертификата

        final String STORE_TYPE = JCSP.HD_STORE_NAME; // тип контейнера
        final String PROVIDER = JCSP.PROVIDER_NAME; // провайдер Java CSP
        final String ALIAS = "cades-2012-256"; // алиас ключа на алгоритме ГОСТ 2012 (256)
        final char[] PASSWORD = "password".toCharArray(); // пароль к ключу
        final byte[] DATA = "Hello, world!".getBytes(); // подписываемые данные

        // Задаем провайдер по умолчанию.

        AdESConfig.setDefaultProvider(PROVIDER);

        // Читаем закрытый ключ и цепочку сертификатов из контейнера.

        KeyStore keyStore = KeyStore.getInstance(STORE_TYPE, PROVIDER);
        keyStore.load(null, null);

        JCPProtectionParameter parameter = new JCPProtectionParameter(PASSWORD);
        JCPPrivateKeyEntry entry = (JCPPrivateKeyEntry) keyStore.getEntry(ALIAS, parameter);

        PrivateKey privateKey = entry.getPrivateKey();
        Certificate[] chain = entry.getCertificateChain();

        List<X509Certificate> certificates = new ArrayList<>();

        for (Certificate cert : chain) {
            certificates.add((X509Certificate) cert);
        } // for

        // Формируем отдельный хеш подписываемых данных на нужном
        // алгоритме ГОСТ 2012 (256). Он будет использован при подписи.

        MessageDigest md = MessageDigest.getInstance(
            JCP.GOST_DIGEST_2012_256_NAME, PROVIDER); // ГОСТ 2012 (256)

        final byte[] RAW_DIGEST = md.digest(DATA); // хеш данных

        // Создаем CAdES-BES подпись по хешу данных.

        CAdESSignature cAdESSignature = new CAdESSignature(true, true);

        cAdESSignature.addSigner( // добавляем подписанта
            PROVIDER,
            null,
            null,
            privateKey,
            certificates,
            CAdESType.CAdES_BES,
            null,
            false,
            null,
            null,
            null,
            true // добавляем цепочку сертификатов в подпись
        );

        ByteArrayOutputStream outSignatureStream = new ByteArrayOutputStream();
        cAdESSignature.open(outSignatureStream);

        cAdESSignature.update(RAW_DIGEST); // по хешу
        cAdESSignature.close();

        byte[] signature = outSignatureStream.toByteArray();
        System.out.println("%%% SIGNATURE:\n" + (new Encoder()).encode(signature));

        // 1. Проверка подписи по хешу.

        cAdESSignature = new CAdESSignature(signature, RAW_DIGEST, null, true); // используем хеш данных
        cAdESSignature.verify(null); // можно не задавать сертификаты, т.к. они есть в подписи

        System.out.println("%%% VERIFIED by HASH.");

        // 2. Проверка подписи по подписанным данным.

        cAdESSignature = new CAdESSignature(signature, DATA, null); // используем данные
        cAdESSignature.verify(null); // можно не задавать сертификаты, т.к. они есть в подписи

        System.out.println("%%% VERIFIED by DATA.");

    }
}

Результат проверки в cptools приложен cades_ver.jpg (95kb) загружен 14 раз(а).

Отредактировано пользователем 30 июня 2021 г. 18:00:04(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил Евгений Афанасьев за этот пост.
Скобелев Дмитрий оставлено 01.07.2021(UTC)
Offline Скобелев Дмитрий  
#16 Оставлено : 1 июля 2021 г. 11:22:17(UTC)
Скобелев Дмитрий

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

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

Сказал(а) «Спасибо»: 1 раз
Добрый день.
Нашел ошибку.
hashData нужно не просто представлять в виде byteArray( hashData.toByteArray() ), а с помощью метода
Код:
fun hexStringToByteArray(s: String): ByteArray {
            val len = s.length
            val data = ByteArray(len / 2)
            var i = 0
            while (i < len) {
                data[i / 2] = ((Character.digit(s[i], 16) shl 4)
                        + Character.digit(s[i + 1], 16)).toByte()
                i += 2
            }
            return data
        }


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