简介
非对称加密:加密和解密使用不同的秘钥的加解密方法。一般的,用公钥做加密,私钥做解密使用
常用的加解密有:RSA、ECC、DSA,在java中使用最多的是RSA
工具类
/**
* 非对称加解密工具类(RSA)
*
* RSA加密(一次)有最大字节数组限制 177、解密的最大字符限制128
*
*
*/
public class AsymmetricEncryptDecryptionUtil {
public static final String UTF8= StandardCharsets.UTF_8.name();
public static final String ALGORITHM = "RSA";
public static final int MAX_ENC_LENGTH = 117;
public static final int MAX_DEN_LENGTH = 128;
/**
* 创建公钥和私钥对的16进制字符串
*
* @throws NoSuchAlgorithmException 算法异常
* @throws IOException io异常
*/
public static void createKeyPair() throws NoSuchAlgorithmException, IOException {
KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
pairGenerator.initialize(1024);
KeyPair keyPair = pairGenerator.genKeyPair();
// 公钥
PublicKey publicKey = keyPair.getPublic();
// 私钥
PrivateKey privateKey = keyPair.getPrivate();
// 公钥秘钥字节数组
byte[] publicKeyPairEncoded = publicKey.getEncoded();
// 私钥秘钥字节数组
byte[] privateKeyEncoded = privateKey.getEncoded();
String pubHexStr = Hex.encodeHexString(publicKeyPairEncoded);
String priHexStr = Hex.encodeHexString(privateKeyEncoded);
System.out.println("公钥是:" + pubHexStr);
System.out.println("私钥是:" + priHexStr);
}
private static PublicKey getPublicKey() throws Exception {
String pubCfFile = AsymmetricEncryptDecryptionUtil.class.getClassLoader().getResource("rsa.pub").getPath();
String pubKeyHexStr = FileUtils.readFileToString(new File(pubCfFile), UTF8);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Hex.decodeHex(pubKeyHexStr));
return keyFactory.generatePublic(x509EncodedKeySpec);
}
private static PrivateKey getPrivateKey() throws Exception {
String priCfFile = AsymmetricEncryptDecryptionUtil.class.getClassLoader().getResource("rsa.pri").getPath();
String priKeyHexStr = FileUtils.readFileToString(new File(priCfFile), UTF8);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Hex.decodeHex(priKeyHexStr));
return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
}
public static String encodeStr(String originalStr,Key key) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE,key);
byte[] bytes = doCodec(cipher, originalStr.getBytes(UTF8), MAX_ENC_LENGTH);
return Hex.encodeHexString(bytes);
}
public static String deCodeStr(String hexStr,Key key) throws Exception {
byte[] bytes = Hex.decodeHex(hexStr);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,key);
byte[] originalBytes = doCodec(cipher,bytes,MAX_DEN_LENGTH);
return new String(originalBytes,UTF8);
}
/**
* 由于RSA加密、解密都有最大字节数组长度限制(加密是177长度,解密是128长度)
*
* 所以需要循环处理
*
* @param cipher cipher
* @param bytes 待加解密的字节数组
* @param maxLength 处理的最大长度
* @return 加解密的字节数组
* @throws BadPaddingException BadPaddingException
* @throws IllegalBlockSizeException IllegalBlockSizeException
*/
private static byte[] doCodec(Cipher cipher,byte[] bytes,int maxLength) throws BadPaddingException, IllegalBlockSizeException {
int length = bytes.length;
int offset = 0;
byte[] cache;
int i = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((length - offset) > 0) {
if(length - offset > maxLength) {
cache = cipher.doFinal(bytes,offset,maxLength);
} else {
cache = cipher.doFinal(bytes,offset,length - offset);
}
i++;
offset = i * maxLength;
bos.write(cache,0,cache.length);
}
return bos.toByteArray();
}
public static void main(String[] args) throws Exception {
String str = "法律";
PublicKey publicKey = getPublicKey();
String s = encodeStr(str, publicKey);
System.out.println("RSA encode result:" + s);
PrivateKey privateKey = getPrivateKey();
String s1 = deCodeStr(s,privateKey);
System.out.println("RSA decode result:" + s1);
}
}
注意:RSA加解密有限制,一次加密的最大字节数组不能超过177长度,解密的最大数组长度不能超过128个字节长度