d2i_RSA_PUBKEY, d2i_RSAPrivateKey and d2i_RSAPublicKey returns NULL

后端 未结 1 590
伪装坚强ぢ
伪装坚强ぢ 2021-01-16 11:00

I created a RSA private key using the following command:

 openssl genrsa -out keypair.pem 2048

I must to use DER-encoded keys (PKCS#1) for

相关标签:
1条回答
  • 2021-01-16 11:26

    TLDR: d2i_RSA_PUBKEY and d2i_RSAPrivateKey should work, and do for me on Unix.

    You say you want 'DER-encoded keys (PKCS#1)'.

    For publickeys OpenSSL normally uses the format defined in X.509 as SubjectPublicKeyInfo which contains an AlgorithmIdentifier plus (edited) BIT STRING containing a publickey value in a structure that varies depending on the algorithm. For RSA, the algid contains an OID identifying RSA and no parameters; the algorithm-dependent structure is PKCS#1.

    In contrast, OpenSSL supports two types of privatekey format: there is a 'legacy' format for each algorithm (except DH), which for RSA is PKCS#1; and a generic format defined by PKCS#8 which like SPKI consists of an AlgorithmIdentifier plus an algorithm-dependent privatekey value, this time in OCTET STRING. PKCS#8 also has an option to encrypt the key, which SPKI doesn't have or need.

    Older parts of OpenSSL, including the genrsa and rsa commandline utilities, use legacy privatekey format, but SPKI publickey format which OpenSSL names PUBKEY. Thus your rsa commands created a publickey file readable by d2i_RSA_PUBKEY but not d2i_RSAPublicKey (which would be only the PKCS#1 part) and a privatekey file readable by d2i_RSAPrivateKey.

    If you truly need publickey in 'bare' PKCS#1 format, the rsa utility has options -RSAPublicKey_in and -RSAPublicKey_out to read and write this format since 1.0.0, although documented only recently and still not in the help message. That file will be readable by d2i_RSAPublicKey but not d2i_RSA_PUBKEY.

    One possibility: you don't mention operating system. DER files are binary, and in C to correctly handle binary files on Windows you must fopen with the b modifier, here you want "rb" for read binary. If I run your code on Unix it works, but to get correct results on Windows I must add the b.

    Also a minor point: you talk about 'loading contents ... in char* variables'. Actually you load the file contents into memory and use a char * variable to point to them. Strictly speaking, OpenSSL d2i routines want the address of a const unsigned char * variable -- and your compiler should warn you about this mismatch at least if you run it in a standard-conforming mode. But C requires pointers to all char flavors (signed unsigned and 'plain'), with or without qualification, to have the same representation and alignment requirements, even though they aren't compatible as defined in the standard, so passing char ** where const unsigned char ** is expected does work.

    0 讨论(0)
提交回复
热议问题