【问题标题】:Android encryption "pad block corrupted" exceptionAndroid 加密“垫块损坏”异常
【发布时间】:2013-11-26 05:56:13
【问题描述】:

在这段代码中,这一行导致了一个异常:

clearText = c.doFinal(Base64.decode(encryptedText, Base64.DEFAULT));

javax.crypto.BadPaddingException: pad block corrupted

我的代码来自: http://www.techrepublic.com/blog/software-engineer/attention-android-developers-keep-user-data-safe/

有什么想法吗?

    private String decrypt (String encryptedText) {
        byte[] clearText = null;
        try {
            SecretKeySpec ks = new SecretKeySpec(getKey(), "AES");
            Cipher c = Cipher.getInstance("AES");
            c.init(Cipher.DECRYPT_MODE, ks);
            clearText = c.doFinal(Base64.decode(encryptedText, Base64.DEFAULT));
            return new String(clearText, "UTF-8");
        } catch (Exception e) {
            return null;
        }
    }

详细信息:我也在 android 上对其进行加密

【问题讨论】:

    标签: java android exception encryption aes


    【解决方案1】:

    owlstead 的建议很有帮助,但对于这种情况,在使用代码时

    Android 开发者注意:确保用户数据安全 http://www.techrepublic.com/blog/software-engineer/attention-android-developers-keep-user-data-safe/

    我对代码进行了一些更改,这些更改可能对未来的其他人有所帮助。我完全删除了getkey方法。

    private static String seed;
    
    /**
     * Encrypts the text. 
     * @param clearText The text you want to encrypt
     * @return Encrypted data if successful, or null if unsucessful
     */
    protected String encrypt(String clearText) {
        byte[] encryptedText = null;
        try {
            byte[] keyData = seed.getBytes();
            SecretKey ks = new SecretKeySpec(keyData, "AES");
            Cipher c = Cipher.getInstance("AES");
            c.init(Cipher.ENCRYPT_MODE, ks);
            encryptedText = c.doFinal(clearText.getBytes("UTF-8"));
            return Base64.encodeToString(encryptedText, Base64.DEFAULT);
        } catch (Exception e) {
            return null;
        }
    }
    
    /**
     * Decrypts the text
     * @param encryptedText The text you want to encrypt
     * @return Decrypted data if successful, or null if unsucessful
     */
    protected String decrypt (String encryptedText) {
        byte[] clearText = null;
        try {
            byte[] keyData = seed.getBytes();
            SecretKey ks = new SecretKeySpec(keyData, "AES");
            Cipher c = Cipher.getInstance("AES");
            c.init(Cipher.DECRYPT_MODE, ks);
            clearText = c.doFinal(Base64.decode(encryptedText, Base64.DEFAULT));
            return new String(clearText, "UTF-8");
        } catch (Exception e) {
            return null;
        }
    }   
    

    【讨论】:

    • 如果您不确定自己在做什么,则不应创建此类示例。例如,您仍在使用 AES ECB 模式,这是不安全的。您正在使用 getBytes() 而不指定编码。您正在使用一个字符串,就好像它是一个键一样。基本上,您已经解决了一个问题,但至少保留了三个其他问题。
    • 向社区 wiki 开放,以防您想修复您提到的问题。
    • 谢谢,但是我必须重写,最后我会得到类似于this answer 的代码。也许你想看看它,它还包含一些安全建议。
    • 如果我像上面那样使用没有 getKey 生成过程,它的抛出异常。 java.security.InvalidKeyException:密钥长度不是 128/192/256 位。
    【解决方案2】:

    Java + Android + Encryption + Exception 通常只意味着一件事,有人再次使用SecureRandom 类作为密钥派生函数。当"SHA1PRNG"SecureRandom 实现与Sun 在Java SE 中的实现不同时,这将失败。特别是如果将种子添加到随机数生成器的状态,而不是将种子用作 PRNG 的起点。

    基本上,只需使用 SecretKey aesKey = new SecretKeySpec(byte[] keyData, "AES") 代替,或者 - 如果您从密码开始 - 尝试使用 PBKDF2 生成密钥。

    【讨论】:

    • 链接中所说的方式不是更安全吗?如果这家伙花时间制作指南,它可能在他的机器上工作,但为什么不是我的?
    • byte[] keyData = "0123456789012345".getBytes(); SecretKey ks = new SecretKeySpec(keyData, "AES");我试过这个,它有效。 Buttt,由于现在它不会自动转换为128-192-256位,我必须手动输入,我想我需要添加一个自动转换的方法,有什么建议吗?
    • @Esq 没有标准化的方法可以通过添加零值来创建更小或更大的密钥,因为这显然会降低密钥提供的安全性。因此,要做到这一点,需要使用 KDF,如果您现在拥有的关键数据中有足够的熵,则可能是 KBKDF。如果数据少于 16 字节(对于 AES-128),那么您应该使用 PBKDF 来加强密钥。 PBKDF2 方法已由 Java 实现。 KBKDF 不存在,但它们相对容易从 HMAC 构建,例如你可以使用 HKDF。
    • 您也可以使用简单的 KDF,例如 KDF1。基本上,您将设置为零的四个字节附加到密钥种子,然后将OtherInfo 结构附加到该结构(例如,"ENC""MAC" 的ASCII 表示)。最后,您使用任何加密安全哈希对其进行哈希处理,例如SHA-256。然后使用最左边的字节作为 KDF 的输出。
    • 哦,我已将丢失的 KDF 添加到 Bouncy Castle。或者使用迭代计数为 1 的 PBKDF2 作为 KBKDF。
    【解决方案3】:

    对我来说,问题出在getKey()

    确保getKey() 的两次调用返回相同的值。

    我使用new SecureRandom(password.getBytes()) 生成密钥。它在 Windows 上工作,但在 Android 上,它为不同的调用返回不同的值。

    【讨论】:

    • 我也有同样的问题。我已经将用户密码加密到 SHA1PRNG 密钥的方法分开了,但是每次我调用该方法时,它都会生成许多不同的字符串。
    【解决方案4】:

    我引用了这个:https://androidfreetutorial.wordpress.com/2017/03/14/android-encryptiondecryption-with-aes-algorithm/

    从“AES/ECB/PKCS7Padding”改为“AES”;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 2014-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多