使用 Crypto Js 密钥进行 Aes 算法令牌解密获取问题格式异常:flutter dart 中的无效字符(字符 1085)

问题描述 投票:0回答:1

下面是我使用 cryptoJsKey 的令牌解密代码, 这里的 cryptoText 是令牌,密码是 CryptoJsKey,

 static String decryptAES(String encryptedText, String password) {
    final keyBytes = Uint8List.fromList(utf8.encode(password));
    final iv = Uint8List(16);
    final cipher = BlockCipher("AES/CBC")..init(false, ParametersWithIV(KeyParameter(keyBytes), iv));

    final encryptedBytes = base64.decode(encryptedText);
    final decryptedBytes = decryptBytes(cipher, encryptedBytes);

    final decryptedText = utf8.decode(decryptedBytes);
    return decryptedText;
  }

static Uint8List decryptBytes(BlockCipher cipher, Uint8List input) {
    final blockSize = cipher.blockSize;
    final result = Uint8List(input.length);
    for (var i = 0; i < input.length; i += blockSize) {
      cipher.processBlock(input, i, result, i);
    }
    return removePadding(result);
  }

这里我成功解码了令牌,但是在令牌解码之后我得到了 另一个像这样的密文

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJc1N1cGVydmlzb3IiOiJGYWxzZSIsIklzQWdlbnQiOiJGYWxzZSIsIklzQWxsb3dlZEltcGVyc29uYXRlIjoiRmFsc2UiLCJEb21haW5Vc2VyIjoidHJ1ZSIsIkRvbWFpblVzZXJOYW1lIjoiSml0aGluLlBiIiwiRG9tYWluIjoiUVVBTEZPTkNFTlRFUiIsIkRlcGFydG1lbnRLZXkiOiJEUDE0NjAiLCJFbWFpbEFkZHJlc3MiOiJNb25hLkRhbmllbHNAcXVhbGZvbi5jb20iLCJEaXNwbGF5TmFtZSI6Ik1PTkEgREFOSUVMUyIsIlVzZXJJZCI6IjMzMDkzMCIsIkxvY2F0aW9uSWQiOiJSVVM0OCIsIkRpdmlzaW9uRGVwYXJ0bWVudENvbXBvc2l0ZUtleSI6IkRWMTIyOHxEUDE0NjAiLCJTdXBlcnZpc29yRXJwSWQiOiIzMzA5NjAiLCJTdXBlcnZpc29yTmFtZSI6Ik5FTFNPTiwgS0lOSVRBIiwiRGl2aXNpb25OYW1lIjoiT1BFUkFUSU9OUyBTVVBQT1JUIiwiQnVzaW5lc3NVbml0TmFtZSI6IkNVU1RPTUVSIEVOR0FHRU1FTlQgU09MVVRJT05TIiwiQnVzaW5lc3NVbml0SWQiOiJCVTExMiIsIlJlcG9ydGluZ0xvY2F0aW9uSWQiOiIxMDAwMSIsIlJlcG9ydGluZ0xvY2F0aW9uTmFtZSI6IlVTIC0gSElHSExBTkQgUEFSSyAoQ0VTKSIsIk1hbmFnaW5nVW5pdElkIjoiTVUxMTAiLCJNYW5hZ2luZ1VuaXQiOiJNQU5BR0lORyBVTklUIDAyIChFUklDIFJPVEhFUlQpIiwiTG9jYXRpb25OYW1lIjoiVVMgLSBNSUNISUdBTiwgUkVNT1RFIiwiUmVtb3RlRW1wbG95ZWUiOiIxIiwiSm9iVGl0bG

对于这个令牌,我使用一种转换方法

static String decodeJWT(String jwt) {
    final parts = jwt.split('.');
    if (parts.length != 3) {
      return 'Invalid JWT format';
    }
    final encodedPayload = parts[1];
    final missingPadding = 4 - (encodedPayload.length % 4);
    final paddedPayload = (missingPadding > 0) ? encodedPayload + '=' * missingPadding : encodedPayload;
    final decodedPayload = String.fromCharCodes(base64Url.decode(paddedPayload));
    print("payload $decodedPayload");
    return decodedPayload;
  }

在此转换中,我在这条线下遇到问题 最终解码的Payload = String.fromCharCodes(base64Url.decode(paddedPayload)); 错误消息就像 FormatException:无效字符(位于字符 1085) ...CISIm5iZiI6MTY5OTY1NDUxOSwiZXhwIjoxNzAwMDAwMTE5LCJpYXQiOjE2OTk2NTQ1MTl9====

flutter dart aes cryptojs pointycastle
1个回答
0
投票

您的算法存在某种问题。 Base64 编码的填充长度不应超过 2 个。您可以查看规范或代码参考示例来填充输入,但 dart 实际上提供了一种更简单的方法来使用

base64Url.normalize
函数来完成此操作。

这就是你如何使用它:

Uint8List base64UrlDecode(String inputBase64) {
  final normalized = base64Url.normalize(inputBase64);
  return base64Url.decode(normalized);
}

如果仍然出现错误,这可能意味着数据编码不正确,或者在某处出现了偏差为 1 的错误。


顺便说一句,除非您在解密AES 函数之外执行某些操作,否则您的代码看起来存在相当严重的安全漏洞。 AES/CBC 只能与 MAC 或哈希一起使用,否则很容易受到位翻转攻击。您可能会说,通过使用签名的 JWT 可以缓解这种情况,您可能是对的,但 JWE 中的最佳实践是验证整个包,无论是通过加密算法还是通过添加 mac。如果您可以控制服务器软件,一个简单的修复方法就是切换到 AES/GCM。但是,除非您是安全专家并且这只是一些非常未完成的代码,否则我认为您不应该编写自己的加密代码的格言可能适用于此。我建议考虑使用像 jose 这样的库,尽管如果您的代码在具有严格安全限制的地方使用,您可能应该拥有它以及由专业人员审查的任何库。

我还真心希望您不要使用函数中显示的明文密码作为加密密钥。密码作为加密密钥非常不安全,应始终首先使用安全密码算法进行哈希处理 - 不仅仅是简单的 SHA,而是诸如 argon2、PBKDF2、scrypt 或 bcrypt 之类的算法。如果您直接使用密码,除非您能保证密码始终是 128 位的非常随机的数据,否则基本上会使加密变得毫无价值。

© www.soinside.com 2019 - 2024. All rights reserved.