AES工具類加解密麦备,在windows環(huán)境下可以正常加解密(之前部署到linux服務(wù)器上也沒有出現(xiàn)問題)孽椰,但是在mac環(huán)境下解密時出現(xiàn)以下問題
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:989)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:845)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
整個工具類代碼如下
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class AESUtils {
public static String encryptStr(String content, String password) {
return ParseHexUtils.parseByte2HexStr(encrypt(content,password));
}
public static byte[] encrypt(String content, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 創(chuàng)建AES的Key生產(chǎn)者
/*SecureRandom random=SecureRandom.getInstance("SHA1PRNG");
random.setSeed(password.getBytes());
kgen.init(128, random);*/
kgen.init(128, new SecureRandom(password.getBytes()));// 利用用戶密碼作為隨機數(shù)初始化出
SecretKey secretKey = kgen.generateKey();// 根據(jù)用戶密碼,生成一個密鑰
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本編碼格式的密鑰泥兰,如果此密鑰不支持編碼弄屡,則返回
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 轉(zhuǎn)換為AES專用密鑰
Cipher cipher = Cipher.getInstance("AES");// 創(chuàng)建密碼器
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化為加密模式的密碼器
byte[] result = cipher.doFinal(byteContent);// 加密
return result;
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public static String decryptStr(String content, String password){
try {
return new String(decrypt(ParseHexUtils.parseHexStr2Byte(content),password),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public static byte[] decrypt(byte[] content, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 創(chuàng)建AES的Key生產(chǎn)者
/*SecureRandom random=SecureRandom.getInstance("SHA1PRNG");
random.setSeed(password.getBytes());
kgen.init(128, random);*/
kgen.init(128, new SecureRandom(password.getBytes()));
SecretKey secretKey = kgen.generateKey();// 根據(jù)用戶密碼,生成一個密鑰
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本編碼格式的密鑰
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 轉(zhuǎn)換為AES專用密鑰
Cipher cipher = Cipher.getInstance("AES");// 創(chuàng)建密碼器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化為解密模式的密碼器
byte[] result = cipher.doFinal(content);
return result; // 明文
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
}
}
最后的解決辦法就是把上述代碼中加密解密方法中的多行注釋的部分放開鞋诗,再把下方的kegen.init(...)這行注釋掉即可
原因:
簡單看了一下源碼SecureRandom的源碼膀捷,沒有得到很好的結(jié)論,個人覺得大概是環(huán)境的問題削彬,沒有調(diào)用setSeed()方法的時候全庸,直接new SecureRandom(...)調(diào)用了它的默認方式生成秘鑰,而調(diào)用了setSeed()方法,指定了它的秘鑰生成方式
注:在此過程中融痛,曾嘗試修改jdk中jre目錄下的java.security文件中屬性且沒有恢復(fù)默認壶笼,具體路徑為
/Users/.../Documents/jdk1.8.0_201.jdk/Contents/Home/jre/lib/security/java.security
修改了文件中
securerandom.source=file:/dev/random屬性為securerandom.source=file:/dev/./urandom