import org.apache.commons.codec.binary.Base64
;
import org.junit.
Test;
import javax.crypto.Cipher
;
import java.io.ByteArrayOutputStream
;
import java.security.KeyFactory
;
import java.security.PrivateKey
;
import java.security.PublicKey
;
import java.security.spec.PKCS8EncodedKeySpec
;
import java.security.spec.X509EncodedKeySpec
;
/**
* 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
* 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
* 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
*/
public class RSAEncrypterTest {
/**
* 加密算法RSA
*/
private static final String
KEY_ALGORITHM =
"RSA";
/**
* 签名算法
*/
private static final String
CIPHER_ALGORITHM =
"RSA/ECB/PKCS1Padding";
/**
* 私钥
* openssl pkcs8 -topk8 -inform PEM -in p_key.pem -outform PEM -nocrypt
*/
private static final String
PRIVATE_KEY =
"" +
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPMhwl+bv8MlboJf" +
"u6W5ec0SoQQxsHn8fHmfIEvWpLc1K6uiycJfOR4nHz2hRPMquw5uuz/yWvDUkrcl" +
"dabWKuI9tq2kv8Kxv1M2E+9DE+ySCKqsrAp/XZMlsy8DP+fkPEATQRv4EUkH5eD6" +
"x+0BlOpbZVtXdC7vyWeGSPOwldiRAgMBAAECgYBZ5ozB34xbszaWnKF9GQURsCa7" +
"r0frA1Jfglhl0ntbhxybvXjPF3i+Tob9uekN5Sn/nzA75/h6fo+1ivNi+mQmRVf2" +
"6h5/kfRYy0y3RNPFOTnd6B36etUx6EpzXlpT/q+igRqlu4ts4P1heBGOdqtLlSp9" +
"0KqHnjieFEgMpMschQJBAP1HdyYoSJwbYd5J3DpUIEpfjIn1MkJ2OyrEk6MQypqF" +
"G8ilOJCMsFFW8oY6pPPYT9z+3NwPqxz+UWU9Kv9WjXcCQQD1vmNcAB4eg99uEExs" +
"WOHEcWFNZ654K/iJ915A/c7cIJSBkoe80kqDYg+UXuY/r7ZuUi3zPSECZzs4ge8H" +
"+yw3AkEAzPSM1WLZxwFdhAzO2qCC9Mw3JNg3EJMuM+CY++a1nK7EGeyhRk+iyl+K" +
"p9ZC71QG5HWU8br4I+EkqsEBz1gR5wJAf8/kEaemAq0H+lDTzs5zrh5iQ0YXwjzs" +
"aaWVCix3+JmhY7r4ika9ppPMEplBHAKh2cM4TviOQJe8f2llDzueBQJBAPaYpKS7" +
"fTh7xi5WkJrStcNVOVgThxgmIEg3mGTztBMe87WTgUAPMr4N9gewNf+5jx231cFB" +
"3gYkkPgWNOYL/2Y=";
/**
* 公钥
*/
private static final String
PUBLIC_KEY =
"" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzIcJfm7/DJW6CX7uluXnNEqEE" +
"MbB5/Hx5nyBL1qS3NSurosnCXzkeJx89oUTzKrsObrs/8lrw1JK3JXWm1iriPbat" +
"pL/Csb9TNhPvQxPskgiqrKwKf12TJbMvAz/n5DxAE0Eb+BFJB+Xg+sftAZTqW2Vb" +
"V3Qu78lnhkjzsJXYkQIDAQAB";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK =
117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK =
128;
@Test
public void decodeTest()
throws Exception {
String data =
"g08ZvPcrV+k8Fh1wJ8BRGDGJWOV6pm6aq6G+Q0vgfS4SQXAXx1DI9r489cs9krBu/2Okm1g4tvqzESWHW/" +
"HFqFdsgYAHluN/x6mOAx4WTYYw5XlWCYdEUhhfHeUhZi9WR0omKCrFgSfyNWx5OPy/35PSLuvl5df5E30ewejDM9+tV8" +
"pAr/lDQD30BE/XwH2Hvc1EdsZ54kncK2v7lOvmMNR3PmjVsryQNnuy4kqUY5yOqi7VJlf8atOheCUe+psrnJauDc32m/" +
"R99hE1UhD/R8j7Df9ZptbL/37GOpyeCyRrBpGaSjUDJ2YmiS3AnA2hoeDVV5eT72J8P5EPFYuDGQ==";
PrivateKey privateKey =
getPrivateKey(
PRIVATE_KEY)
;
Cipher vDeCipher = Cipher.
getInstance(
CIPHER_ALGORITHM)
;
vDeCipher.init(Cipher.
DECRYPT_MODE, privateKey)
;
//私钥解密
byte[] decrypted =
autoFinal(Base64.
decodeBase64(data.getBytes())
, vDeCipher
, MAX_DECRYPT_BLOCK)
;
System.
out.println(
"解密后:" +
new String(decrypted
, "utf-8"))
;
}
@Test
public void baseTest()
throws Exception {
PrivateKey privateKey =
getPrivateKey(
PRIVATE_KEY)
;
PublicKey publicKey =
getPublicKey(
PUBLIC_KEY)
;
String data =
"RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。";
//--
Cipher pEnCipher = Cipher.
getInstance(
CIPHER_ALGORITHM)
;//java默认"RSA"="RSA/ECB/PKCS1Padding"
pEnCipher.init(Cipher.
ENCRYPT_MODE, publicKey)
;
Cipher vDeCipher = Cipher.
getInstance(
CIPHER_ALGORITHM)
;
vDeCipher.init(Cipher.
DECRYPT_MODE, privateKey)
;
//--
Cipher vEnCipher = Cipher.
getInstance(
CIPHER_ALGORITHM)
;
vEnCipher.init(Cipher.
ENCRYPT_MODE, privateKey)
;
Cipher pDeCipher = Cipher.
getInstance(
CIPHER_ALGORITHM)
;
pDeCipher.init(Cipher.
DECRYPT_MODE, publicKey)
;
//公钥加密
byte[] encrypted = Base64.
encodeBase64(
autoFinal(data.getBytes(
"utf-8")
, pEnCipher
, MAX_ENCRYPT_BLOCK))
;
System.
out.println(
"加密后:" +
new String(encrypted))
;
//私钥解密
byte[] decrypted =
autoFinal(Base64.
decodeBase64(encrypted)
, vDeCipher
, MAX_DECRYPT_BLOCK)
;
System.
out.println(
"解密后:" +
new String(decrypted
, "utf-8"))
;
//私钥加密
byte[] encrypted2 = Base64.
encodeBase64(
autoFinal(data.getBytes(
"utf-8")
, vEnCipher
, MAX_ENCRYPT_BLOCK))
;
System.
out.println(
"加密后:" +
new String(encrypted2))
;
//公钥解密
byte[] decrypted2 =
autoFinal(Base64.
decodeBase64(encrypted2)
, pDeCipher
, MAX_DECRYPT_BLOCK)
;
System.
out.println(
"解密后:" +
new String(decrypted2
, "utf-8"))
;
}
/**
* 将base64编码后的公钥字符串转成PublicKey实例
*/
private static PublicKey
getPublicKey(String publicKey)
throws Exception {
byte[] keyBytes =
new Base64().decode(publicKey.getBytes())
;
X509EncodedKeySpec keySpec =
new X509EncodedKeySpec(keyBytes)
;
KeyFactory keyFactory = KeyFactory.
getInstance(
KEY_ALGORITHM)
;
return keyFactory.generatePublic(keySpec)
;
}
/**
* 将base64编码后的私钥字符串转成PrivateKey实例
*/
private static PrivateKey
getPrivateKey(String privateKey)
throws Exception {
byte[] keyBytes =
new Base64().decode(privateKey.getBytes())
;
PKCS8EncodedKeySpec keySpec =
new PKCS8EncodedKeySpec(keyBytes)
;
KeyFactory keyFactory = KeyFactory.
getInstance(
KEY_ALGORITHM)
;
return keyFactory.generatePrivate(keySpec)
;
}
private static byte[]
autoFinal(
byte[] data
, Cipher cipher
, int blockSize)
throws Exception {
int inputLen = data.
length;
byte[] rs
;
try (ByteArrayOutputStream out =
new ByteArrayOutputStream()) {
int offSet =
0;
byte[] cache
;
int i =
0;
// 对数据分段加密
while (inputLen - offSet >
0) {
if (inputLen - offSet > blockSize) {
cache = cipher.doFinal(data
, offSet
, blockSize)
;
}
else {
cache = cipher.doFinal(data
, offSet
, inputLen - offSet)
;
}
out.write(cache
, 0, cache.
length)
;
i++
;
offSet = i * blockSize
;
}
rs = out.toByteArray()
;
}
return rs
;
}
}