'Convert RSA Public .pem file to pkcs8

Created RSA public - private key pairs using following commands -

Private key -

openssl genrsa -out private-key.pem 512

Public key

openssl rsa -in private-key.pem -pubout -out public-key.pem

Converted the private-key.pem from PEM to pkcs8 using following command(it worked completely fine) -

openssl pkcs8 -topk8 -inform PEM -outform DER -in private-key.pem -nocrypt > my_key

But can not convert public-key.pem from PEM to pkcs8 using a command like bellow -

openssl pkcs8 -topk8 -inform PEM -outform DER -in public-key.pem -nocrypt > my_key.pub

Getting following error -

openssl pkcs8 -topk8 -inform PEM -outform DER -in public-key.pem -nocrypt > my_key.pub
unable to load key
4525680300:error:09FFF06C:PEM routines:CRYPTO_internal:no start line:/AppleInternal/Library/BuildRoots/66382bca-8bca-11ec-aade-6613bcf0e2ee/Library/Caches/com.apple.xbs/Sources/libressl/libressl-2.8/crypto/pem/pem_lib.c:684:Expecting: ANY PRIVATE KEY

"unable to load key" "Expecting: ANY PRIVATE KEY"

Like to use it for RSA based JWT process like this



Solution 1:[1]

PKCS8 is not a standard for public keys. That is why Java, including the code you link, uses PKCS8EncodedKeySpec for private key, but X509EncodedKeySpec -- NOT PKCS8 -- for public key.

To create the X.509 (SPKI) DER publickey Java wants, use

openssl rsa -pubin -in public.pem -outform der -out public.der

... or combine with the extract step

openssl rsa -in private.pem -pubout -outform der -out public.der

Also you should know 512-bit RSA is horribly, pitifully weak and was breakable 25 years ago; I haven't checked recently but now it can probably be broken in minutes. But that isn't about programming or development and thus is offtopic, except in that if you want to use this for JWT/JWS/JWE those use the algorithms in JWA RFC7518 and for RSA signatures (3.3 and 3.5) and key transport (4.2) that document requires the key be '2048 bits or larger'.


Added for comment: The last argument to the genrsa command is the size of the key (in bits); your genrsa ... 512 generated 512. You can see this with e.g. openssl rsa -in private.pem -text -noout (you don't really need -noout, that just reduces clutter). Substituting e.g. 2048 would generate a 2048-bit key, which is the most common standard (and most common actual value) today, although some people still use slightly smaller values, and some prefer to use larger values to protect against faster-than-expected improvements in conventional technology (but not quantum, which if and when it is achieved at practical scale is expected to break all practical sizes of RSA and require changing to entirely different algorithms).

I'm going to guess you actually looked at the file size (which is always shown in bytes). That is quite different from the key size (which is measured in bits), but would never be 256, and rarely if ever 512 (i.e. by happenstance equal to the bit-size of the modulus).

First (and fundamentally) keys for traditional/symmetric ciphers are mostly 'just bits' (although DES confused this by using parity), but keys for publickey/asymmetric algorithms like RSA are more complicated. An RSA keypair (and OpenSSL's privatekey is really a keypair, which is why you can extract the pubkey from it) starts with a modulus n, but also contains two exponents (e and d), two prime factors (p and q), and several 'CRT' components (dp, dq, and qinv). For details see wikipedia or PKCS1 republished as RFC8017 et pred especially 3.2 and A.1.2. The size of an RSA key is conventionally measured by its modulus (only, and in bits), but the complete keypair is several times larger, although the publickey is only slightly larger than the modulus.

Second, the files used by OpenSSL to store a key (keypair or publickey-only) contain more than just the actual key; they contain metadata whose size varies depending on the format, and in some cases are superencoded and/or encrypted which increased the size (although your example doesn't use encryption), and files are measured in bytes. To begin with OpenSSL represents all asymmetric keys using Abstract Syntax Notation One aka ASN.1 and specifically Distinguished Encoding Rules aka DER (linked there); for RSA keys these are the ASN.1 structures in RFC8017 A.1.2 and A.1.1 linked above. ASN.1 DER is a variable-length encoding, and the RSAPrivateKey structure for a 512-bit RSA key will usually vary in a range from 317-321 bytes, although it can (very rarely) be less (but never more).

Then for privatekeys (keypairs) OpenSSL has two main formats, with several variants or subformats. For the 'traditional' format in DER, it simply writes the PKSC1 RSAPrivateKey structure; in PEM if not encrypted it first converts the PKCS1 structure to base64 with linebreaks, then adds header and trailer lines, for a total of usually 487-498 bytes. PEM format can be encrypted, which makes it even longer. For the algorithm-generic PKCS8 form if unencrypted in DER it effectively adds a header which is 26 bytes in this case to the PKCS1 structure, giving usually 343-347 bytes, which converts to PEM as 520-532 bytes; PKCS8 encrypted, supported in either DER or PEM, is larger. None of these is 256.

OTOH for publickey OpenSSL (at least in most commandline) uses only one format with two variants; the RSAPublicKey structure from PKCS1 (linked above) in the SubjectPublicKeyInfo structure defined by X.509 as subsetted by PKIX RFC5280 4.1. For 512-bit RSA the result is 94 bytes in DER or 182-186 bytes in PEM (neither encrypted). Again not 256.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1