4

I'm working with Openssl on C++ and getting in trouble with my CSR generation. What i'm wanted to do is creating a CSR without using the private key. I want to put my details and of course the public key in it, but because of security management i can't call the sign function. Instead i want to collect all the "data which should be signed" and transmit it to another application which creates the signature in a secure area. When my application is receiving the signature i want to manually set the value in the X509_REQ struct and write the CSR to PEM format.

My problem is, how to get the "data to be signed"? I know that the CSR is Asn1 Decoded, do you know any function to get the asn1 data as a string or something?

This is from my test prog:

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());
matsjoyce
  • 5,744
  • 6
  • 31
  • 38
NFoerster
  • 386
  • 2
  • 16
  • I doubt you will be able to create (or maybe submit?) a CSR using the OpenSSL APIs without signing the request. The Certificate Signing Request process is engineered to ensure the party submitting the request proves ownership or knowledge of the private key. I'm guessing the OpenSSL workflows are predicated upon it. With that said, you may be able to hack something together using the OpenSSL APIs. You should checkout the subcommand sources, like that of [`apps/x509.c`](https://github.com/openssl/openssl/blob/master/apps/x509.c). The x509 utility is responsible for CSRs. – jww Feb 28 '17 at 23:37
  • If you are using C++ *and* using `BIO_new` and `BIO_free` without a `unique_ptr`, then you are missing a lot of C++ opportunities. There's almost no reason to call `BIO_free` yourself with RAII. You may want to checkout questions like [How to get PKCS7_sign result into a char * or std::string](http://stackoverflow.com/a/38079093/608639) and [How to generate RSA private key using openssl?](http://stackoverflow.com/a/30493975/608639) They show you some of the tricks to write C++-ish code with OpenSSL. – jww Feb 28 '17 at 23:42
  • 2
    I finally did it with a realy dirty hack, i compiled openssl sources with logs und got the array which gonna be signed. I compared it with my signing data and it was nearly the same, i manipulated my data that it fits the one from openssl. Further i read out the structs being filled by the sign function and filled my structs with that data + my own generated signature. At least the PEM is the same and the private key must not leave the private area. It's dirty but it works. Thanks – NFoerster Mar 02 '17 at 11:31
  • Why not send all the info for the CSR to the 'secure machine', create the CSR over there, sign it, and send back the signed certificate? (Sorry, not enough rep to comment so I'm using an answer :P) – melk Nov 03 '17 at 14:56
  • 1
    Just to clear missunderstanding why i did that: We have a trusted zone on an embedded machine which does not know open ssl lib but conserves all private keys. The private keys could not be retrieved from that place. The API to that zone only knows a sign data method and nothing else, so i have to give the CSR in its raw form as a byte array to that API and finally construct the CSR with the received signature. – NFoerster Dec 16 '17 at 16:22

0 Answers0