Dart中使用jose库解码收件人加密密钥时遇格式异常
问题诊断与修复
错误根源
你遇到的FormatException: Unexpected extension byte是解码方式错误导致的,和jose库无关:
encrypted_key是RSA加密后的二进制密文,不是符合UTF-8编码的文本字符串。用Utf8Decoder解码二进制密文必然触发编码格式错误——密文里的字节序列不符合UTF-8编码规则。- 代码里还存在逻辑错误:调用
decrypt时传入的是原始base64字符串recipientEncryptedKey,但RSA解密需要的是base64解码后的二进制字节数据。
修复后的代码
Future<String?> decryptMessage() async { JoseHeader joseHeader = JoseHeader.fromBase64EncodedString(token!); print('decoded token: $joseHeader'); try { List recipients = joseHeader['recipients']; var jaData = recipients[0]; try { // 收件人头部是JSON文本的base64编码,转UTF-8合理 var recipientHeader = const Utf8Decoder().convert(base64Decode(jaData['header'])); print('recipient_header: $recipientHeader'); var recipientEncryptedKey = jaData['encrypted_key']; print('encrypted_key: $recipientEncryptedKey'); // 直接解码成字节数组,跳过UTF-8转换步骤 var encryptedKeyBytes = base64Decode(recipientEncryptedKey); try { String privateKeyFromFile = await rootBundle.loadString('assets/keys/privateky.pem'); var privateKey = rsaSup.parsePrivateKeyFromPem(privateKeyFromFile); // 传入字节数组进行解密,而非base64字符串 Uint8List decryptedKeyBytes = decrypt(encryptedKeyBytes, privateKey); // 若解密结果是对称密钥类文本,再转UTF-8字符串 String decryptedStuff = const Utf8Decoder().convert(decryptedKeyBytes); print(decryptedStuff); } catch(e) { print(e); } } catch(e) { print(e); } } catch(e) { print(e); } }
额外注意事项
- 确认你的
decrypt函数接收Uint8List类型的密文数据,而非字符串。如果第三方库要求传字符串,也应该用base64编码后的原始字符串,而非尝试把二进制密文转成UTF-8字符串。 - JWE中的
encrypted_key、iv、ciphertext、tag都是二进制数据的base64编码,处理时需先解码成字节再进行加解密,不要直接转UTF-8(除非明确知道是文本内容)。
内容的提问来源于stack exchange,提问作者dave
相关产品推荐
相关产品推荐

