使用openssl生成密钥对:
1 2 3 4 5 6 |
>openssl genrsa -out private.key >openssl rsa -in private.key -pubout -outform PEM -out public.key // 因为java里面不识别x509格式的私钥,所以必须转换为 pkcs8格式方可使用 // java异常描述为: java.security.spec.InvalidKeySpecException: Only RSAPrivate(Crt)KeySpec and PKCS8EncodedKeySpec supported for RSA private keys // 虽然RSAPrivate(Crt)KeySpec 也支持,但是目前还不知道怎么用 >openssl pkcs8 -topk8 -inform PEM -outform PEM -in private.key -out pkcs8_priv.pem -nocrypt |
java代码:
1. 注意: java 语言本身没有实现base64编码,而openssl生成的密钥对一般做base64编码,便于维护,所以这里引用了 org.apache.commons.codec.binary.Base64;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; import javax.crypto.Cipher; import org.apache.commons.codec.binary.Base64; //下载地址: http://commons.apache.org/codec/download_codec.cgi public static class MyRsa { /** * String to hold name of the encryption algorithm. */ public static final String ALGORITHM = "RSA"; /** * String to hold the name of the private key file. */ public static final String PRIVATE_KEY_FILE = "D:/rsa/pkcs8_priv.pem"; /** * String to hold name of the public key file. */ public static final String PUBLIC_KEY_FILE = "D:/rsa/public.key"; /** * Encrypt the plain text using public key. * * @param text * : original plain text * @param key * :The public key * @return Encrypted text * @throws java.lang.Exception */ public static byte[] encrypt(String text, PublicKey key) { byte[] cipherText = null; try { // get an RSA cipher object and print the provider final Cipher cipher = Cipher.getInstance(ALGORITHM); // encrypt the plain text using the public key cipher.init(Cipher.ENCRYPT_MODE, key); cipherText = cipher.doFinal(text.getBytes()); } catch (Exception e) { e.printStackTrace(); } return cipherText; } /** * Decrypt text using private key. * * @param text * :encrypted text * @param key * :The private key * @return plain text * @throws java.lang.Exception */ public static String decrypt(byte[] text, PrivateKey key) { byte[] dectyptedText = null; try { // get an RSA cipher object and print the provider final Cipher cipher = Cipher.getInstance(ALGORITHM); // decrypt the text using the private key cipher.init(Cipher.DECRYPT_MODE, key); dectyptedText = cipher.doFinal(text); } catch (Exception ex) { ex.printStackTrace(); } return new String(dectyptedText); } public static void test() { String s = "Hello world"; try { BufferedReader privateKey = new BufferedReader(new FileReader( PRIVATE_KEY_FILE)); BufferedReader publicKey = new BufferedReader(new FileReader( PUBLIC_KEY_FILE)); String strPrivateKey = ""; String strPublicKey = ""; String line = ""; while((line = privateKey.readLine()) != null){ strPrivateKey += line; } while((line = publicKey.readLine()) != null){ strPublicKey += line; } privateKey.close(); publicKey.close(); // 私钥需要使用pkcs8格式的,公钥使用x509格式的 String strPrivKey = strPrivateKey.replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", ""); String strPubKey = strPublicKey.replace("-----BEGIN PUBLIC KEY-----", "") .replace("-----END PUBLIC KEY-----", ""); //System.out.print(strPrivKey); //System.out.println(strPubKey); byte [] privKeyByte = Base64.decodeBase64(strPrivKey); byte [] pubKeyByte = Base64.decodeBase64(strPubKey); PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(privKeyByte); //PKCS8EncodedKeySpec pubKeySpec = new PKCS8EncodedKeySpec(pubKeyByte); //X509EncodedKeySpec privKeySpec = new X509EncodedKeySpec(privKeyByte); X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pubKeyByte); KeyFactory kf = KeyFactory.getInstance("RSA"); PrivateKey privKey = kf.generatePrivate(privKeySpec); PublicKey pubKey = kf.generatePublic(pubKeySpec); byte [] encryptByte = encrypt(s, pubKey); System.out.println(decrypt(encryptByte, privKey)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvalidKeySpecException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } |
稍后提供一个PHP加密Java解密的实现
参考资料:
http://stackoverflow.com/questions/11787571/how-to-read-pem-file-to-get-private-and-public-key
http://stackoverflow.com/questions/8647165/how-to-sign-a-generic-text-with-rsa-key-and-encode-with-base64-in-java
http://www.javamex.com/tutorials/cryptography/rsa_encryption.shtml
http://snowolf.iteye.com/blog/381767
密钥结构及格式: https://polarssl.org/kb/cryptography/asn1-key-structures-in-der-and-pem