(2018-08-24 13:42:46 отредактировано gas)

Key is not permitted to be used in operation

Здравствуйте! Разбираюсь с API pkicore, работаю с ЭЦП смарт-картой. Использую тестовый сертификат, который мне выдал мой локальный контроллер домена. Сертификат успешно экспортирован на карту. Открытый ключ - RSA (1024). Успешно шифрую им тестовое сообщение, но при попытке его тут же расшифровать на устройстве, получаю "Key is not permitted to be used in operation".
В чем может быть причина? Может ключевая пара не той системы?

Код примерно такой:

    try
    {
        cout << boolalpha;
        rutoken::pkicore::initialize(".");
        SCOPE_EXIT() { rutoken::pkicore::deinitialize(); };

        auto devices = Pkcs11Device::enumerate();
        const std::string plaint_text = "Hello, World!"; //Типа секретные данные
        const std::vector<uint8_t> plaint_data{ plaint_text.begin(), plaint_text.end() };

        for (auto&& device : devices)
        {
            device.login("12345678");
            SCOPE_EXIT(&device) { device.logout(); };

            auto cert_file_data = readFile("D:\\Temp\\123-dev.cer");
            ExternalCert cert_file(cert_file_data.data(), cert_file_data.size());
            cms::EnvelopParams enlelop_params{ device };
            enlelop_params.addRecipient(cert_file);
            auto enveloped_data = cms::envelop(plaint_data, enlelop_params);

            auto certs = device.enumerateCerts();
            if (certs.empty())
            {
                throw runtime_error("Token has no certificates.");
            }

            auto cert = move(certs.front());
            try
            {
                cert.getCorrespondingPrivateKey();
            }
            catch (std::exception&)
            {
                throw runtime_error("Certificate has no private key.");
            }

            auto message = enveloped_data.decrypt(cms::EnvelopedData::DecryptParams{ cert }); // <<= Вот тут вылетает исключение с сообщением "Key is not permitted to be used in operation"
            if (message.contentType() != cms::ContentType::data)
            {
                throw runtime_error("Unsupported content type of enveloped data");
            }
        }
    }
    catch (const exception& e)
    {
        cerr << e.what() << endl;
        return 1;
    }

Re: Key is not permitted to be used in operation

В общем, методом тыка выяснилось, что если сгенерить ключевую пару на устройстве (например гост), создать CSR, выдать по нему самоподписанный сертификат и экспортировать его обратно на устройство, то все работает как надо. Но если загрузить на устройство сертификат, изначально содержащий ключевую пару, то получаем "Key is not permitted to be used in operation".

Re: Key is not permitted to be used in operation

Похоже сертификаты с RSA не поддерживаются. Печаль. Причем если самому сгенерить RSA на устройстве, то можно зашифровать/расшифровать сообщения (если разбить на блоки и соблюсти паддинг, но это уже другая история).

Re: Key is not permitted to be used in operation

Добрый день, gas.

Вы описали несколько сценариев работы и не совсем понятно в каком именно у Вас не заработали сертификаты с RSA. Можете уточнить? Какое именно устройство Вы используете?

Судя по тому, что Вам не удалось импортировать ГОСТ ключевую пару, скорее всего это одна из моделей смарт-карты семейства Рутокен ЭЦП. Импорт ГОСТ ключей на сертифицированные Рутокен ЭЦП запрещен регулятором (ФСБ), такие токены генерируют ключи на борту и никогда не выдают их наружу, что гарантирует их существование в единственном экземпляре.

(2018-08-27 10:45:38 отредактировано gas)

Re: Key is not permitted to be used in operation

Какое именно устройство Вы используете?

Использую смарт-карту Рутокен ЭЦП 2.0.

в каком именно у Вас не заработали сертификаты с RSA

Сертификаты с RSA не заработали во всех нижеперечисленных сценариях:
1. Сертификат с ключевой парой RSA (1024), выданный моим местным контроллером домена (файл обмена личной информацией .pfx). Импорт сертификата на устройство проходит успешно, приватный ключ перечисляется в общем списке c помощью методов Pkcs11Device::enumeratePrivateKeys и  Pkcs11UserCert::getCorrespondingPrivateKey. Но при попытке выполнить enveloped_data.decrypt(cms::EnvelopedData::DecryptParams{ cert }) для сертификата с RSA-ключем, получаю исключение "Key is not permitted to be used in operation"
2. Сертификат, сделанный на ключевой паре RSA, которая была сгенерирована в самом устройстве. Для этого я генерил ключевую пару RSA (2048), на ее основе выдавал запрос на выдачу сертификата. Получал сертификат, экспортировал его на устройство. В итоге на устройстве получался сертификат с нормальной ключевой парой, которой вел себя точно так же, как описано в первом случае.

Единственное, что пока заработало - это выполнение п.2, но для ключевой пары, полученной на устройстве с помощью Pkcs11Device::generateKeyPair с настройками Pkcs11Device::Gost34102012_512KeyGenParams.
Такой сертификат перечисляется, объект его приватного ключа можно получить обеими указанными выше методами и при этом enveloped_data.decrypt(cms::EnvelopedData::DecryptParams{ cert }) для указанного сертификата нормально выполняется и расшифровывает ранее зашифрованное сообщение.

Однако, по определенным причинам хотелось бы того же, но для RSA 1024 и выше.

Импорт ГОСТ ключей на сертифицированные Рутокен ЭЦП запрещен регулятором (ФСБ), такие токены генерируют ключи на борту и никогда не выдают их наружу, что гарантирует их существование в единственном экземпляре.

Это очевидно, я и не пытался экспортировать ключевую пару наружу из устройства или импортировать имеющийся (у меня такого и нет). Создавал сертификат на основе запроса из устройства и импортировал его на устройство, где он уже самостоятельно подклеивал приватный ключ, от сгенерированной ранее ключевой пары.

Re: Key is not permitted to be used in operation

gas, похоже в pkicore действительно есть проблема с расшифровыванием. Исправим в будущем релизе.

На данный момент есть несколько обходных вариантов:

  • Использовать "сырое" шифрование\расшифрование с помощью PKCS#11. Пример можно посмотреть тут - sdk\pkcs11\samples\Standard\EncDecRSA

  • Если нужен именно CMS, то использовать openssl. Пример можно посмотреть тут - sdk\openssl\rtengine\samples\EncryptCMS (DecryptCMS)

Re: Key is not permitted to be used in operation

Сырое шифрование RSA я проверял и оно работает. Пока выберу этот вариант.
Спасибо.