V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
autulin
V2EX  ›  Android

Android 的 Receiver 中使用 AES 解密会报错?请问有没有可用的方案?

  •  
  •   autulin · 2016-04-30 00:55:56 +08:00 · 7143 次点击
    这是一个创建于 2912 天前的主题,其中的信息可能已经有所发展或是发生改变。

    试过了在 Activity 中加密 /解密没有任何问题

    然而在 Reciever 中解密会出现 javax.crypto.BadPaddingException: pad block corrupted 的错误,用了几个网上的库也都不行

    第 1 条附言  ·  2016-04-30 13:51:22 +08:00
    加密解密方法我认为应该没有问题,因为在 Activity 中是正确的。

    关键问题应该是 Activity 中的加密解密环境跟 Receiver 中可能有什么不同?
    第 2 条附言  ·  2016-04-30 13:57:41 +08:00

    还是贴个加密解密代码吧

        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);
            return decrypted;
        }
    
        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;
        }
    
    10 条回复    2016-09-17 15:57:45 +08:00
    aWangami
        1
    aWangami  
       2016-04-30 01:00:28 +08:00
    代码呢?
    autulin
        2
    autulin  
    OP
       2016-04-30 01:14:04 +08:00
    @aWangami 代码就是网络上流传的通用的, github 上专门给 Android 封装的包也有,我看了下源代码也都差不多。问题关键是他们在 Receiver 里面都会出同样的问题,很奇怪,我明天准备试下用 JNI 看看
    limhiaoing
        3
    limhiaoing  
       2016-04-30 13:25:46 +08:00
    AES 有好几种工作模式,看这个异常我估计楼主解密用的是 ECB 或 CBC 。
    ECB 和 CBC 在加密的时候需要对数据进行填充,然后再解密后要移除加密时填充的数据。
    会出现这个异常我估计是,加密的时候没有填充,然后解密的时候尝试移除填充的时候,遇到了不正确的数据。
    AES 的填充主要有 3 种:
    1. NoPadding 不填充,要求带加密的数据大小刚好是 16 字节的整数倍;
    2. ZorePadding 不可靠;
    3. PKCS7Padding 。
    autulin
        4
    autulin  
    OP
       2016-04-30 13:48:41 +08:00
    @limhiaoing 看来这加密在理论上还是有好多学习的地方呢。
    不过我的问题的关键是,我在 Activity 中执行同样的加密解密方法是没有问题的,但是在 Receiver 中加密后传输到另外一个 Reciever 中解密就会报这个错。
    不过值得一提的是,生成密钥和加密我都是用的默认设置,没有仔细研究是否需要设置填充的情况,但是默认情况他们应该是用的同一种填充方式吧?在 Activity 中能够正常加密解密也能证明这一点
    我想这可能是 Android 本身的 bug 。
    现在我能想到的点就是加密解密是否跟 Context 有关,因为我出错的环境目前能推测的唯一不同点就是:我在同一个 Activity 中加密解密,这都是相当于在同一个 Context 中完成的;而我用这个 Receiver 加密,另外一个 Receiver 解密,他们应该是在不同的 Context 中的。
    autulin
        5
    autulin  
    OP
       2016-04-30 13:58:18 +08:00
    @aWangami 已在 Append 中贴出
    Lonely
        6
    Lonely  
       2016-04-30 15:40:23 +08:00
    @autulin 如果你是怀疑 context 的话,可以试试用 applicationContext
    special
        7
    special  
       2016-04-30 23:47:51 +08:00
    「但是在 Receiver 中加密后传输到另外一个 Reciever 中解密就会报这个错」

    传输前有没有做 base64 对二进制流编码,没有做的话会有失真,同样情况也适用于网络传输。
    autulin
        8
    autulin  
    OP
       2016-04-30 23:58:44 +08:00
    @special 没做 BASE64 ,做了转十六进制,并且调试看过变量,并没有失真的现象
    markkitty
        9
    markkitty  
       2016-08-26 22:31:08 +08:00 via Android
    楼主这个问题最后是怎么解决的?求告知
    autulin
        10
    autulin  
    OP
       2016-09-17 15:57:45 +08:00 via Android
    @markkitty 很傻的两边传错了 key
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3023 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 00:11 · PVG 08:11 · LAX 17:11 · JFK 20:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.