收藏
回答

微信小程序解密偶发性的 "填充无效,无法被移除"

框架类型 问题类型 API/组件名称 终端类型 微信版本 基础库版本
小程序 Bug AES解密 客户端 最新版本 最新版本

C#基础代码片段:

private static byte[] AES_decrypt(string input, string iv, string key)
        {
            RijndaelManaged aes = new RijndaelManaged();
            aes.KeySize = 256;
            aes.BlockSize = 128;
            aes.Mode = CipherMode.CBC;
            aes.Padding =  PaddingMode.PKCS7;
            aes.Key = Convert.FromBase64String(key);
            aes.IV = Convert.FromBase64String(iv);
            var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
            byte[] xBuff = null;
            using (var ms = new MemoryStream())
            {
                using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
                {
                    byte[] xXml = Convert.FromBase64String(input);
                     byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
                     Array.Copy(xXml, msg, xXml.Length);
                    cs.Write(xXml, 0, xXml.Length);
                }
                xBuff = decode2(ms.ToArray());
               
            }
            return xBuff;
        }       

 private static byte[] decode2(byte[] decrypted)
        {
            int pad = (int)decrypted[decrypted.Length - 1];
            if (pad < 1 || pad > 32)
            {
                pad = 0;
            }
            byte[] res = new byte[decrypted.Length - pad];
            Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
            return res;
        }


错误日志:

ExecptionMessage:Padding is invalid and cannot be removed.

mscorlib

   at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)

   at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)

   at System.Security.Cryptography.CryptoStream.FlushFinalBlock()

   at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)

   at System.IO.Stream.Close()

   at System.IO.Stream.Dispose()

   at Senparc.Weixin.WxOpen.Helpers.EncryptHelper.AES_Decrypt(String Input, Byte[] Iv, Byte[] Key)

   at Senparc.Weixin.WxOpen.Helpers.EncryptHelper.DecodeEncryptedData(String sessionKey, String encryptedData, String iv)


加密数据:

sessionKey:98195476102492321891401391061935624977242;IV:116115241129461711788323441202601974169239;

encryptedData:deWfUALVVTxrux2cp0qeqLWotTHTIpRmIrpcuWoh3ngyr7vjCDYq1wh2Q0CE6Zj9P/V2ZVqtjkVAiGdBuBR8fSs9qpWhb9ieO5FoumuvgoM6HP5+7Eul6lm8njXJlbTZr+pODAIeMoBIwpQUPpCLwYtpSuKlQGKvsrmoVU5j5xgoKm4dyKmNwq3qcqE5Q+HUOV0r/c7GusFWZD0haaccduMjmKAyupCpbwdDu6kiVfEo1pVZdp5j4C5ihrZdE7gzeS9vOAFDaB+NXPB6Lz+H8js6BH8gVJ7tZ1KUAwqt+FIqHHBKsREKoyjePwREkRc1Sr/N+QR1vps2cFGpqp16NAoTyT/JFi2jNs8PgrrEYZkjVvyMUYFlDnq5BWNyyh5RX34JEq7EN62sc+wfAMB2Nrm/QEcBCtYLycP3xcQnCLasU2SQbpIr5GOUz7aiIu5rwMXMUDDg7jxCOA4+ORfSHUgS6OczRjY+QqrcfKmlA84=


回答关注问题邀请回答
收藏

6 个回答

  • Jimmy
    Jimmy
    2020-11-13

    我也一样遇到这个问题,checkSession是进行了本地存储的,每次调用之前,也进行了checkSession操作,但还是这样,那就说明Session_key已经失效了,但是checkSession并没有检查出来;我就执行这样的操作:

    1、从本地缓存获取Session_key;

    2、用checkSession方法检查Session_key是否失效;

    3、把sessionkey、encryptedData、iv传回接口进行解密,成功了就不进行任何操作;

    4、失败了则执行wx.login,重新获得Session_key再来解析(做好次数限制,防止死循环)

    2020-11-13
    有用
    回复
  • 上善若水
    上善若水
    2020-06-04

    解决问题,填充无效,无法被移除

    var rgbKey = Convert.FromBase64String(AesKey);

                    var rgbIV = Convert.FromBase64String(AesIV);


                    RijndaelManaged rijndael = new RijndaelManaged();

                    ICryptoTransform transform = rijndael.CreateDecryptor(rgbKey, rgbIV);

                    byte[] bCipherText = Convert.FromBase64String(inputdata);//这里要用这个函数来正确转换Base64字符串成Byte数组

                    MemoryStream ms = new MemoryStream(bCipherText);

                    CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read);

                    byte[] bPlainText = new byte[bCipherText.Length];

                    cs.Read(bPlainText, 0, bPlainText.Length);

                    return Encoding.UTF8.GetString(bPlainText);

    2020-06-04
    有用
    回复
  • Microestc ® ZngL
    Microestc ® ZngL
    2019-11-10

    已经找到根源了,详情去看我博客吧 微信小程序加密解密 C# 以及 填充无效,无法被移除错误的解决方案 Padding is invalid and cannot be removed

    2019-11-10
    有用
    回复
  • &z
    &z
    2019-10-19

    确保调用顺序为:先登录拿到code换取sessionkey,然拿到用户授权信息,进行解密,一定要注意sessionkey和encryptedData,iv是同时变化的

    2019-10-19
    有用
    回复
  • 平平淡淡
    平平淡淡
    2018-11-21

    我这边也遇到了这个问题,楼主解决了吗

    2018-11-21
    有用
    回复 6
    • 华茂
      华茂
      2019-06-12

      没有解决,你解决了吗

      2019-06-12
      回复
    • 李青松
      李青松
      2019-06-13

      老哥解决了吗?我的第一次授权不行,报错时候,在点一次可以,但是两次的数据一模一样

      2019-06-13
      回复
    • 华茂
      华茂
      2019-06-14回复李青松

      我也是这样的。一直没有解决呀

      2019-06-14
      回复
    • 李青松
      李青松
      2019-06-17回复华茂

      http://www.mamicode.com/info-detail-2431223.html

      2019-06-17
      回复
    • 李青松
      李青松
      2019-06-17回复华茂

      肯定不是C# 代码解析的问题。

      2019-06-17
      回复
    查看更多(1)
  • 半寸灰
    半寸灰
    2018-11-19

    一般是  session key  不对应 导致的


    会话密钥 session_key 有效性

    开发者如果遇到因为 session_key 不正确而校验签名失败或解密失败,请关注下面几个与 session_key 有关的注意事项。

    1. wx.login 调用时,用户的 session_key 可能会被更新而致使旧 session_key 失效(刷新机制存在最短周期,如果同一个用户短时间内多次调用 wx.login,并非每次调用都导致 session_key 刷新)。开发者应该在明确需要重新登录时才调用 wx.login,及时通过 code2Session 接口更新服务器存储的 session_key。

    2. 微信不会把 session_key 的有效期告知开发者。我们会根据用户使用小程序的行为对 session_key 进行续期。用户越频繁使用小程序,session_key 有效期越长。

    3. 开发者在 session_key 失效时,可以通过重新执行登录流程获取有效的 session_key。使用接口 wx.checkSession可以校验 session_key 是否有效,从而避免小程序反复执行登录流程。

    4. 当开发者在实现自定义登录态时,可以考虑以 session_key 有效期作为自身登录态有效期,也可以实现自定义的时效性策略。


    2018-11-19
    有用
    回复 4
    • 华茂
      华茂
      2018-11-19

      我在获取了sessionkey的第一时间然后就去验证的。所有sessionkey 也不至于过期。然后就是传入的sessionkey与获取的是一致的

      2018-11-19
      回复
    • 半寸灰
      半寸灰
      2018-11-19回复华茂

      session key不应该第一时间获取的

      总之  

      获取了加密数据后  不应该再wx.login  获取code再 获取 session key。

      session key应该保存再数据库什么的

      前端检查 登录是否有效再  更新   session key


      2018-11-19
      回复
    • 华茂
      华茂
      2018-11-19回复半寸灰

      现在刚开始开发的。所以只有一个登陆页面,也就通过该页面再开发调试这个问题。所以不存在重复登陆情况。唯一的就是重复的再测试该问题而已

      2018-11-19
      回复
    • &z
      &z
      2019-10-19
      确保调用顺序为:先登录拿到code换取sessionkey,然拿到用户授权信息,进行解密,一定要注意sessionkey和encryptedData,iv是同时变化的
      2019-10-19
      回复
登录 后发表内容