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

oug3syen  于 2023-11-14  发布在  Flutter
关注(0)|答案(1)|浏览(122)

下面是我用cryptoJsKey解密的令牌代码,这里的cryptedText是令牌,密码是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);
  }

字符串
在这里,我成功地解码令牌,但令牌解码后,我得到另一个这样的密文

*******JIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJc1N1cz***********


对于该令牌,iam使用转换方法

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;
  }


在此转换中,我在这行final decodedPayload = String.fromCharCodes(base64Url.decode(paddedPayload))下得到问题;错误消息类似于Exception:Invalid character(at character 1085). CIsIm 5iZiI 6 MTY 5 OTY 1 NDUxOSwiZXhwIjoxNzAwMDAWMTE 5LCJpYXQiOjE 2 OTk 2NTQ 1 MTl 9 =

yrdbyhpb

yrdbyhpb1#

你的算法有一些问题。Base64编码不应该有超过2个字符的填充。你可以去看看规范或参考代码示例来填充输入,但dart实际上提供了一个更简单的方法来使用base64Url.normalize函数。
这是你可以使用它的方式:

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

字符串
如果你仍然得到错误,这可能意味着数据的编码不正确,或者你在某个地方有一个偏离1的错误。
顺便说一句,你的代码看起来有一个相当严重的安全漏洞,除非你在decryptAES函数之外做了一些事情。AES/CBC应该只在MAC或哈希之外使用,否则它很容易受到位翻转攻击。你可能会说这是通过使用签名的JWT来缓解的,你可能是对的,但JWE中的最佳实践是通过加密算法或添加mac来验证整个包。如果您可以控制服务器软件,则简单的修复方法是切换到AES/GCM。然而,除非你是一个安全Maven,这只是一些非常未完成的代码,我认为你不应该写自己的密码的格言可能适用于这里。我建议考虑使用一个库,如jose,但是如果你的代码被用在有严格安全约束的地方,你可能应该让专业人员检查它和任何库。
我也非常希望你没有使用明文密码作为加密密钥,因为它出现在函数中。密码作为加密密钥是非常不安全的,应该首先使用安全的密码算法进行散列-不仅仅是简单的SHA,而是像argon 2,PBKDF 2,scrypt或bcrypt这样的算法。如果你直接使用密码,除非你能保证密码总是128位的随机数据,否则加密就毫无价值了。

相关问题