简体   繁体   English

如何在 java 中使用 RSA 密钥加密解密

[英]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我需要用 openssl 生成的rsaprivatekey.pemrsapublickey.pem密钥替换从 Unix 到 java 代码的加密和解密步骤

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)我使用 unix 中的密钥(我需要用 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但它不起作用,PKCS8EncodedKeySpec/X509EncodedKeySpec 不正确......但我不知道该放什么

Solution: 解:

Thanks to @Sanjeev, using the bouncy castle API, I was able to encrypt/decrypt with the keys generated by openssl 感谢@Sanjeev,使用充气城堡API,我能够使用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. 我认为您在阅读PEM文件时遇到问题。 The JPA doesn't directly support the PEM format. JPA不直接支持PEM格式。 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. 您有两个选项,要么将它们转换为DER编码文件(您可以使用openSSL执行此操作),也可以使用bouncy castle API来读取(或写入)PEM文件。 the class you'd be interested in is called PEMReader (and maybe also PEMWriter). 您感兴趣的课程称为PEMReader(也可能是PEMWriter)。 Here is the Javadoc on the bouncycastle website. 这是 bouncycastle网站上的Javadoc

You can use this library for it, it already does Base64 encoding/decoding for you:你可以使用这个库,它已经为你做了 Base64 编码/解码:

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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