Suppose i have to public pem key like this
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vbqajDw4o6gJy8UtmIbkcpnk
O3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2
eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1
QWPdspTBKcxeFbccDwIDAQAB
-----END PUBLIC KEY-----
And i want to use openssl
int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,RSA *rsa, int padding)
. How can i translate the pem key to RSA *rsa
structure?
FYI: I can't use BIO because i just want to transplant openssl into a bootloader which doesn't have a UNIX filesystem. The only way i can do is translate public key into a C array.
I can't use BIO because i just want to transplant openssl into a bootloader which doesn't have a UNIX filesystem
I think you can still use a BIO
, it just has to be a memory BIO
, and not a file BIO
.
If you can't use a memory BIO
either, then I'm not sure you can use OpenSSL here.
How to translate pem public key into openssl RSA* structure
Use PEM_read_PUBKEY
or PEM_read_bio_PUBKEY
(or one of the *_PUBKEY
routines). They return an EVP_PKEY
. Then, use EVP_PKEY_get1_RSA
to convert it to a RSA
.
Something like:
static const char key[] = "-----BEGIN PUBLIC KEY-----\n"
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vbqajDw4o6gJy8UtmIbkcpnk\n"
"O3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2\n"
"eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1\n"
"QWPdspTBKcxeFbccDwIDAQAB\n"
"-----END PUBLIC KEY-----\n";
BIO* bio = BIO_new_mem_buf(key, (int)sizeof(key));
ASSERT(bio != NULL);
EVP_PKEY* pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
ASSERT(pkey != NULL);
int type = EVP_PKEY_get_type(pkey);
ASSERT(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2);
RSA* rsa = EVP_PKEY_get1_RSA(pkey);
ASSERT(rsa != NULL);
...
EVP_PKEY_free(pkey);
RSA_free(rsa);
BIO_free(bio);
And here's the helper you need. EVP_PKEY_get_type
is not part of the library:
int EVP_PKEY_get_type(EVP_PKEY *pkey)
{
ASSERT(pkey);
if (!pkey)
return EVP_PKEY_NONE;
return EVP_PKEY_type(pkey->type);
}
Related, you can also use the non-PEM version, which is the ASN.1/DER encoding of the key. This will allow you to save some size in the image. Then, you would use d2i_PUBKEY_bio
to read the key.
Converting from PEM to ASN.1/DER will save about 110 bytes:
$ ls -al pubkey.*
-rw-r--r-- 1 user staff 162 Jun 5 00:36 pubkey.der
-rw-r--r-- 1 user staff 272 Jun 5 00:52 pubkey.pem
To convert the PEM encoded public key to ASN.1/DER, follow these steps. First, copy the key to the clipboard. Second, pipe it into openssl pkey
with a tool like pbpaste
on OS X or xclip
on Linux:
$ pbpaste | openssl pkey -pubin -inform PEM -out pubkey.der -outform DER
Then, inspect the public key:
$ dumpasn1 pubkey.der
0 159: SEQUENCE {
3 13: SEQUENCE {
5 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
16 0: NULL
: }
18 141: BIT STRING, encapsulates {
22 137: SEQUENCE {
25 129: INTEGER
: 00 BB BD BA 9A 8C 3C 38 A3 A8 09 CB C5 2D 98 86
: E4 72 99 E4 3B 72 B0 73 8A AC 12 74 99 A7 F4 D1
: F9 F4 22 EB 61 7B F5 11 D6 9B 02 8E B4 59 B0 B5
: E5 11 80 B6 E3 EC 3F D6 1A E3 4B 18 E7 DA FF 6B
: EC 7B 71 B6 78 79 C7 97 90 81 F2 BB 91 5F D7 C1
: 97 F2 A0 C0 25 6B D8 96 84 B9 49 BA E9 B0 50 78
: FE 57 78 1A 2D 75 1E 1C BD 7D FC B8 F6 22 BC 20
: DD 3E 32 75 41 63 DD B2 94 C1 29 CC 5E 15 B7 1C
: 0F
157 3: INTEGER 65537
: }
: }
: }
Finally, do something like:
int main(int argc, char* argv[])
{
UNUSED(argc), UNUSED(argv);
static const unsigned char key[] = {
0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0xbd, 0xba,
0x9a, 0x8c, 0x3c, 0x38, 0xa3, 0xa8, 0x09, 0xcb, 0xc5, 0x2d, 0x98, 0x86, 0xe4, 0x72, 0x99, 0xe4,
0x3b, 0x72, 0xb0, 0x73, 0x8a, 0xac, 0x12, 0x74, 0x99, 0xa7, 0xf4, 0xd1, 0xf9, 0xf4, 0x22, 0xeb,
0x61, 0x7b, 0xf5, 0x11, 0xd6, 0x9b, 0x02, 0x8e, 0xb4, 0x59, 0xb0, 0xb5, 0xe5, 0x11, 0x80, 0xb6,
0xe3, 0xec, 0x3f, 0xd6, 0x1a, 0xe3, 0x4b, 0x18, 0xe7, 0xda, 0xff, 0x6b, 0xec, 0x7b, 0x71, 0xb6,
0x78, 0x79, 0xc7, 0x97, 0x90, 0x81, 0xf2, 0xbb, 0x91, 0x5f, 0xd7, 0xc1, 0x97, 0xf2, 0xa0, 0xc0,
0x25, 0x6b, 0xd8, 0x96, 0x84, 0xb9, 0x49, 0xba, 0xe9, 0xb0, 0x50, 0x78, 0xfe, 0x57, 0x78, 0x1a,
0x2d, 0x75, 0x1e, 0x1c, 0xbd, 0x7d, 0xfc, 0xb8, 0xf6, 0x22, 0xbc, 0x20, 0xdd, 0x3e, 0x32, 0x75,
0x41, 0x63, 0xdd, 0xb2, 0x94, 0xc1, 0x29, 0xcc, 0x5e, 0x15, 0xb7, 0x1c, 0x0f, 0x02, 0x03, 0x01,
0x00, 0x01
};
BIO* bio = BIO_new_mem_buf(key, (int)sizeof(key));
ASSERT(bio != NULL);
EVP_PKEY* pkey = d2i_PUBKEY_bio(bio, NULL);
ASSERT(pkey != NULL);
int type = EVP_PKEY_get_type(pkey);
ASSERT(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2);
RSA* rsa = EVP_PKEY_get1_RSA(pkey);
ASSERT(rsa != NULL);
// ...
EVP_PKEY_free(pkey);
RSA_free(rsa);
BIO_free(bio);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With