在javax.crypto中获取填充异常

在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

我正在尝试编写一个加密java测试类,它使用BouncyCastle对字符串密码进行加密和解密。
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密钥)。目前,您正在随机生成加密和解密密钥。