rosl
rosl

Reputation: 33

Passing RSA keys between Java and Crypto++ code

I have a server written in java that generates RSA key pair. I want to use the private key in a C++ client for decryption.

This is the code I use to create the private key:

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(4096);
KeyPair keyPair = keyGen.genKeyPair();

PrivateKey privateKey = keyPair.getPrivate();
byte[] encoded = privateKey.getEncoded();
String b64Encoded = Base64.getEncoder().encodeToString(encoded);

I then save the base64 encoded string and try to load it as a private key in my cpp code.

I decode the base64 string to a binary array and then use the following code to try loading the private key (encodedString should be the DER encoded data after decoding it from base64):

ByteQueue queue;

StringSource ss(encodedString,true);
ss.TransferTo(queue);
queue.MessageEnd();

key.BERDecodePrivateKey(queue, false , queue.MaxRetrievable());

However this code always crashes with exception: CryptoPP::BERDecodeErr.

I believe both libraries use PKCS#8 to encode the key parameters.

Note: When I create the key pair using crypto++ and then encode it (DER + base64) I get a 3172/3176 chars string while in my java code I get a 3168 chars string. I'm not sure whether this info helps with anything.

Upvotes: 2

Views: 886

Answers (1)

jww
jww

Reputation: 102245

It looks like you need to call Load and not BERDecodePrivateKey. You call Load when you have a key+info (like version and algorithm id); while you call BERDecodePrivateKey when you have just a key. The following works for me.

If the private key is password protected, then you will need the PEM Pack. The PEM Pack is a community contribution, but its maintained like the proper library.

$ cat rsa_java.java 
import java.io.*;
import java.util.*;
import java.security.*;

public class rsa_java {
    public static void main (String[] args) throws Exception {

    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
    keyGen.initialize(4096);
    KeyPair keyPair = keyGen.genKeyPair();

    PrivateKey privateKey = keyPair.getPrivate();
    byte[] encodedPrivateKey = privateKey.getEncoded();
    String b64Encoded = Base64.getEncoder().encodeToString(encodedPrivateKey);

    try (PrintStream out = new PrintStream(new FileOutputStream("rsa_key.txt")))
    {
        out.print(b64Encoded);
    }
}

And:

$ cat rsa_cryptopp.cxx
#include <iostream>
using namespace std;

#include "cryptopp/rsa.h"
#include "cryptopp/files.h"
#include "cryptopp/osrng.h"
#include "cryptopp/base64.h"
using namespace CryptoPP;

int main(int argc, char* argv[])
{
  try
  {
    RSA::PrivateKey key;
    FileSource fs("rsa_key.txt", true, new Base64Decoder);
    key.Load(fs);

    cout << "Loaded RSA key" << endl;

    AutoSeededRandomPool prng;
    key.Validate(prng, 3);

    cout << "Validated RSA key" << endl;
  }
  catch(const Exception& ex)
  {
    cout << "Exception: " << ex.what() << endl;
  }

  return 0;
}

It results in:

$ javac rsa_java.java && java rsa_java
$ g++ -I. rsa_cryptopp.cxx cryptopp/libcryptopp.a -o rsa_cryptopp.exe
$ ./rsa_cryptopp.exe 
Loaded RSA key
Validated RSA key

For completeness, here's the key with the Base64 encoding. Its 3168 bytes:

$ fold -w 80 -s rsa_key.txt
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

Upvotes: 2

Related Questions