Загрузите закрытый ключ RSA в PEM в Crypto ++ - PullRequest
12 голосов
/ 22 марта 2012

Часто пользователь имеет закрытые ключи RSA в кодировке PEM.Crypto ++ требует, чтобы эти ключи были загружены в формате DER.Я просил людей заранее конвертировать свои файлы PEM в DER, используя openssl, например:

openssl pkcs8 -in in_file.pem -out out_file.der -topk8 -nocrypt -outform der

Это прекрасно работает, но некоторые люди не понимают, как это делать, и не хотят.Поэтому я хотел бы автоматически конвертировать PEM-файлы в файлы DER в программе.

Это так же просто, как убрать "----- BEGIN CERTIFICATE -----" и "-----КОНЕЦ СЕРТИФИКАТА ----- "от PEM или требуется какое-то другое преобразование?Мне сказали, что между этими маркерами это просто кодированный с помощью b64 DER.Вот некоторый код, который демонстрирует проблему:

// load the private key
CryptoPP::RSA::PrivateKey PK;
CryptoPP::ByteQueue bytes;

try
{
    CryptoPP::FileSource File( rsa.c_str(), true, new CryptoPP::Base64Decoder() );
    File.TransferTo( bytes );
    bytes.MessageEnd();

    // This line Causes BERDecodeError when a PEM encoded file is used
    PK.Load( bytes );
}

catch ( CryptoPP::BERDecodeErr )
{
    // Convert PEM to DER and try to load the key again
}

Я бы хотел избежать системных вызовов openssl и выполнять преобразование полностью в Crypto ++, чтобы пользователи могли предоставлять любой формат, и все «просто работает».Спасибо за любой совет.

Ответы [ 3 ]

7 голосов
/ 22 марта 2012

Да, это поток DER, закодированный с Base64.Однако обратите внимание, что помимо чередования маркеров BEGIN и END, в случае формата ключа RSA вам также необходимо удалить любые флаги, которые могут быть вставлены между маркером BEGIN и закодированными данными.Только оставшаяся часть может быть успешно декодирована Base64.Похоже, что вы передаете полный файл сертификата в декодер, и это требует исправления.

2 голосов
/ 25 августа 2014

... Я хотел бы автоматически конвертировать файлы PEM в файлы DER в программе.

В июле 2014 года для пакета PEM Pack был предоставлен *1005*.Библиотека Crypto ++.Пакет PEM - это частичная реализация шифрования сообщений, которая позволяет считывать и записывать ключи и параметры, закодированные в PEM, включая зашифрованные закрытые ключи.Дополнительные файлы включают в себя поддержку ключей RSA, DSA, EC, ECDSA и параметров Диффи-Хеллмана.

Это дополнение к библиотеке, а не часть самой библиотеки.Вы загружаете ZIP и добавляете пять исходных файлов в библиотеку.Затем вы создаете библиотеку (Crypto ++ автоматически подбирает их).ZIP содержит пять дополнительных исходных файлов, скрипт для создания тестовых ключей с использованием OpenSSL, программу на C ++ для тестирования чтения и записи ключей и скрипт для проверки ключей, написанных Crypto ++ с использованием OpenSSL.

Вот как выбудет использовать его:

CryptoPP::RSA::PrivateKey pk;
CryptoPP::FileSource file("<rsa-key-file.pem>", true);

CryptoPP::PEM_Load(file, pk);

CryptoPP::AutoSeededRandomPool prng;
bool = pk.Validate(prng, 3);
if (! valid)
    throw ...

Если ключи зашифрованы, то вот как вы могли бы загрузить его. PEM Pack повторно реализует OpenSSL EVP_BytesToKey, поэтому деривация ключей будет работать, и вы можете взаимодействовать:

CryptoPP::RSA::PrivateKey pk;
CryptoPP::FileSource file("<rsa-key-file.pem>", true);

std::string pass = "<super secret password>";
CryptoPP::PEM_Load(file, pk, pass.data(), pass.size());

CryptoPP::AutoSeededRandomPool prng;
bool = pk.Validate(prng, 3);
if (! valid)
    throw ...

Также есть PEM_Save, поэтому вы можете писать ключипрямо из Crypto ++.Например:

// Generate it or load it from somewhere
CryptoPP::RSA::PrivateKey pk = ...; 
CryptoPP::FileSink file("<rsa-key-file.pem>", true);

CryptoPP::PEM_Save(file, pk);

и PEM_Save для зашифрованного ключа (или ключа, который вы собираетесь шифровать):

// Generate it or load it from somewhere
CryptoPP::RSA::PrivateKey pk = ...; 
CryptoPP::FileSink file("<rsa-key-file.pem>", true);

std::string pass = "<super secret password>";
CryptoPP::PEM_Save(file, pk, "AES-128-CBC", pass.data(), pass.size());

PEM_Load делает не необходималгоритм, потому что он закодирован в инкапсулированном заголовке.PEM_Save нужен алгоритм, потому что нет алгоритма по умолчанию.

2 голосов
/ 24 января 2013

Я знаю, что это старый вопрос, но другие могут посчитать это полезным.Как только вы уберете маркеры, у вас останется «внутренний» ключевой материал.В соответствии с http://www.cryptopp.com/wiki/Keys_and_Formats#BER_and_DER_Encoding вы можете использовать BERDecodePrivateKey, чтобы загрузить это.Таким образом, чтобы загрузить ключ openssl, у которого были удалены маркеры, вы можете сделать что-то вроде

bool LoadKey(RandomNumberGenerator& rng, const std::string& file, 
    RSA::PrivateKey& key)
{
    ByteQueue q;
    FileSource KeyFile(file.c_str(), true, new Base64Decoder);
    KeyFile.TransferTo(q);
    key.BERDecodePrivateKey(q,false,0); // last 2 params unused
    return key.Validate(rng, 2);
}
...