Dart中是否有类似crypto.subtle的工具?能否调用浏览器该API?
Dart中crypto.subtle替代方案与AES-CBC实现
一、访问浏览器原生crypto.subtle
在Dart Web环境中,可直接访问浏览器的crypto.subtle,你之前遇到的dart-html中Crypto.subtle不可访问的问题,大概率是用法有误。正确调用方式是通过window.crypto.subtle,示例代码如下:
import 'dart:html'; import 'dart:typed_data'; Future<Uint8List> cbcEncryptBrowser(Uint8List data, Uint8List iv, Uint8List key) async { // 导入密钥 final importedKey = await window.crypto.subtle.importKey( 'raw', key, {'name': 'AES-CBC'}, false, ['encrypt', 'decrypt'], ); // 加密数据 final cipherBuffer = await window.crypto.subtle.encrypt( {'name': 'AES-CBC', 'iv': iv}, importedKey, data, ); return Uint8List.view(cipherBuffer); }
注意:这段代码仅适用于Dart Web环境,无法在Flutter移动端或桌面端运行。
二、跨平台替代方案
1. cryptography包(推荐,API贴近web crypto)
你提到的cryptography包其实有直接对应AES-CBC的实现,以下是匹配你JS逻辑的代码:
import 'package:cryptography/cryptography.dart'; import 'dart:typed_data'; Future<Uint8List> cbcEncryptCryptography(Uint8List data, Uint8List iv, Uint8List key) async { final algorithm = AesCbc.with256bits(macAlgorithm: null); // 无需MAC,与JS逻辑对齐 final secretKey = await algorithm.newSecretKeyFromBytes(key); final encrypted = await algorithm.encrypt( data, secretKey: secretKey, nonce: iv, // AES-CBC中nonce等价于IV ); return encrypted.bytes; }
该包支持Web、Flutter移动端、桌面端,跨平台兼容性优异。
2. pointycastle包
pointycastle是Dart生态老牌加密库,功能全面,定位与crypto.subtle类似(底层加密实现),但API风格更偏向传统密码库。对应实现如下:
import 'package:pointycastle/pointycastle.dart'; import 'dart:typed_data'; Uint8List cbcEncryptPointyCastle(Uint8List data, Uint8List iv, Uint8List key) { final cipher = CBCBlockCipher(AESEngine()) ..init( true, // 加密模式 ParametersWithIV(KeyParameter(key), iv), ); // JS的crypto.subtle默认使用PKCS7补位,需手动实现 final paddedData = _addPkcs7Padding(data, 16); final output = Uint8List(paddedData.length); var offset = 0; while (offset < paddedData.length) { offset += cipher.processBlock(paddedData, offset, output, offset); } return output; } // PKCS7补位实现 Uint8List _addPkcs7Padding(Uint8List data, int blockSize) { final paddingLength = blockSize - (data.length % blockSize); final padding = Uint8List(paddingLength)..fillRange(0, paddingLength, paddingLength); return Uint8List.fromList([...data, ...padding]); }
三、总结
- 仅Web环境:直接用
window.crypto.subtle最贴合你的JS逻辑; - 跨平台需求:优先选择
cryptography包,API简洁且贴近web crypto;pointycastle功能更全面,但需手动处理补位等细节。
内容的提问来源于stack exchange,提问作者Bishwajeet Parhi
相关产品推荐
相关产品推荐

