1

I have a java program which RSA encrypts data with a private key:

    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

    PrivateKey privateKey = null;
    PublicKey publicKey = null;

    // Load certificate from keystore
    try {
        FileInputStream keystoreFileInputStream = new FileInputStream("keystore.jks");
        KeyStore keystore = KeyStore.getInstance("JKS");
        keystore.load(keystoreFileInputStream, "passphrase".toCharArray());

        try {
            privateKey = (PrivateKey) keystore.getKey("idm_key", "passphrase".toCharArray());

        } catch (UnrecoverableKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    } catch (Exception e) {
        // TODO broad exception block
        e.printStackTrace();
    }

    // Make the encrypted data.

byte[] toEncrypt = "Data to encrypt".getBytes();
    byte[] encryptedData = null;

    // Perform private key encryption 
    try {
        // Encrypt the data
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        encryptedData = cipher.doFinal(toEncrypt);

    } catch (Exception e) {
        // TODO broad exception block
        e.printStackTrace();
    }

I have the need to do the same thing using openssl. Here is the code I tried:

uint8_t *encryptedBytes = NULL;

const char* data = "Data to enrypt";
char *private_key_file_name = "privatekey.pem"

FILE *fp = fopen(private_key_file_name, "r");
RSA *rsa = RSA_new();

PEM_read_RSAPrivateKey(fp, &rsa, 0, "passphase");

size_t encryptedBytesSize = RSA_size(rsa);

encryptedBytes = malloc(encryptedBytesSize * sizeof(uint8_t));
memset((void *)encryptedBytes, 0x0, encryptedBytesSize);
fclose(fp);

int result = RSA_private_encrypt(strlen(data), data, encryptedBytes, rsa,RSA_PKCS1_PADDING);

This is not producing the same output as the Java implementation. Instead, it produces the output that is gotten by signing the data in Java, i.e.,

Signature rsa = Signature.getInstance("RSA");
rsa.initSign(privateKey);
rsa.update(toEncrypt);
byte [] signed = rsa.sign();

Though this is what I would expect given the documentation for RSA_private_encrypt, it's not what I need. Is there a way to replicate what the java code is doing with openssl?

Josh Dubey
  • 11
  • 3

2 Answers2

3

I think you are confused. you don't "encrypt" data with a private key. That's worthless, as anyone can decrypt it. You sign with the private key (so anyone can verify it) and encrypt with the public key (so that only the holder of the private key can decrypt it). That is why the openssl API has RSA_public_encrypt which does encryption and RSA_private_encrypt which does signing.

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • I'm not confused, at least I don't believe I am. A bit more background: The first bit of java code was provided to me by a client. Unless I am misunderstanding it, they use it as is to encrypt with the private key. I know that is backwards, but that is what they do. I need to do the same thing with openssl. See also http://stackoverflow.com/questions/1391692/encrypting-with-rsa-private-key-in-java – Josh Dubey Aug 27 '12 at 15:51
  • @JoshDubey - Well, that my be what they do (which doesn't make any sense), unfortunately the openssl api (at first glance) doesn't appear to support it. – jtahlborn Aug 27 '12 at 16:00
0

You don't need to use OpenSSL in Java at all, whatever it is that you're trying to do. Java has its own crypto libraries. See the JCE reference and the javax.crypto package.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I guess my question wasn't entirely clear. The first bit of java code was presented as an example. I am writing an c program that needs to mimic that behavior, hence the need for OpenSSL. – Josh Dubey Aug 28 '12 at 11:01