# RSAKey & openSSL-generated keys

**URL:** https://forum.juce.com/t/rsakey-openssl-generated-keys/51737
**Category:** General JUCE discussion
**Created:** [June 7, 2022, 10:08pm UTC](https://forum.juce.com/t/rsakey-openssl-generated-keys/51737 "2022-06-07T22:08:36Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![matkatmusic](https://avatars.discourse-cdn.com/v4/letter/m/dfb087/32.png) [@matkatmusic](https://forum.juce.com/u/matkatmusic)
#### Post date: [June 7, 2022, 10:08pm UTC](https://forum.juce.com/t/rsakey-openssl-generated-keys/51737/1 "2022-06-07T22:08:36Z")

</div>

This has been asked before over the years and there is no definitive answer

Is the consensus that JUCE’s RSAKey class is not compatible with public & private keys generated using openssl?

Over the past few days I have figured out how to parse PEM-formatted public keys. When I print the key as a hex string, it produces the same hex output as shown here for the same key:

> **[Online Certificate Decoder, decode...](https://8gwifi.org/PemParserFunctions.jsp)**
>
> Use this Certificate Decoder to decode your certificates in PEM format. This certificate viewer tool will decode certificates so you can easily see their contents. This parser will parse the follwoing ...

I know I am on the right track, but it seems like the `juce::RSAKey` is just not compatible with keys produced externally. using `BigInteger::exponentModulo` also produces garbage with the parsed values.

I am not sure, when loading this hex string into the BigInteger, whether or not the external SSL public key is stored in little endian or big-endian format.

Here is what I’m currently doing, which works up until the point of decryption:

```auto
    static juce::String convertPEMPublicKeyToString(juce::String pubKey)
    {
        jassert( pubKey.contains("-----BEGIN PUBLIC KEY-----"));
        jassert( pubKey.contains("-----END PUBLIC KEY-----"));
        jassert( pubKey.contains("MII")); //PEM keys start with 'MII'
        
        auto keyDataArr = juce::StringArray::fromLines(pubKey);
        keyDataArr.remove(keyDataArr.indexOf("-----END PUBLIC KEY-----"));
        keyDataArr.remove(0);
        keyDataArr.removeEmptyStrings();
        
        auto pemData = keyDataArr.joinIntoString("");
        
        DBG( "pemData: " );
        DBG( pemData );
        
        return pemData;
    }

```

```auto
    using PEMMemoryBlock = juce::MemoryBlock;
    using PEMDataType = juce::uint8;
    
    static PEMMemoryBlock convertPEMStringToPEMMemoryBlock(juce::String pemString)
    {
        PEMMemoryBlock mb;
        {
            juce::MemoryOutputStream mos(mb, false);
            auto ok = juce::Base64::convertFromBase64(mos, pemString);
            jassert(ok);
            juce::ignoreUnused(ok);
        }
        
        return mb;
    }

```

usage:

```auto
        auto pemString = PEMHelpers::convertPEMPublicKeyToString(pubKey);
        
        if( ! pemString.contains("MII") )
        {
            //it's not a PEM key. abort!
            DBG( "invalid key!" );
            return;
        }
        
        auto pemData = PEMHelpers::convertPEMStringToPEMMemoryBlock(pemString);
//parsing of PEM data goes here...
//then...

```

```auto
        auto modulusHexStr = juce::String::toHexString(modulusBlock.getData(), modulus->length);
        modulusHexStr = modulusHexStr.removeCharacters(" ");
        DBG( "modulus hex: ");
        DBG( modulusHexStr );
        
        auto modulusBigInteger = juce::BigInteger();
        modulusBigInteger.parseString(modulusHexStr, 16);

        auto exponentHexStr = juce::String::toHexString(exponentBlock.getData(), exponent->length);
        exponentHexStr = exponentHexStr.removeCharacters(" ");
        DBG( "exponent hex: ");
        DBG( exponentHexStr );
        auto exponentBigInteger = juce::BigInteger();
        exponentBigInteger.parseString(exponentHexStr, 16);
        DBG( "exponent val: " );
        DBG( exponentBigInteger.toString(10));

```

```auto
        auto confirmation = resultVar["confirmation"].toString();
        auto confirmationBlock = PEMHelpers::convertPEMStringToPEMMemoryBlock(confirmation);
        auto confirmationHex = juce::String::toHexString(confirmationBlock.getData(),
                                                         confirmationBlock.getSize());
        
        juce::BigInteger confirmationBigInt;
        confirmationBigInt.parseString(confirmationHex, 16);
        confirmationBigInt.exponentModulo(exponentBigInteger, modulusBigInteger);
        auto decrypted = confirmationBigInt.toMemoryBlock();

```

`decrypted` never contains the correct result.  
but the `exponentHexStr` and `modulusHexStr` printouts match the output from various online tools that show the exponent and modulus in hex for a given public key.  
Also, the `value` printout matches the various online tools’ values for these massive exponents and modulos.

Comments?

> [@Can RSAKey class be used with regular keys?](https://forum.juce.com/t/can-rsakey-class-be-used-with-regular-keys/9705):
>
> Can i use RSAKey Class with regular server generated RSAKeys? Like: -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6yFeJ/hedg4JzDmVlQOyw4YPadu90lN5YTrH/ 2vdtobMOFTBA+f9gtvnIYONQIG22fJVrvHBnx2x/G+ho4k1kk2A3vbDxe/FwjjPe6/id9ahu0M61 VxighjOgwmtFo0EI7bjSfbaeVl7Cr97p++LRMeCVQoz3Ew5fHaKMQVUBuwIDAQAB -----END PUBLIC KEY----- it seems the class needs two big numbers, how can those numbers be generated? Is the RSA compatible with anything outside juce?, or is more RSA-likeish. Tha…

> [@RSAKey and openssl compatibilities](https://forum.juce.com/t/rsakey-and-openssl-compatibilities/4755):
>
> I’ve tried to make the juce RSAKey work with a pair of openssl generated keys with no success. Any probability of getting the juce classes to work with openssl rsa keys ?

> [@Instanciating rsaKey with key from openssl lib](https://forum.juce.com/t/instanciating-rsakey-with-key-from-openssl-lib/18430):
>
> I want to instanciate an rsa key from a string like the following " 048dd230b9c480fa1aeaa3dd3ca74cb902ce6ddc5140eb9ab35a16d6d2eec917fde00e616f499 e6ee40545346296f4ac … 86540094c9d55a60446066d97c43f1b61c64b7fed41586cb8d27054c8379e71 " But there is no comma in the string, and I got an assertion because of that. The format seems different, maybe it’s my lack of experience, but does someone know about this issue? Thank you

---

<div class="post-metadata">

### Author: ![matkatmusic](https://avatars.discourse-cdn.com/v4/letter/m/dfb087/32.png) [@matkatmusic](https://forum.juce.com/u/matkatmusic)
#### Post date: [June 8, 2022, 2:46am UTC](https://forum.juce.com/t/rsakey-openssl-generated-keys/51737/2 "2022-06-08T02:46:47Z")

</div>

Alright, a little bit more sleuthing and I have figured it out!

I’m able to load an openssl-generated public key into a juce::RSAKey class, and then successfully decrypt a message from my server that was encrypted with an openssl-generated private key.

I’ll share the code in a bit after I test it out some more.

Fun fact, the decrypted string is reversed! That means there is finally a need for a `juce::String::reverse` member function!! 😜

---

<div class="post-metadata">

### Author: ![danielrudrich](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/danielrudrich/32/3735_2.png) [@danielrudrich](https://forum.juce.com/u/danielrudrich)
#### Post date: [June 8, 2022, 5:05am UTC](https://forum.juce.com/t/rsakey-openssl-generated-keys/51737/3 "2022-06-08T05:05:55Z")

</div>

Congrats you made it!

Please note that encryption with private keys isn’t as secure as encryption with public keys. Usually you create signature with the private key, the receiver can verify with the public one. And encryption usually happens with the public one so that only the holder of the private key can decrypt a message.

---

<div class="post-metadata">

### Author: ![matkatmusic](https://avatars.discourse-cdn.com/v4/letter/m/dfb087/32.png) [@matkatmusic](https://forum.juce.com/u/matkatmusic)
#### Post date: [June 8, 2022, 6:06am UTC](https://forum.juce.com/t/rsakey-openssl-generated-keys/51737/4 "2022-06-08T06:06:39Z")

</div>

Sure sure.

I’m just trying to get things working, and encrypting on the server with one key and decrypting with the other is all I’ve tried so far.  
The php snippet I borrowed showed encrypting with the private key and decryption with the public key, so that’s why I encrypted with private, and sent the public key to my JUCE app.

A lot of what I used to get this working is ported from a pure javascript tool for parsing PEM files.  
Since a lot of that project’s code is copied and edited from other sites, I am not sure how much of what I ported is actually needed or as well-written as it could be.  
But i’ll share it so people can use/adapt/improve.

---

<div class="post-metadata">

### Author: ![matkatmusic](https://avatars.discourse-cdn.com/v4/letter/m/dfb087/32.png) [@matkatmusic](https://forum.juce.com/u/matkatmusic)
#### Post date: [June 9, 2022, 4:18am UTC](https://forum.juce.com/t/rsakey-openssl-generated-keys/51737/5 "2022-06-09T04:18:50Z")

</div>

Ok, here is the php and C++.  
I have tested it with keys that have 1024 bits, 2048, 4096, and 8192 bits.  
It works as expected (decrypting successfully).

If testing if I can use the private key on the C++ side to decrypt messages encrypted on the server side with the public key fails, I will update accordingly.

Some of this code is ported from this javascript page: [ASN.1 JavaScript decoder](https://lapo.it/asn1js)  
Therefore, the ported code definitely has room for improvement.

Perhaps the JUCE team can add this functionality to the RSAKey class, now that I’ve demonstrated how to get the RSAKey class working with regular OpenSSL keys. Keys that were generated like this:

```auto
openssl genpkey -algorithm RSA -out ./key.pem -pkeyopt rsa_keygen_bits:8192

openssl rsa -in ./key.pem -out ./publickey.pem -outform PEM -pubout

```

> <https://gist.github.com/matkatmusic/bd7091ebcbd539aa5d1a5e0a79acf480>

---

<div class="post-metadata">

### Author: ![asimilon](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/asimilon/32/4235_2.png) [@asimilon](https://forum.juce.com/u/asimilon)
#### Post date: [June 9, 2022, 8:10am UTC](https://forum.juce.com/t/rsakey-openssl-generated-keys/51737/6 "2022-06-09T08:10:51Z")

</div>

> [@danielrudrich](#):
>
> Please note that encryption with private keys isn’t as secure as encryption with public keys. Usually you create signature with the private key, the receiver can verify with the public one. And encryption usually happens with the public one so that only the holder of the private key can decrypt a message.

> [@matkatmusic](#):
>
> If testing if I can use the private key on the C++ side to decrypt messages encrypted on the server side with the public key fails, I will update accordingly.

This very much depends on the principle that the private key is **private**. If you distribute software containing the private key, it’s possible to derive the public key and your “encryption” is now useless.

---

<div class="post-metadata">

### Author: ![matkatmusic](https://avatars.discourse-cdn.com/v4/letter/m/dfb087/32.png) [@matkatmusic](https://forum.juce.com/u/matkatmusic)
#### Post date: [June 9, 2022, 4:26pm UTC](https://forum.juce.com/t/rsakey-openssl-generated-keys/51737/7 "2022-06-09T16:26:22Z")

</div>

@asimilon I’m well aware that private keys should remain private.

The code I shared is solely for the purpose of loading public openssl keys into the juce::RSAKey class, because no one has shared how to do that on the forum as of yet, and jules stated over a decade ago that supporting openssl keys in the juce RSAKey class is not on his todo list: ([RSAKey and openssl compatibilities - #2 by jules](https://forum.juce.com/t/rsakey-and-openssl-compatibilities/4755/2)).

Consider the code I shared as a starting place for supporting openssl keys in the juce::RSAKey class.  
It is by no means a complete solution for us JUCE users.

---

<div class="post-metadata">

### Author: ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)
#### Post date: [December 26, 2023, 11:17am UTC](https://forum.juce.com/t/rsakey-openssl-generated-keys/51737/8 "2023-12-26T11:17:39Z")

</div>

Hi @matkatmusic ,  
how is the experience after using this code now for a while?  
I was using the code from the juce docs with phpseclib, and it broke each time I move it to a new server, once even when moving to a different domain at the same hoster, so I am fed up with that approach.

If you are using your code successfully, I would volunteer to review it and move it into a juce module and add unit tests. I need something stable now.  
Cheers
