在javax.crypto中获取填充异常
我正在尝试编写一个加密java测试类,它使用BouncyCastle对字符串密码进行加密和解密。在javax.crypto中获取填充异常,java,cryptography,bouncycastle,Java,Cryptography,Bouncycastle,我正在尝试编写一个加密java测试类,它使用BouncyCastle对字符串密码进行加密和解密。main()非常简单,我先执行encryptPass(),然后执行decryptPass(),并查看控制台跟踪 问题是当它尝试解密时,我得到了一个填充异常: javax.crypto.BadPaddingException: pad block corrupted at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unk
main()
非常简单,我先执行encryptPass()
,然后执行decryptPass()
,并查看控制台跟踪
问题是当它尝试解密时,我得到了一个填充异常:
javax.crypto.BadPaddingException: pad block corrupted
at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at com.kiengi.crypto.Crypto.decryptPass(Crypto.java:79)
我的加密类代码如下所示:
// password to be crypted
public String pass = "password_go_here";
// key for encrypt pass
public String passKey = generateRandomKey(); // generation clef 16 caractere [a-zA-Z0-9]
// Encrypted pass
public String cryptedPass;
public final Logger logger = Logger.getLogger(this.getClass());
private final static byte[] IV_BYTES = new byte[] { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
0x00, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
public Crypto() {
super();
}
public void encryptPass(){
Security.addProvider(new BouncyCastleProvider());
IvParameterSpec _ivSpec = new IvParameterSpec(IV_BYTES);
try{
KeyGenerator _keygen = KeyGenerator.getInstance("AES");
_keygen.init(new SecureRandom(passKey.getBytes()));
SecretKey _key = _keygen.generateKey();
logger.trace("Secret key generated");
Cipher _cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
_cipher.init(Cipher.ENCRYPT_MODE, _key, _ivSpec);
cryptedPass = asHex(_cipher.doFinal(pass.getBytes("UTF-8")));
logger.trace("Encrypted pass : "+cryptedPass);
}catch (Exception e) {
logger.warn("encrypt failed");
e.printStackTrace();
}
}
public void decryptPass() {
byte[] _passKey = passKey.getBytes();
byte[] _cryptedPass = hexFromString(cryptedPass);
Security.addProvider(new BouncyCastleProvider());
IvParameterSpec _ivSpec = new IvParameterSpec(IV_BYTES);
try {
KeyGenerator _keygen = KeyGenerator.getInstance("AES");
_keygen.init(new SecureRandom(_passKey));
SecretKey _key = _keygen.generateKey();
logger.trace("Secret key generated");
Cipher _cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
_cipher.init(Cipher.DECRYPT_MODE, _key, _ivSpec);
String _pass = new String(_cipher.doFinal(_cryptedPass), "UTF-8");
logger.trace("Decrypted pass : "+_pass);
} catch (Exception e) {
logger.warn("decrypt failed");
e.printStackTrace();
}
}
private int fromDigit(char ch) {
if ((ch >= '0') && (ch <= '9')) {
return ch - '0';
} else if ((ch >= 'A') && (ch <= 'F')) {
return ch + 10 - 'A';
} else if ((ch >= 'a') && (ch <= 'f')) {
return ch + 10 - 'a';
} else {
throw new IllegalArgumentException(String.format(
"Invalid hex character 0x%04x", 0xff & ch));
}
}
private byte[] hexFromString(String hex) {
final byte[] buf = new byte[hex.length() / 2];
for (int i = 0, j = 0; i < hex.length(); i += 2) {
buf[j++] = (byte) (fromDigit(hex.charAt(i)) << 4 | fromDigit(hex
.charAt(i + 1)));
}
return buf;
}
private static String asHex(byte buf[]) {
final Formatter formatter = new Formatter(new StringBuffer());
for (int i = 0; i < buf.length; i++) {
formatter.format("%02x", 0xff & buf[i]);
}
return formatter.toString();
}
private String generateRandomKey() {
String _chars = "abcdefABCDEF1234567890";
StringBuffer _pass = new StringBuffer();
for (int x = 0; x < 32; x++) {
int i = (int) Math.floor(Math.random() * (_chars.length() - 1));
_pass.append(_chars.charAt(i));
}
return _pass.toString();
}
//要加密的密码
公共字符串pass=“password\u go\u here”;
//用于加密通行证的密钥
公共字符串passKey=generateRandomKey();//第16代谱号字符[a-zA-Z0-9]
//加密通行证
公共字符串密码传递;
public final Logger=Logger.getLogger(this.getClass());
私有最终静态字节[]IV_字节=新字节[]{0x07、0x06、0x05、0x04、0x03、0x02、0x01,
0x00、0x07、0x06、0x05、0x04、0x03、0x02、0x01、0x00};
公开密码{
超级();
}
公共密码(){
addProvider(新的BouncyCastleProvider());
IvParameterSpec _ivSpec=新的IvParameterSpec(IV_字节);
试一试{
KeyGenerator _keygen=KeyGenerator.getInstance(“AES”);
_init(新的SecureRandom(passKey.getBytes());
SecretKey _key=_keygen.generateKey();
logger.trace(“生成的密钥”);
Cipher\u Cipher=Cipher.getInstance(“AES/CBC/PKCS7Padding”,“BC”);
_cipher.init(cipher.ENCRYPT_MODE,_key,_ivSpec);
cryptedPass=asHex(_cipher.doFinal(pass.getBytes(“UTF-8”));
logger.trace(“加密过程:”+cryptedPass);
}捕获(例外e){
logger.warn(“加密失败”);
e、 printStackTrace();
}
}
公共通行证(){
字节[]_passKey=passKey.getBytes();
字节[]_cryptedPass=hexFromString(cryptedPass);
addProvider(新的BouncyCastleProvider());
IvParameterSpec _ivSpec=新的IvParameterSpec(IV_字节);
试试{
KeyGenerator _keygen=KeyGenerator.getInstance(“AES”);
_keygen.init(新的SecureRandom(_passKey));
SecretKey _key=_keygen.generateKey();
logger.trace(“生成的密钥”);
Cipher\u Cipher=Cipher.getInstance(“AES/CBC/PKCS7Padding”,“BC”);
_cipher.init(cipher.DECRYPT_模式,_密钥,_ivSpec);
字符串_pass=新字符串(_cipher.doFinal(_cryptedPass),“UTF-8”);
trace(“解密的过程:”+\u过程);
}捕获(例外e){
logger.warn(“解密失败”);
e、 printStackTrace();
}
}
私有int fromDigit(char ch){
如果((ch>='0')&&&(ch='A')&&(ch='A')&&(ch此代码有一个bug。它假定新的SecureRandom(passKey.getBytes())
将仅使用构造函数中提供的字节初始化SecureRandom实例。这是错误的。构造函数中的数据将补充SecureRandom使用的任何熵源,而不是替换它们
您需要使用正确的基于密码的加密(PBE)方案。此异常意味着填充块已损坏。您使用带有16B块的PKCS#7填充。在此示例中,您的输出也是16B。因此,始终应将其添加到具有16字节值0x10的块中。
填充已损坏,因为解密已损坏。您的SecureRandom实现添加了自己的熵并生成了错误的解密密钥。此SecureRandom构造函数使用已注册SecureRandom实现的第一个提供程序的第一个PRNG算法。捕获正确。是的,您需要对密码进行哈希运算rd的密钥长度将与加密算法配合使用(即使用SHA256(密码)作为AES 256密钥)。目前,您正在随机生成加密和解密密钥。