Создайте CSR с OpenSSL без подписи

Я работаю с Openssl на С++ и у меня проблемы с созданием CSR. Что я хотел сделать, так это создать CSR без использования закрытого ключа. Я хочу поместить в него свои данные и, конечно же, открытый ключ, но из-за управления безопасностью я не могу вызвать функцию подписи. Вместо этого я хочу собрать все «данные, которые должны быть подписаны» и передать их другому приложению, которое создает подпись в защищенной области. Когда мое приложение получает подпись, я хочу вручную установить значение в структуре X509_REQ и записать CSR в формат PEM.

Моя проблема в том, как получить «данные для подписи»? Я знаю, что CSR декодируется как Asn1, знаете ли вы какую-нибудь функцию для получения данных asn1 в виде строки или что-то в этом роде?

Это из моей тестовой программы:

std::string subjectCN = "Test123";
std::string subjectL = "Test456";
std::string subjectSN = "1234";
std::string szProvinceStr = "test";
std::string szOrganization = "My Organization";
std::string szCountry = "DE";
int         nVersion = 1;
EVP_PKEY        *test = NULL;

//RSA just for test validation
std::string mKey = "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQCDT4ntP3Fqj73RQW32B6hCDHMG64GtxeQDZ5BcQnQSRB3S/EwM\ngpZwuGYwTb7E65pdAAQ0e5na2d7yIGZX4MoDRGaDbYgdxr49J430cVLRU1r9EW+O\nqZQERyGYefxWOqBaNZL2PBclS/qf+AxRh1WnD8aY5V5zNItgVV4Bv9w4YQIDAQAB\nAoGAMd6xaXNg5bG1y5Vn57q8wmjr/sLOu2qe0FQy1Xc/kfhgw1Kip1WpQSInXU0J\nmMxKEewBrNUMd7urGpYHiHSNA+QXiIp3qxGy7PrmZrPSrJImPxAE02YaUGDoh+6o\nZJc7xXCw2bwX8Fth8Duj2KNcIDuWuieybfzwTYKKJG3J04ECQQDxSa4gq/0SiiZ2\nc8YTn9wCTwqezmdI8SWsWXRnpXt1BhejokvLFbqpfQZ6m9LLYvpUsihZ2QkBXUl/\n1/uNu+aJAkEAi1Ey/7fjJJSJalNUgF3lKQdTqUlYI/9O9/98zPOcDmXcKlLNpf+f\nTV3nhK3vsewYqsx3Tu9bMKBVTE0dv+/NGQJAHfYyQyhYMpcpE4hozkMJhNffz7x9\notcfAHnTNJOd8vggs1cR5lP6a9V0moEC+fJ+d0nwLMgAkETPParKN91fUQJAEWMB\n3V4ir+cFu0pJCngtaFBsxXzMzjlHrrWo6p8gg798mZ+Z4LSlOe+VPD7E4kyXy4EX\nBrfihpAL9SjOpKyVyQJBAPD3E4Z7THZCQI/2u4eRXz3qbJAmPYLPTn/AxuX4VssW\n1WJAxZeCFHWL6+/84zoDWwzXN0xQFzO0ZspxxQNFqCI=\n-----END RSA PRIVATE KEY-----";

BIO* bo = BIO_new( BIO_s_mem() );
BIO_write( bo, mKey.c_str(),mKey.length());

EVP_PKEY* pkey = 0;
PEM_read_bio_PrivateKey( bo, &pkey, 0, 0 );

BIO_free(bo);

RSA* rsa = EVP_PKEY_get1_RSA( pkey );

x509Req = X509_REQ_new();
ret = X509_REQ_set_version(x509Req, nVersion);

x509Name = X509_REQ_get_subject_name(x509Req);

ret = X509_NAME_add_entry_by_txt(x509Name,"C", MBSTRING_ASC, (const unsigned char*)szCountry.c_str(), -1, -1, 0);
ret = X509_NAME_add_entry_by_txt(x509Name,"ST", MBSTRING_ASC, (const unsigned char*)szProvince.c_str(), -1, -1, 0);
ret = X509_NAME_add_entry_by_txt(x509Name,"L", MBSTRING_ASC, (const unsigned char*)subjectL.c_str(), -1, -1, 0);
ret = X509_NAME_add_entry_by_txt(x509Name,"O", MBSTRING_ASC, (const unsigned char*)szOrganization.c_str(), -1, -1, 0);
ret = X509_NAME_add_entry_by_txt(x509Name,"CN", MBSTRING_ASC, (const unsigned char*)subjectCN.c_str(), -1, -1, 0);

test = EVP_PKEY_new();
EVP_PKEY_assign_RSA(test, rsa);
ret = X509_REQ_set_pubkey(x509Req, test);

PEM_write_bio_X509_REQ(basicInputOutput, x509Req);
BIO_get_mem_ptr(basicInputOutput, &pointerToBuffer);

std::string csrTemp = std::string(pointerToBuffer->data, pointerToBuffer->length);

//now i need all the data to create the signature
//i cant't call 
//ret = X509_REQ_sign(x509Req, test, EVP_sha256());

person Thorgas    schedule 28.02.2017    source источник
comment
Я сомневаюсь, что вы сможете создать (или, может быть, отправить?) CSR, используя API-интерфейсы OpenSSL, не подписывая запрос. Процесс запроса на подпись сертификата разработан таким образом, чтобы сторона, отправляющая запрос, подтвердила право собственности или знание закрытого ключа. Я предполагаю, что рабочие процессы OpenSSL основаны на этом. С учетом сказанного вы можете взломать что-то вместе, используя API OpenSSL. Вы должны проверить источники подкоманд, такие как apps/x509.c. Утилита x509 отвечает за CSR.   -  person jww    schedule 01.03.2017
comment
Если вы используете C++ и, используя BIO_new и BIO_free без unique_ptr, то вы упускаете много возможностей C++. Практически нет причин вызывать BIO_free самостоятельно с помощью RAII. Вы можете проверить такие вопросы, как Как получить результат PKCS7_sign в char * или std::string и Как сгенерировать закрытый ключ RSA с помощью openssl? Они покажут вам некоторые приемы написания кода C++ с OpenSSL.   -  person jww    schedule 01.03.2017
comment
Наконец, я сделал это с помощью действительно грязного взлома, я скомпилировал исходники openssl с журналами и получил массив, который будет подписан. Я сравнил его с моими данными для подписи, и они были почти такими же, я манипулировал своими данными, чтобы они соответствовали данным из openssl. Далее я прочитал структуры, заполняемые функцией знака, и заполнил свои структуры этими данными + моей собственной сгенерированной подписью. По крайней мере, PEM тот же, и закрытый ключ не должен покидать приватную область. Это грязно, но это работает. Спасибо   -  person Thorgas    schedule 02.03.2017
comment
Почему бы не отправить всю информацию для CSR на «защищенную машину», создать CSR там, подписать его и отправить обратно подписанный сертификат? (Извините, недостаточно представителей для комментариев, поэтому я использую ответ: P)   -  person melk    schedule 03.11.2017
comment
Просто чтобы устранить непонимание, почему я это сделал: у нас есть доверенная зона на встроенной машине, которая не знает open ssl lib, но сохраняет все закрытые ключи. Закрытые ключи не могут быть извлечены из этого места. API этой зоны знает только метод данных знака и ничего больше, поэтому я должен предоставить CSR в необработанном виде в виде массива байтов для этого API и, наконец, создать CSR с полученной подписью.   -  person Thorgas    schedule 16.12.2017