功能解密throws javax.crypto.BadPaddingException:pad块在Android中的类SimpleCrypto中被破坏 [英] function decrypt throws javax.crypto.BadPaddingException: pad block corrupted in class SimpleCrypto in android

查看:5047
本文介绍了功能解密throws javax.crypto.BadPaddingException:pad块在Android中的类SimpleCrypto中被破坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个解密文件中存储的一些文本的Android应用程序。我使用以下代码 -

  public class SimpleCrypto {
public static String encrypt(String seed,String cleartext)
throws Exception {
byte [] rawKey = getRawKey(seed.getBytes());
byte [] result = encrypt(rawKey,cleartext.getBytes());
return toHex(result);
}

public static String decrypt(String seed,String encrypted)
throws异常{
byte [] rawKey = getRawKey(seed.getBytes());
byte [] enc = toByte(encrypted);
byte [] result = decrypt(rawKey,enc);
return new String(result);
}

private static byte [] getRawKey(byte [] seed)throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance(AES);
SecureRandom sr = SecureRandom.getInstance(SHA1PRNG,Crypto);
sr.setSeed(seed);
kgen.init(128,sr); // 192和256位可能不可用
SecretKey skey = kgen.generateKey();
byte [] raw = skey.getEncoded();
返回原始;
}

private static byte [] encrypt(byte [] raw,byte [] clear)throws异常{
SecretKeySpec skeySpec = new SecretKeySpec(raw,AES);
密码密码= Cipher.getInstance(AES);
cipher.init(Cipher.ENCRYPT_MODE,skeySpec);
byte [] encrypted = cipher.doFinal(clear);
返回加密;
}

private static byte [] decrypt(byte [] raw,byte [] encrypted)
throws异常{
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
密码密码= Cipher.getInstance(AES);
cipher.init(Cipher.DECRYPT_MODE,skeySpec);
byte [] decryptpted = cipher.doFinal(encrypted); //这是抛出错误的行
返回解密;
}

public static String toHex(String txt){
return toHex(txt.getBytes());
}

public static String fromHex(String hex){
return new String(toByte(hex));
}

public static byte [] toByte(String hexString){
int len = hexString.length()/ 2;
byte [] result = new byte [len]; (int i = 0; i result [i] = Integer.valueOf(hexString.substring(2 * i,2 * i + 2),
16).byteValue();
返回结果;
}

public static String toHex(byte [] buf){
if(buf == null)
return;
StringBuffer result = new StringBuffer(2 * buf.length); (int i = 0; i< buf.length; i ++){
appendHex(result,buf [i]);

}
return result.toString();
}

private final static String HEX =0123456789ABCDEF;

private static void appendHex(StringBuffer sb,byte b){
sb.append(HEX.charAt((b>> 4)& 0x0f))。 charAt(b& 0x0f));
}

}

编辑:这是文本我正在尝试解密 -

  39D4CA73AAF2D42C32659FDC5D1848EA 

使用此键 -

  thebestsecret153 

如果这有帮助。它应该在153中显示



编辑:在android中抛出错误的行。 -

  byte [] decryptpted = cipher.doFinal(encrypted); 

我还创建了一个摆动的项目,从文件中读取并收到以下错误 -

  javax.crypto.BadPaddingException:给定最终块未正确填充
在com.sun.crypto.provider.CipherCore.doFinal( CipherCore.java:811)
在com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
在com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java: 676)
在com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
在javax.crypto.Cipher.doFinal(Cipher.java:2087)
在解密.devpt.decrypt(Decrypt.java:43)
在在解密.MainForm $ 1.mouseClicked(MainForm.java:46)
在java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:270)
在java.awt.Component.processMouseEvent(Component.java: 6508)
在javax.swin (java.awt.Component.processEvent(Component.java:6270))

在java.awt.Component.dispatchEventImpl(Component.java:4861)
在java.awt.Container.dispatchEventImpl(Container.java:2287)
在java.awt.Component.dispatchEvent (Component.java:4687)
在java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
在java.awt.LightweightDispatcher.processMouseEvent(Container.java:4501)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
在java.awt.Container.dispatchEventImpl(Container.java:2273)
在java.awt.Window.dispatchEventImpl(Window.java: 2719)
在java.awt.Component.dispatchEvent(Component.java:4687)
在java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
在java.awt.EventQueue .access $ 200(EventQueue.java:103)
在java.awt.EventQueue $ 3 .run(EventQueue.java:694)
java.awt.EventQueue $ 3.run(EventQueue.java:692)
java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76)
在java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:87)
在java.awt.EventQueue $ 4.run(EventQueue java.security.AccessController.doPrivileged(Native Method)
java.security中的
ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76)
在java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
在java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
在java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
在java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
在java.awt.Eve ntDispatchThread.pumpEvents(EventDispatchThread.java:146)
在java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
在java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
线程中的异常AWT-EventQueue-0java.lang.NullPointerException
在java.lang.String。< init>(String.java:556)
在decrypt.MainForm.jButton1MouseClicked MainForm.java:91)
在decrypt.MainForm.access $ 000(MainForm.java:20)
在decrypt.MainForm $ 1.mouseClicked(MainForm.java:46)
在java.awt .AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:270)
java.awt.Component.processMouseEvent(Component.java:6508)
javax.swing.JComponent.processMouseEvent(JComponent.java:3320)
在java.awt.Component.processEvent(Component.java:6270)
在java.awt.Container.processEvent(Container.java:2229)
在java.awt.Component.dispatchEventImpl( Component.java:4861)
在java.awt.Container.disp atchEventImpl(Container.java:2287)
在java.awt.Component.dispatchEvent(Component.java:4687)
在java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
在java.awt.LightweightDispatcher.processMouseEvent(Container.java:4501)
在java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
在java.awt.Container.dispatchEventImpl(Container.java :2273)
在java.awt.Window.dispatchEventImpl(Window.java:2719)
在java.awt.Component.dispatchEvent(Component.java:4687)
在java.awt。 EventQueue.dispatchEventImpl(EventQueue.java:735)
在java.awt.EventQueue.access $ 200(EventQueue.java:103)
在java.awt.EventQueue $ 3.run(EventQueue.java:694)
在java.awt.EventQueue $ 3.run(EventQueue.java:692)
在java.security.AccessController.doPrivileged(本机方法)
在java.security.ProtectionDomain $ 1.doIntersectionPrivilege( ProtectionDomain.java:76)
在java.security.ProtectionD omain $ 1.doIntersectionPrivilege(ProtectionDomain.java:87)
在java.awt.EventQueue $ 4.run(EventQueue.java:708)
在java.awt.EventQueue $ 4.run(EventQueue.java:706 )
在java.security.AccessController.doPrivileged(本机方法)
在java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76)
在java.awt.EventQueue.dispatchEvent( EventQueue.java:705)
在java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
在java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
在java .awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
在java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
在java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138 )
在java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

它工作完美如果加密和dec在同一程序中完成。



任何帮助都不胜感激。感谢提前。

解决方案

TL; DR: SecureRandom.getInstance(SHA1PRNG)




p>你已经走进了一个人认为伪随机数生成器(PRNG)与密钥导出函数(KDF)相同的陷阱。一般来说,它们相当接近运行。唯一的问题是,通过(一些实现的)Android的加密提供程序实现, setSeed 方法将种子添加到随机内,即使是第一个电话。所以你每次都会生成一个不同的键。不同的密钥意味着可能永远不会被解密的随机密文。



随机密文意味着填充很可能是不正确的,因为ECB或CBC使用错误的密钥解密仍然返回明文 - 它只是随机的,就像密文一样。随机纯文本中的非加载例程可能失败,因此解密将失败并带有填充异常。请注意,如果使用错误的密钥,那么认证密码(如GCM模式加密)将另一方面总是失败。



解决方案:使用或者使用内置的PBKDF2功能从密码(和盐)中导出密钥。您可以查看如何执行此操作的示例此处






使用SecureRandom进行关键派生功能的问题:




  • SecureRandom 算法可能(并且)在每个提供者/运行时不同;

  • SecureRandom 实现可能会有所不同提供者/运行时;

  • SecureRandom 实现可能会在首次调用 SecureRandom时添加或替换种子;



最后一些提供者返回一个完全不同的随机数生成器,当SHA1PRNG 被使用,默认情况下许多人似乎都这样做。当创建一个随机数生成器时,只需使用新的SecureRandom ,并记住SHA1PRNG不表示特定的算法。



与提供者相关的意思是加密服务提供商,如Java加密体系结构JCA所述;即 java.security.Provider


I am writing an android app that decrypts some text stored in a file. I used the following code -

public class SimpleCrypto {
    public static String encrypt(String seed, String cleartext)
            throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] result = encrypt(rawKey, cleartext.getBytes());
        return toHex(result);
    }

    public static String decrypt(String seed, String encrypted)
            throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
        sr.setSeed(seed);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;
    }

    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    private static byte[] decrypt(byte[] raw, byte[] encrypted)
            throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encrypted);//this is the line that throws error
        return decrypted;
    }

    public static String toHex(String txt) {
        return toHex(txt.getBytes());
    }

    public static String fromHex(String hex) {
        return new String(toByte(hex));
    }

    public static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
                    16).byteValue();
        return result;
    }

    public static String toHex(byte[] buf) {
        if (buf == null)
            return "";
        StringBuffer result = new StringBuffer(2 * buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }

    private final static String HEX = "0123456789ABCDEF";

    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
    }

}

EDIT: This is the text that I am trying to decrypt -

39D4CA73AAF2D42C32659FDC5D1848EA

with this key -

thebestsecret153

if that helps. it should show in153.

EDIT: The line that throws the error in android. -

byte[] decrypted = cipher.doFinal(encrypted);

I also created a project in swing to read from a file and got the following error -

javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
    at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    at decrypt.Decrypt.decrypt(Decrypt.java:43)
    at decrypt.MainForm.jButton1MouseClicked(MainForm.java:91)
    at decrypt.MainForm.access$000(MainForm.java:20)
    at decrypt.MainForm$1.mouseClicked(MainForm.java:46)
    at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:270)
    at java.awt.Component.processMouseEvent(Component.java:6508)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3320)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4501)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:708)
    at java.awt.EventQueue$4.run(EventQueue.java:706)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at java.lang.String.<init>(String.java:556)
    at decrypt.MainForm.jButton1MouseClicked(MainForm.java:91)
    at decrypt.MainForm.access$000(MainForm.java:20)
    at decrypt.MainForm$1.mouseClicked(MainForm.java:46)
    at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:270)
    at java.awt.Component.processMouseEvent(Component.java:6508)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3320)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4501)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:708)
    at java.awt.EventQueue$4.run(EventQueue.java:706)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

It works perfectly if encryption and decryption is done in same program.

Any help is appreciated. Thanks in advance.

解决方案

TL;DR: SecureRandom.getInstance("SHA1PRNG") may not always return the same results even when seeded with the same seed.


You have walked in the trap set up by some person that thought a Pseudo Random Number Generator (PRNG) is the same thing as a Key Derivation Function (KDF). And in general, they are pretty close in operation. The only problem is that with (some implementations of) Android's crypto provider implementation, the setSeed method adds the seed to the random, even when it is the first call. So you will generate a different key each time. Different keys mean random ciphertext that may never be decrypted.

Random ciphertext means that the padding is very likely to be incorrect as ECB or CBC decryption with the wrong key still returns plaintext - it's just random just like the ciphertext. The unpadding routine is likely to fail on randomized plaintext, so the decryption will fail with a padding exception. Note that authenticated ciphers such as GCM mode encryption will on the other hand always fail if the wrong key is used.

The solution: use a true random AES key, or use the build-in PBKDF2 functionality to derive a key from a password (and salt). You can view an examples of how to do this here.


Issues with using SecureRandom for key derivation functions:

  • the SecureRandom algorithm may (and does) differ per provider/runtime;
  • the SecureRandom implementation may differ per provider/runtime;
  • the SecureRandom implementation may either add or replace the seed during the first call of SecureRandom;

Finally some providers return a completely different random number generator when "SHA1PRNG" is used as many people seem to do this by default. When creating a random number generator simply use new SecureRandom instead and remember that "SHA1PRNG" does not denote a specific algorithm.

With provider I mean a cryptographic service provider as explained in the Java Cryptography Architecture, JCA; i.e. a java.security.Provider.

这篇关于功能解密throws javax.crypto.BadPaddingException:pad块在Android中的类SimpleCrypto中被破坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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