Java and OPENSSL

I need help to decrypt a base64 string of an ecncrypted text with openssl.

In the linux command line, I have done the following:

  1. Generated the public / private keys:
openssl genrsa -out private_key.pem 1024
openssl rsa -in private_key.pem -out public_key.pem -outform PEM -pubout

My private_key.pem looks like:

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDDu/0Fcq5/4M2t9Y+R4QvoDADQ+VaGSR3VEQiCV9xXcpkKAda+
nO2PrljIMcUO76O5a4twxxl1YT1dzKmj7T8i+EqYF1Y/1TxxWjIdo8hELD2Wug4d
ey3pMjI+5MXVraMyl5zEgfB64eTiu48LWygKi57Cfg41wKekSn2S/SvETQIDAQAB
AoGAFPgVwjioAyElR8av69PtP53RlJGxuE8q+AGMJNKe02t+g7jwtZkARk1KS6Ax
WUlJA/tGg/2Ad7fEKEFdxycKhVeF0ephOo8Xje6pMDDPpYSj/RlevUb60NEZZma1
PbA9TqS5Ys533jLYRbJUeNpufi0qQbRyB0QBJOUwbBHWDoECQQDsTYCoolsBHutY
YPZYBszOZhtxiDYqJ+B6/GoW/Y9h4HVg7CkKxaMdQBHbjTm+2YOH4SNHnwl7MVk3
cagbC/RhAkEA1AzKatUc7pUnkAO7VPM5luLnV/0ltpp6eveSgwxVs618a2BfFvS1
d8PAoKFCuCawTVd/GbY/fFKQab3hGiAXbQJBAOvIlZUukyG2KVzBO20wM9HK/p01
Ld64dXwiOvV/wj8GifjRDE7MT+rS0D7DVxhAz8aYdex0GzDKV9xD01pRfmECQBwi
9ljmnkgqEm3RkPHctC+JPBk4xeBM7yOR5ibtZBHLW08EIpnxLoMNvmmR/EBjIdGh
YoQO4q2kZvUg9NV6nKECQCFHa7lwlstxDqLgTzKHnRIK2hbUufrWKp+nDb18aqmF
eHvC4MZkixR+rykGRHsYjmwGKnXpbchKjC2iPFn1XY0=
-----END RSA PRIVATE KEY-----

And my public key looks like:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDu/0Fcq5/4M2t9Y+R4QvoDADQ
+VaGSR3VEQiCV9xXcpkKAda+nO2PrljIMcUO76O5a4twxxl1YT1dzKmj7T8i+EqY
F1Y/1TxxWjIdo8hELD2Wug4dey3pMjI+5MXVraMyl5zEgfB64eTiu48LWygKi57C
fg41wKekSn2S/SvETQIDAQAB
-----END PUBLIC KEY-----
  1. I can create a base64 string using my public_key.pem:
echo "Hola Mundo" | openssl rsautl -encrypt -pubin -inkey public_key.pem | base64 -w 0
gQO7XwvkClncfTpsv0jZ1Ptm2tI7YppHWdqwdrH2sZrG3ah5pcWt+PJ1q2ADPhZo8EURVmiYLO+q/P475/eUKY0h/T+IWQmV4lFCoXZfBzD3TzkN3nSmvj9HiR4psevYUa9HeOpECCXLJ1z8K4ut978zHtYKDi89k3VIdZUT6uY=
  1. I can decrypt the string using my private_key.pem:
echo "gQO7XwvkClncfTpsv0jZ1Ptm2tI7YppHWdqwdrH2sZrG3ah5pcWt+PJ1q2ADPhZo8EURVmiYLO+q/P475/eUKY0h/T+IWQmV4lFCoXZfBzD3TzkN3nSmvj9HiR4psevYUa9HeOpECCXLJ1z8K4ut978zHtYKDi89k3VIdZUT6uY=" | base64 -d | openssl rsautl -decrypt -inkey private_key.pem

Hola Mundo

Now, my question is, in JAVA, having the private key loaded like this:

String key = "MIICXAIBAAKBgQDDu/0Fcq5/4M2t9Y+R4QvoDADQ+VaGSR3VEQiCV9xXcpkKAda+\n" +
        "nO2PrljIMcUO76O5a4twxxl1YT1dzKmj7T8i+EqYF1Y/1TxxWjIdo8hELD2Wug4d\n" +
        "ey3pMjI+5MXVraMyl5zEgfB64eTiu48LWygKi57Cfg41wKekSn2S/SvETQIDAQAB\n" +
        "AoGAFPgVwjioAyElR8av69PtP53RlJGxuE8q+AGMJNKe02t+g7jwtZkARk1KS6Ax\n" +
        "WUlJA/tGg/2Ad7fEKEFdxycKhVeF0ephOo8Xje6pMDDPpYSj/RlevUb60NEZZma1\n" +
        "PbA9TqS5Ys533jLYRbJUeNpufi0qQbRyB0QBJOUwbBHWDoECQQDsTYCoolsBHutY\n" +
        "YPZYBszOZhtxiDYqJ+B6/GoW/Y9h4HVg7CkKxaMdQBHbjTm+2YOH4SNHnwl7MVk3\n" +
        "cagbC/RhAkEA1AzKatUc7pUnkAO7VPM5luLnV/0ltpp6eveSgwxVs618a2BfFvS1\n" +
        "d8PAoKFCuCawTVd/GbY/fFKQab3hGiAXbQJBAOvIlZUukyG2KVzBO20wM9HK/p01\n" +
        "Ld64dXwiOvV/wj8GifjRDE7MT+rS0D7DVxhAz8aYdex0GzDKV9xD01pRfmECQBwi\n" +
        "9ljmnkgqEm3RkPHctC+JPBk4xeBM7yOR5ibtZBHLW08EIpnxLoMNvmmR/EBjIdGh\n" +
        "YoQO4q2kZvUg9NV6nKECQCFHa7lwlstxDqLgTzKHnRIK2hbUufrWKp+nDb18aqmF\n" +
        "eHvC4MZkixR+rykGRHsYjmwGKnXpbchKjC2iPFn1XY0=";

and the encryped string loaded like this:

String data = "I3E5pjXE0chhtmkFBa56PGtWv5XDcIXfi2h5e3Bi44CCMvaIQ7UT7XBwkGZTRR11wfQIl7MswcEebXDmmw/C6JobrqQHQ0rU7zLPOU8j24JCFiccxclq5efMAcIO/ZcSO34uObrFQwQ4L2ex/3xL7b/YKujCQDTtzQkxE2N1JPU=";

How can I get the original "Hola Mundo" string back? Could you please point me in the right direction?

Thank you in advance.

Upvotes: 0

Views: 1531

Answers (2)

Whith the help of @michael-fehr, I could make it work; here what I did, just in case someone else could need it:

  1. Generate the openssl PKCS8 key pair:
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key

and as result now I have 2 files, publickey.crt:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxlfy+juJwTDtw8XolfSK
QB+JaKTgZMl+MjWo+m9n8Kt64ygqtfGvDda1UvT3t9e2ZpOvlsmfSIN0SUMhsq+T
/O8+Xyr87/sUU7tYocQ6adGh+zO58EecuSUtgutDdwh9/WkVqHhdCjeZXN5310/s
afaxJJzBemMjvmc/1yiMtBSVrCl71CloR6J1lnz+QZK+zqaNlKIQdQay9PoQlGEL
RrGgqo8fHdK3OQVUd6Ifzh5G1Mmnv67esCAKyeW8yeb6lQ7dtsJQJEC8M9yn4n1D
bz0+OwWWTzqHBo8b5JYi6xXnb/0WsaRX/ooWk5BEykmkkBhSmDYx0ZtLZcA2/Pj2
jwIDAQAB
-----END PUBLIC KEY-----

and pkcs8.key:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDGV/L6O4nBMO3D
xeiV9IpAH4lopOBkyX4yNaj6b2fwq3rjKCq18a8N1rVS9Pe317Zmk6+WyZ9Ig3RJ
QyGyr5P87z5fKvzv+xRTu1ihxDpp0aH7M7nwR5y5JS2C60N3CH39aRWoeF0KN5lc
3nfXT+xp9rEknMF6YyO+Zz/XKIy0FJWsKXvUKWhHonWWfP5Bkr7Opo2UohB1BrL0
+hCUYQtGsaCqjx8d0rc5BVR3oh/OHkbUyae/rt6wIArJ5bzJ5vqVDt22wlAkQLwz
3KfifUNvPT47BZZPOocGjxvkliLrFedv/RaxpFf+ihaTkETKSaSQGFKYNjHRm0tl
wDb8+PaPAgMBAAECggEAWpirnI77cioWQJkyjuQ/DeEZ05mUAZVjti16fMHMWUsK
e53KPIcjbY/IDRdl2yyF3T7SMm7v+aBJynkGeGboktz4wWGSXU9zTnfBmUpXYCRn
96T95nnfZVZM/oLVsxZG7ixEv0oTPWp9+8SGOuv/0brj2RRc77k/B2aD65RTCKGc
iHMqK/mzeLedXrthaBwd0ppkQw1M6YvPw+nx8Mhs/sADKMLUTNkqpu16d+2pOLeU
DKsvnA8ns6/jfFMMdkJ3mhoIeCfqYJJhosydMebLnt8yUo/3NlNmeRKcqH9qx8zC
em+0wx9+a1fEgzPvadF1pnmI4n/5VlIn9moZXmO0MQKBgQDkg+4QqJT1upAg2NSQ
QMagoSECGoCM54aMpTCTDlhrzphW7tms5AjDmfrN/2NQ+LodjBHpqNd6E44D9U+6
EHBJ/PGOJE1CWdVckAUX+a51g67lmPNrfrFolTT1zrTJNq4VCKFffLUDW9yw+B+0
9QlWN36LG/jYr3Ia4D59mAgCRwKBgQDeMwTCJDfCMOPtiLT5Xl4J9H76aHU8por0
4C3fkq/zWCPxxU3XAO6eJQNzEhM8I+Yo/b3WbyzyqM2Ww9Y8qSOD/cpr2ftSdT60
l7jPSGjAIyudAd3QjkVC+OgwX1cSrfyuiRoyuQiHPyzAoiqK4AKxxUa0EFD8Ec42
X+mHT3eFeQKBgH13TmvJE9iDcYUHaFY3qpchQO1VvcUfjcmFHVFwq+2tRgldJRj/
LyyuS311PoODvTRh5qfjM0Psnqnfs8GWKwEEp2AC4ISQrEwhKxrJ1RbikVGwk94u
dpvUaHqZ3rsnkZcs4OV7pCtO8bIc2dPSQikbWRhp6EyYr86/1q/AnI0bAoGAb5G4
gu8CnFxGJkAtdsUefOsqUvveWhzZywlBn3AdLxgDvGMwqZOLPRciu0XJKLpx2AVI
rAJY1GNUD663xO+8qIrnd+4VFptOaAmCv3oBNvCx9n04bn7xYiZvF9LXesaoCM9I
u01Tbe2XwAXtTJwcXjzLOqCyuU8LdxwDu3B4eCkCgYEAsTQ8Rn6YaCy2cNl/7BZy
Jfr8tqwKprOeu+tcRg/MxUjjo72PVsK8WiahHHKxpFNlsDa0/u6GlICKUaY9Emul
Chu20kYr6xFFiczLo9enwiAJ5TDOz8yqOyv/1wALiTayOz2DVTwiax/D45yLJxQ6
dV0YXCvoOcDjM1c/vDVOK7w=
-----END PRIVATE KEY-----
  1. Now, let's cypher "Hola Mundo" to a base64 string using the publickey.crt file:
echo "Hola Mundo" | openssl rsautl -encrypt -pubin -inkey publickey.crt | base64 -w 0
jeqdFnlj5Rxl8iQcoLc8o0u3KV4950OjSeqJW2ba0P5hcfdkIbtff/WW6rPdFudSYBOr1i+NwQ2jEpRGzOVrJ6mEZI4r/iFAJHkL7a3kQTs+pC1i5nig8MzO+5IU615HZhOykQ1FJfv3+OVOtTj8C5HLDZEehr1ggFPIp10YrYls6Gffxww5xlOZHBbg5J6JBmItmwFmvCl8O5ZI7N9hp5ynqqKYwAHxqRj0UUe1MXyGjEiL9aQdNiYJFCUL5V/0Vq6iP4sLRrU3Ir35fkMAWlQHt4vbmhgX5XUjv1804BIa7HlMytwnN7ZuKnJ6WKnOoJznpYbZOw92yXtKhPfUsA==
  1. Now, the java code to get the "Hola Mundo" back, with a little use of the Bouncy Castle Library:
import java.io.File;
import java.io.FileReader;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

import javax.crypto.Cipher;

import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

public class App {
    public static RSAPrivateKey readPrivateKey(File file) throws Exception {
        KeyFactory factory = KeyFactory.getInstance("RSA");
     
        try (FileReader keyReader = new FileReader(file);
          PemReader pemReader = new PemReader(keyReader)) {
     
            PemObject pemObject = pemReader.readPemObject();
            byte[] content = pemObject.getContent();
            PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
            return (RSAPrivateKey) factory.generatePrivate(privKeySpec);
        }
    }
    
    public static String getDecrypted(String data, RSAPrivateKey key) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        
        cipher.init(Cipher.DECRYPT_MODE, key);
        
        byte[] encryptedbytes = cipher.doFinal(Base64.getDecoder().decode(data.getBytes()));
        
        return new String(encryptedbytes);
    }
    
    public static void main(String[] args) {
        String data = "GjoUq7pz6ZV231MlZmBNiWnB7FlOHsGKFmAiMGhSUa9aIkXswnP8Ow4WTYR12tFIdyIeevQWCmEJgebiQ9wpBDLODtT4U00wTxPAfIjulgVhj0MA56b1nDkhCfL6gwzwsD2JxFO8/eMhqY1Wptn/fYn6USfbt7XFRyV73IeFBUvp0OisJ3DXxZsHfpfdL/yQcbGCboiiYEDkJ3DnLhGiaeMuLIedmABLgqWJv8EwPIBT0x/jgIMhaxQSwcs0w/fAYIEt/E4gkOpcFVkiTp6IKDsmiYgzDnXTnPko059Be9mQ3eJ3tIZ+U6Tfm1RCFY7Jr1oTIoZxOgHspgAIQb3U+w==";
        System.out.println("TEXTO CIFRADO:");
        System.out.println(data);
        System.out.println();

        
        try {
            File file = new File("/home/gbasisty/pruebas_openssl/pkcs8.key");
            RSAPrivateKey key = readPrivateKey(file);

            String texto = getDecrypted(data, key);
            System.out.println("TEXTO DESCIFRADO:");
            System.out.println(texto);
            System.out.println();
        } catch(Exception e) {
            System.out.println(e);
        }
    }
}

... and it works like a charm.

Thank you again Michael!

Upvotes: 0

Michael Fehr
Michael Fehr

Reputation: 6404

The issue that you are struggling with is the format/encoding of the private key.

You generated the RSA key pair with OpenSSL and received a private key in the "old" PKCS1 encoding, clearly to see in the beginning of the pem-string:

-----BEGIN RSA PRIVATE KEY-----

Unfortunately Java is not capable to use this encoding "out of the box" (you could use e.g. Bouncy Castle to read this kind of keys). But there is a solution and that is to convert the key to the (Java capable) PKCS8-encoding. Simply convert the key with

openssl pkcs8 -topk8 -nocrypt -in rsaprivatekeypkcs1.pem -out rsaprivatekeypkcs8.pem

and you will receive this private key:

-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMO7/QVyrn/gza31
j5HhC+gMAND5VoZJHdURCIJX3FdymQoB1r6c7Y+uWMgxxQ7vo7lri3DHGXVhPV3M
qaPtPyL4SpgXVj/VPHFaMh2jyEQsPZa6Dh17LekyMj7kxdWtozKXnMSB8Hrh5OK7
jwtbKAqLnsJ+DjXAp6RKfZL9K8RNAgMBAAECgYAU+BXCOKgDISVHxq/r0+0/ndGU
kbG4Tyr4AYwk0p7Ta36DuPC1mQBGTUpLoDFZSUkD+0aD/YB3t8QoQV3HJwqFV4XR
6mE6jxeN7qkwMM+lhKP9GV69RvrQ0RlmZrU9sD1OpLliznfeMthFslR42m5+LSpB
tHIHRAEk5TBsEdYOgQJBAOxNgKiiWwEe61hg9lgGzM5mG3GINion4Hr8ahb9j2Hg
dWDsKQrFox1AEduNOb7Zg4fhI0efCXsxWTdxqBsL9GECQQDUDMpq1RzulSeQA7tU
8zmW4udX/SW2mnp695KDDFWzrXxrYF8W9LV3w8CgoUK4JrBNV38Ztj98UpBpveEa
IBdtAkEA68iVlS6TIbYpXME7bTAz0cr+nTUt3rh1fCI69X/CPwaJ+NEMTsxP6tLQ
PsNXGEDPxph17HQbMMpX3EPTWlF+YQJAHCL2WOaeSCoSbdGQ8dy0L4k8GTjF4Ezv
I5HmJu1kEctbTwQimfEugw2+aZH8QGMh0aFihA7iraRm9SD01XqcoQJAIUdruXCW
y3EOouBPMoedEgraFtS5+tYqn6cNvXxqqYV4e8LgxmSLFH6vKQZEexiObAYqdelt
yEqMLaI8WfVdjQ==
-----END PRIVATE KEY-----

Yes, it looks equal but in the beginning it's just "...BEGIN PRIVATE KEY..".

As the default RSA padding on OpenSSL-side is PKCS1.5 padding

openssl rsautl -help
-pkcs Use PKCS#1 v1.5 padding (default)

you should use on Java-side this instance:

Cipher decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

and you will receive (with the PKCS8-key) the encrypted string Hola Mundo

Upvotes: 2

Related Questions