badPaddingException对doFinal的一些调用。不是全部。相同的输入 [英] badPaddingException on some call of the doFinal. Not all. Same input

查看:1044
本文介绍了badPaddingException对doFinal的一些调用。不是全部。相同的输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用javax.crypto.cipher加密和解密一些数据。
它运行良好。但有时,解密有一个badPaddingException。如果我将一个成功的调用与一个failling调用,给给密码的输入是相同的,并且密码以相同的方式初始化。



如何我instanciate我的密码

  dcipher = Cipher.getInstance(PBEWithMD5AndDES); 
KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(),salt,iterationCount);
SecretKey key = SecretKeyFactory.getInstance(PBEWithMD5AndDES)。generateSecret(keySpec);
dcipher.init(Cipher.DECRYPT_MODE,key,paramSpec);

我使用它的方式

  dec = Base64.decode(str); 
byte [] utf8 = dcipher.doFinal(dec);

doFinal引发异常。



任何想法?



谢谢!



哦,btw,我使用bouncyCastle作为提供者,它位于列表顶部

  Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider ; 

为了完整性,并且因为问题仍然不时出现。这里是完整的类。

  public class EncryptDecryptUtil {
/ **加密密码* /
private static Cipher ecipher;
/ **解密密码* /
私人静态密码解密;

private static Logger logger = Logger.getLogger(EncryptDecryptUtil.class);

/ **
*用于创建此对象的构造函数。负责设置和初始化此对象的加密器和
* decrypter密码实例给出一个秘密密钥和算法。
*
* @param key Secret Key用于初始化encrypter和decrypter实例。
* @param algorithm用于创建encrypter和decrypter实例的算法。
* /
public EncryptDecryptUtil(SecretKey key,String algorithm){
Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider(),1);
try {
ecipher = Cipher.getInstance(algorithm);
dcipher = Cipher.getInstance(algorithm);
ecipher.init(Cipher.ENCRYPT_MODE,key);
dcipher.init(Cipher.DECRYPT_MODE,key);
} catch(NoSuchPaddingException e){
System.out.println(EXCEPTION:NoSuchPaddingException);
} catch(NoSuchAlgorithmException e){
System.out.println(EXCEPTION:NoSuchAlgorithmException);
} catch(InvalidKeyException e){
System.out.println(EXCEPTION:InvalidKeyException);
}
}

/ **
*用于创建此对象的构造函数。负责设置和初始化此对象的加密器和
* decrypter密码实例给出一个Pass Phrase和算法。
*
* @param passPhrase Pass用于初始化encrypter和decrypter实例的短语。
* /
public EncryptDecryptUtil(String passPhrase){
Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider(),1);
// 8字节Salt
byte [] salt = {(字节)0xB9,(字节)0x8B,(字节)0xD8,(字节)0x31,(字节)0x55, (字节)0xF3,(字节)0x13};

//迭代计数
int iterationCount = 19;

try {
//生成与密码短语相关的密钥。
KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(),salt,iterationCount);
SecretKey key = SecretKeyFactory.getInstance(PBEWithMD5AndDES)。generateSecret(keySpec);

//获取密码实例
ecipher = Cipher.getInstance(PBEWithMD5AndDES);
dcipher = Cipher.getInstance(PBEWithMD5AndDES);

//准备参数到cipthers
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt,iterationCount);

ecipher.init(Cipher.ENCRYPT_MODE,key,paramSpec);
dcipher.init(Cipher.DECRYPT_MODE,key,paramSpec);

} catch(InvalidAlgorithmParameterException e){
logger.error(encrypter instantiation,e);
} catch(InvalidKeySpecException e){
logger.error(encrypter instantiation,e);
} catch(NoSuchPaddingException e){
logger.error(encrypter instantiation,e);
} catch(NoSuchAlgorithmException e){
logger.error(encrypter instantiation,e);
} catch(InvalidKeyException e){
logger.error(encrypter instantiation,e);
}
}

/ **
*将单个String作为参数,并返回该字符串的加密版本。
*
* @param str要加密的字符串
* @return< code> String< / code>加密的版本的字符串
* /
public String encrypt(String str){
try {
//使用utf-8将字符串编码为字节
byte [] utf8 = str.getBytes(UTF8);

//加密
byte [] enc = ecipher.doFinal(utf8);

//将字节编码为base64以获取字符串
return new String(Base64.encode(enc),UTF8);

} catch(BadPaddingException e){
logger.error(在加密期间:,e);
} catch(IllegalBlockSizeException e){
logger.error(在加密期间:,e);
} catch(UnsupportedEncodingException e){
logger.error(在加密期间:,e);
}
return new String();
}


/ **
*将加密的String作为参数,解密并返回解密的String。
*
* @param str要解密的加密字符串
* @return< code> String< / code>提供的字符串的解密版本
* /
public String decrypt(String str){
byte [] dec = new byte [0];
try {
//解码base64以获取字节。不知道为什么。
dec = Base64.decode(str);
//解密
byte [] utf8 = dcipher.doFinal(dec);
//使用utf-8解码
return new String(utf8,UTF8);解码的字符串是:+ str +要解码的字节数组是:+ Arrays.toString() dec),e);
} catch(IllegalBlockSizeException e){
logger.error(在解密期间:,e);
} catch(UnsupportedEncodingException e){
logger.error(在解密期间:,e);
}
return new String();
}
}

编辑
我想强调这2点:




  • 相同的输入有时会失败/有时被成功解密。 (我知道感谢BadPaddingException的日志)

  • 这个主要调用decrypt方法1 000 000 000次doest重现issus。



...

  for(int i = 0; i <1000000000; i ++){
EncryptDecryptUtil encryptDecript = new EncryptDecryptUtil(pass);
if(!YES.equals(encryptDecript.decrypt(Q3qWLKo6yJY =))){
System.out.println(Fail at call+ i);
throw new InvalidParameterException();
}
}

也许它可能来自我使用EncryptDecryptUtils类?它是一个Spring bean的领域,一次。

 解密时com.myStuff.dlm.cryptography.EncryptDecryptUtil错误。要解码的字符串是:Q3qWLKo6yJY =要解码的字节数组是:[114,52,-52,-54,82,87,124,84] 
javax.crypto.BadPaddingException:给定最后块未正确填充
at com.sun.crypto.provider.SunJCE_f.b(DashoA13 * ..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13 * ..)
at com.sun .crypto.provider.SunJCE_ab.b(DashoA13 * ..)
在com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineDoFinal(DashoA13 * ..)
在javax.crypto.Cipher.doFinal(DashoA13 * ..)
at com.dvidea.dlm.cryptography.EncryptDecryptUtil.decrypt(EncryptDecryptUtil.java:166)


<


$ b $ b

回答。


I use a javax.crypto.cipher for encrypt and decrypt some data. It's working well. But sometimes, the decryption faill with a badPaddingException. If i compare a succefull call with a failling call, the input given to the cipher are the same, and the cipher is initialised the same way.

that how i instanciate my cipher

dcipher = Cipher.getInstance("PBEWithMD5AndDES");
KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

That how i use it

dec = Base64.decode(str) ;
byte[] utf8 = dcipher.doFinal(dec);

The exception is raised on the doFinal.

Any idea ?

Thanks !

Oh, btw, i use bouncyCastle as a provider, and add it on top on the list with

Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider(), 1);

For the sake of the completeness, and because the problem still appeart from time to time. Here is the complete class.

public class EncryptDecryptUtil {
    /** Encryption Cipher */
    private static Cipher ecipher;
    /** Decription Cipher */
    private static Cipher dcipher;

    private static Logger logger = Logger.getLogger(EncryptDecryptUtil.class);

    /**
     * Constructor used to create this object. Responsible for setting and initializing this object's encrypter and
     * decrypter Cipher instances given a Secret Key and algorithm.
     * 
     * @param key Secret Key used to initialize both the encrypter and decrypter instances.
     * @param algorithm Which algorithm to use for creating the encrypter and decrypter instances.
     */
    public EncryptDecryptUtil(SecretKey key, String algorithm) {
        Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider(), 1);
        try {
            ecipher = Cipher.getInstance(algorithm);
            dcipher = Cipher.getInstance(algorithm);
            ecipher.init(Cipher.ENCRYPT_MODE, key);
            dcipher.init(Cipher.DECRYPT_MODE, key);
        } catch (NoSuchPaddingException e) {
            System.out.println("EXCEPTION: NoSuchPaddingException");
        } catch (NoSuchAlgorithmException e) {
            System.out.println("EXCEPTION: NoSuchAlgorithmException");
        } catch (InvalidKeyException e) {
            System.out.println("EXCEPTION: InvalidKeyException");
        }
    }

    /**
     * Constructor used to create this object. Responsible for setting and initializing this object's encrypter and
     * decrypter Chipher instances given a Pass Phrase and algorithm.
     * 
     * @param passPhrase Pass Phrase used to initialize both the encrypter and decrypter instances.
     */
    public EncryptDecryptUtil(String passPhrase) {
        Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider(), 1);
        // 8-bytes Salt
        byte[] salt = { (byte) 0xB9, (byte) 0x8B, (byte) 0xD8, (byte) 0x31, (byte) 0x55, (byte) 0x24, (byte) 0xF3, (byte) 0x13 };

        // Iteration count
        int iterationCount = 19;

        try {
            // Generate the secret key associated to the passphrase.
            KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
            SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);

            // Get instance of the cipher
            ecipher = Cipher.getInstance("PBEWithMD5AndDES");
            dcipher = Cipher.getInstance("PBEWithMD5AndDES");

            // Prepare the parameters to the cipthers
            AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);

            ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

        } catch (InvalidAlgorithmParameterException e) {
            logger.error("during encrypter instantiation",e);
        } catch (InvalidKeySpecException e) {
            logger.error("during encrypter instantiation",e);
        } catch (NoSuchPaddingException e) {
            logger.error("during encrypter instantiation",e);
        } catch (NoSuchAlgorithmException e) {
            logger.error("during encrypter instantiation",e);
        } catch (InvalidKeyException e) {
            logger.error("during encrypter instantiation",e);
        }
    }

    /**
     * Takes a single String as an argument and returns an Encrypted version of that String.
     * 
     * @param str String to be encrypted
     * @return <code>String</code> Encrypted version of the provided String
     */
    public String encrypt(String str) {
        try {
            // Encode the string into bytes using utf-8
            byte[] utf8 = str.getBytes("UTF8");

            // Encrypt
            byte[] enc = ecipher.doFinal(utf8);

            // Encode bytes to base64 to get a string
            return new String( Base64.encode(enc), "UTF8");

        } catch (BadPaddingException e) {
            logger.error("during encryption : ",e);
        } catch (IllegalBlockSizeException e) {
            logger.error("during encryption : ",e);
        } catch (UnsupportedEncodingException e) {
            logger.error("during encryption : ",e);
        } 
        return new String();
    }


    /**
     * Takes a encrypted String as an argument, decrypts and returns the decrypted String.
     * 
     * @param str Encrypted String to be decrypted
     * @return <code>String</code> Decrypted version of the provided String
     */
    public String decrypt(String str) {
        byte[] dec = new byte[0];
        try {
            // Decode base64 to get bytes. Not sure to understand why.
            dec = Base64.decode(str) ;
            // Decrypt
            byte[] utf8 = dcipher.doFinal(dec);
            // Decode using utf-8
            return new String(utf8, "UTF8");

        } catch (BadPaddingException e) {
            logger.error("error during decryption. String to decode was : "+str + " byte array to decode was : "+ Arrays.toString(dec) ,e);
        } catch (IllegalBlockSizeException e) {
            logger.error("during decryption : ",e);
        } catch (UnsupportedEncodingException e) {
            logger.error("during decryption : ",e);
        }  
        return new String();
    }
}

Edit : I would like to stress this 2 points :

  • the same input will sometime fail / sometime be sucessfully decrypted. ( i know that thanks to the logs in the BadPaddingException )
  • this main calling the decrypt method 1 000 000 000 times doest reproduce the issus.

...

for( int i = 0 ; i<1000000000 ; i++){
    EncryptDecryptUtil encryptDecript = new EncryptDecryptUtil("pass");
    if ( !"YES".equals(encryptDecript.decrypt("Q3qWLKo6yJY="))){
        System.out.println("Fail at call " + i);
        throw new InvalidParameterException() ;
    }
}

So maybe it could come from the way i use the EncryptDecryptUtils class ? It's a field of a Spring bean, instancied one time.

com.myStuff.dlm.cryptography.EncryptDecryptUtil  error during decryption. String to   decode was : Q3qWLKo6yJY= byte array to decode was : [114, 52, -52, -54, 82, 87, 124, 84]
javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_ab.b(DashoA13*..)
    at com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)
    at com.dvidea.dlm.cryptography.EncryptDecryptUtil.decrypt(EncryptDecryptUtil.java:166)

解决方案

Just an idea: Maybe you are jumping among different providers (Sun/BC/etc)

Regards.

这篇关于badPaddingException对doFinal的一些调用。不是全部。相同的输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆