简体   繁体   中英

How to encrypt decrypt with RSA keys in java

I need to replace the encrypt and decrypt step from Unix to java code with the rsaprivatekey.pem and rsapublickey.pem keys generated with openssl

I generate the keys

openssl  genrsa  -out /tmp/rsaprivatekey.pem  -des3 1024
openssl rsa -in /tmp/rsaprivatekey.pem -pubout -out /tmp/rsapublickey.pem

i use the keys in unix (i need do it in java)

echo "Text to encript"| openssl rsautl -encrypt -inkey /tmp/rsapublickey.pem -pubin -out out.enc
openssl rsautl -decrypt -inkey /tmp/rsaprivatekey.pem -in out.enc

This was my attempt to do it

public static void main(String[] args) {


    Base64 base64 = new Base64();

    String TextStream = "this is the input text";
    byte[] Cipher;
    System.out.println("input:\n" + TextStream);
    Cipher = encrypt(TextStream);
    System.out.println("cipher:\n" + base64.encodeAsString(Cipher));
    System.out.println("decrypt:\n" + decrypt(Cipher));
}

private static byte[] encrypt(String Buffer) {
    try {

        Cipher rsa;
        rsa = Cipher.getInstance("RSA");
        rsa.init(Cipher.ENCRYPT_MODE, getPrivateKey(PRIVATE_PATH));
        return rsa.doFinal(Buffer.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}


private static String decrypt(byte[] buffer) {
    try {
        Cipher rsa;
        rsa = Cipher.getInstance("RSA");
        rsa.init(Cipher.DECRYPT_MODE, getPrivateKey(PUBLIC_PATH));
        byte[] utf8 = rsa.doFinal(buffer);
        return new String(utf8, "UTF8");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public static PrivateKey getPrivateKey(String filename) throws Exception {
    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int) f.length()];
    dis.readFully(keyBytes);
    dis.close();

    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePrivate(spec);
}

public static PublicKey getPublicKey(String filename) throws Exception {
    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int) f.length()];
    dis.readFully(keyBytes);
    dis.close();

    X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePublic(spec);
}

but it not works, the PKCS8EncodedKeySpec/X509EncodedKeySpec are not correct... but i do not know what to put

Solution:

Thanks to @Sanjeev, using the bouncy castle API, I was able to encrypt/decrypt with the keys generated by openssl

public static void main(String[] args) throws IOException {

    Security.addProvider(new BouncyCastleProvider());

    KeyPair keyPair = readKeyPair(new File(PRIVATE_PATH), "pass"); 
    // if the private key is not encripted, pass can be anything.
    Key publickey = readPublicKey(new File(PUBLIC_PATH), "pass"); 
    Base64 base64 = new Base64();
    String text = "this is the input text";
    byte[] encripted;
    System.out.println("input:\n" + text);
    encripted = encrypt(keyPair.getPublic(), text);
    System.out.println("cipher:\n" + base64.encodeAsString(encripted));
    System.out.println("decrypt:\n" + decrypt(keyPair.getPrivate(), encripted));        
}

private static byte[] encrypt(Key pubkey, String text) {
    try {
        Cipher rsa;
        rsa = Cipher.getInstance("RSA");
        rsa.init(Cipher.ENCRYPT_MODE, pubkey);
        return rsa.doFinal(text.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}


private static String decrypt(Key decryptionKey, byte[] buffer) {
    try {
        Cipher rsa;
        rsa = Cipher.getInstance("RSA");
        rsa.init(Cipher.DECRYPT_MODE, decryptionKey);
        byte[] utf8 = rsa.doFinal(buffer);
        return new String(utf8, "UTF8");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

private static KeyPair readKeyPair(File privateKey, String keyPassword) throws IOException {
    FileReader fileReader = new FileReader(privateKey);
    PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(keyPassword.toCharArray()));
    try {
        return (KeyPair) r.readObject();
    } catch (IOException ex) {
        throw ex;
    } finally {
        r.close();
        fileReader.close();
    }
}

private static Key readPublicKey(File privateKey, String keyPassword) throws IOException {
    FileReader fileReader = new FileReader(privateKey);
    PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(keyPassword.toCharArray()));
    try {
        return (RSAPublicKey) r.readObject();
    } catch (IOException ex) {
        throw ex;
    } finally {
        r.close();
        fileReader.close();
    }
}

I think you're having problems reading PEM files. The JPA doesn't directly support the PEM format. You have two options, either convert them to DER encoded files (you can use openSSL to do this) or the you can use the bouncy castle API to read (or write) PEM files. the class you'd be interested in is called PEMReader (and maybe also PEMWriter). Here is the Javadoc on the bouncycastle website.

You can use this library for it, it already does Base64 encoding/decoding for you:

AsymmetricKeyPair loadedKeyPair = AsymmetricKeyGenerator.loadKeyPair(AsymmetricKeyAlgorithm.ASYMMETRIC_KEY_ALGORITHM_RS256,"_BASE64_PUBLIC_KEY_", "_BASE64_PRIVATE_KEY_");

String plainMessage = "This is a secret message...";
String encryptedMessage = loadedKeyPair.encrypt(plainMessage);
String decryptedMessage = loadedKeyPair.decrypt(encryptedMessage);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM