import 'dart:convert'; import 'dart:math'; import 'package:pointycastle/pointycastle.dart'; import 'package:pointycastle/key_derivators/pbkdf2.dart'; import 'package:pointycastle/digests/sha256.dart'; import 'package:pointycastle/macs/hmac.dart'; // 随机字符串 String randomString(int len) { if (len <= 0) { len = 16; } // 安全字符集(去掉Base64中的特殊字符 + / =) const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; final random = Random.secure(); final result = StringBuffer(); for (int i = 0; i < len; i++) { final index = random.nextInt(charset.length); result.write(charset[index]); } return result.toString(); } String randomStringEx(int len, { final bool includeLowercase = true, final bool includeUppercase = true, final bool includeDigits = true, final bool includeSpecialChars = true, final String? customCharset, }) { if (len <= 0) { len = 16; } String? charset; if (customCharset != null) { charset = customCharset; } else { final buffer = StringBuffer(); if (includeLowercase) buffer.write('abcdefghijklmnopqrstuvwxyz'); if (includeUppercase) buffer.write('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); if (includeDigits) buffer.write('0123456789'); if (includeSpecialChars) buffer.write('_-'); charset = buffer.toString(); } if (charset.isEmpty) { throw StateError('empty charset'); } final random = Random.secure(); final result = StringBuffer(); for (int i = 0; i < len; i++) { final index = random.nextInt(charset.length); result.write(charset[index]); } return result.toString(); } /// password to PBKDF2 password String passwordWithPBKDF2({ required String password, required String salt, int iterations = 100000, int keyLength = 32, }) { final seed = utf8.encode(password); final saltBytes = utf8.encode(salt); // 1. 初始化 PBKDF2 派生器(HMAC-SHA256 作为伪随机函数) final pbkdf2 = PBKDF2KeyDerivator( HMac(SHA256Digest(), 64), // HMAC-SHA256,64字节块大小 ); // 2. 设置参数:盐值 + 迭代次数 + 密钥长度(AES-256 需要 32 字节) final params = Pbkdf2Parameters( saltBytes, iterations, // 迭代次数(越高越安全,建议 10万+) keyLength, // 输出密钥长度(32字节 = 256位,适配 AES-256) ); pbkdf2.init(params); // 3. 派生密钥(返回 32 字节的 AES-256 密钥) final keyBytes = pbkdf2.process(seed); return base64Encode(keyBytes); } // // /// ---------- 使用 HMAC-SHA256 实现 PBKDF2 ---------- // /// // /// - [password]: 用户密码(UTF-8 编码后的字节) // /// - [salt]: 盐(建议随机生成) // /// - [iterations]: 迭代次数(如 10000) // /// - [keyLength]: 派生密钥长度(字节,如 32 = 256 位) // // String generatePasswordWithPBKDF2({ // required String password, // required String salt, // int iterations = 10000, // int keyLength = 32, // }) { // final key = base64.encode(pbkdf2HmacSha256( // password: utf8.encode(password), // salt: utf8.encode(salt), // iterations: iterations, // keyLength: keyLength, // )); // return key; // } // // Uint8List pbkdf2HmacSha256({ // required Uint8List password, // required Uint8List salt, // int iterations = 100000, // int keyLength = 32, // }) { // if (iterations < 1) throw ArgumentError('Iterations must be >= 1'); // if (keyLength <= 0) throw ArgumentError('Key length must be > 0'); // // final List derivedKey = []; // final int hLen = 32; // SHA-256 输出长度(字节) // final int l = (keyLength + hLen - 1) ~/ hLen; // 块数 // // for (int i = 1; i <= l; i++) { // // T_i = F(Password, Salt, Iterations, i) // final blockSalt = _concat(salt, _encodeInt(i)); // final Uint8List u = hmacSha256(password, blockSalt); // Uint8List t = u; // // for (int j = 1; j < iterations; j++) { // final Uint8List uNext = hmacSha256(password, u); // t = _xor(t, uNext); // u.setAll(0, uNext); // 更新 u 为 uNext // } // // derivedKey.addAll(t); // } // // return Uint8List.fromList(derivedKey.sublist(0, keyLength)); // } // // // HMAC-SHA256 辅助函数 // Uint8List hmacSha256(Uint8List key, Uint8List data) { // final hmac = Hmac(sha256, key); // final digest = hmac.convert(data); // return Uint8List.fromList(digest.bytes); // } // // // 将整数编码为大端 4 字节(符合 RFC 2898) // Uint8List _encodeInt(int i) { // return Uint8List.fromList([ // (i >> 24) & 0xFF, // (i >> 16) & 0xFF, // (i >> 8) & 0xFF, // i & 0xFF, // ]); // } // // // 拼接两个 Uint8List // Uint8List _concat(Uint8List a, Uint8List b) { // final result = Uint8List(a.length + b.length); // result.setAll(0, a); // result.setAll(a.length, b); // return result; // } // // // 按字节异或两个等长 Uint8List // Uint8List _xor(Uint8List a, Uint8List b) { // if (a.length != b.length) { // throw ArgumentError('XOR requires equal-length inputs'); // } // final result = Uint8List(a.length); // for (int i = 0; i < a.length; i++) { // result[i] = a[i] ^ b[i]; // } // return result; // }