keyUtils.dart 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import 'dart:convert';
  2. import 'dart:math';
  3. import 'package:pointycastle/pointycastle.dart';
  4. import 'package:pointycastle/key_derivators/pbkdf2.dart';
  5. import 'package:pointycastle/digests/sha256.dart';
  6. import 'package:pointycastle/macs/hmac.dart';
  7. // 随机字符串
  8. String randomString(int len) {
  9. if (len <= 0) {
  10. len = 16;
  11. }
  12. // 安全字符集(去掉Base64中的特殊字符 + / =)
  13. const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
  14. final random = Random.secure();
  15. final result = StringBuffer();
  16. for (int i = 0; i < len; i++) {
  17. final index = random.nextInt(charset.length);
  18. result.write(charset[index]);
  19. }
  20. return result.toString();
  21. }
  22. String randomStringEx(int len, {
  23. final bool includeLowercase = true,
  24. final bool includeUppercase = true,
  25. final bool includeDigits = true,
  26. final bool includeSpecialChars = true,
  27. final String? customCharset,
  28. }) {
  29. if (len <= 0) {
  30. len = 16;
  31. }
  32. String? charset;
  33. if (customCharset != null) {
  34. charset = customCharset;
  35. } else {
  36. final buffer = StringBuffer();
  37. if (includeLowercase) buffer.write('abcdefghijklmnopqrstuvwxyz');
  38. if (includeUppercase) buffer.write('ABCDEFGHIJKLMNOPQRSTUVWXYZ');
  39. if (includeDigits) buffer.write('0123456789');
  40. if (includeSpecialChars) buffer.write('_-');
  41. charset = buffer.toString();
  42. }
  43. if (charset.isEmpty) {
  44. throw StateError('empty charset');
  45. }
  46. final random = Random.secure();
  47. final result = StringBuffer();
  48. for (int i = 0; i < len; i++) {
  49. final index = random.nextInt(charset.length);
  50. result.write(charset[index]);
  51. }
  52. return result.toString();
  53. }
  54. /// password to PBKDF2 password
  55. String passwordWithPBKDF2({
  56. required String password,
  57. required String salt,
  58. int iterations = 100000,
  59. int keyLength = 32,
  60. }) {
  61. final seed = utf8.encode(password);
  62. final saltBytes = utf8.encode(salt);
  63. // 1. 初始化 PBKDF2 派生器(HMAC-SHA256 作为伪随机函数)
  64. final pbkdf2 = PBKDF2KeyDerivator(
  65. HMac(SHA256Digest(), 64), // HMAC-SHA256,64字节块大小
  66. );
  67. // 2. 设置参数:盐值 + 迭代次数 + 密钥长度(AES-256 需要 32 字节)
  68. final params = Pbkdf2Parameters(
  69. saltBytes,
  70. iterations, // 迭代次数(越高越安全,建议 10万+)
  71. keyLength, // 输出密钥长度(32字节 = 256位,适配 AES-256)
  72. );
  73. pbkdf2.init(params);
  74. // 3. 派生密钥(返回 32 字节的 AES-256 密钥)
  75. final keyBytes = pbkdf2.process(seed);
  76. return base64Encode(keyBytes);
  77. }
  78. //
  79. // /// ---------- 使用 HMAC-SHA256 实现 PBKDF2 ----------
  80. // ///
  81. // /// - [password]: 用户密码(UTF-8 编码后的字节)
  82. // /// - [salt]: 盐(建议随机生成)
  83. // /// - [iterations]: 迭代次数(如 10000)
  84. // /// - [keyLength]: 派生密钥长度(字节,如 32 = 256 位)
  85. //
  86. // String generatePasswordWithPBKDF2({
  87. // required String password,
  88. // required String salt,
  89. // int iterations = 10000,
  90. // int keyLength = 32,
  91. // }) {
  92. // final key = base64.encode(pbkdf2HmacSha256(
  93. // password: utf8.encode(password),
  94. // salt: utf8.encode(salt),
  95. // iterations: iterations,
  96. // keyLength: keyLength,
  97. // ));
  98. // return key;
  99. // }
  100. //
  101. // Uint8List pbkdf2HmacSha256({
  102. // required Uint8List password,
  103. // required Uint8List salt,
  104. // int iterations = 100000,
  105. // int keyLength = 32,
  106. // }) {
  107. // if (iterations < 1) throw ArgumentError('Iterations must be >= 1');
  108. // if (keyLength <= 0) throw ArgumentError('Key length must be > 0');
  109. //
  110. // final List<int> derivedKey = [];
  111. // final int hLen = 32; // SHA-256 输出长度(字节)
  112. // final int l = (keyLength + hLen - 1) ~/ hLen; // 块数
  113. //
  114. // for (int i = 1; i <= l; i++) {
  115. // // T_i = F(Password, Salt, Iterations, i)
  116. // final blockSalt = _concat(salt, _encodeInt(i));
  117. // final Uint8List u = hmacSha256(password, blockSalt);
  118. // Uint8List t = u;
  119. //
  120. // for (int j = 1; j < iterations; j++) {
  121. // final Uint8List uNext = hmacSha256(password, u);
  122. // t = _xor(t, uNext);
  123. // u.setAll(0, uNext); // 更新 u 为 uNext
  124. // }
  125. //
  126. // derivedKey.addAll(t);
  127. // }
  128. //
  129. // return Uint8List.fromList(derivedKey.sublist(0, keyLength));
  130. // }
  131. //
  132. // // HMAC-SHA256 辅助函数
  133. // Uint8List hmacSha256(Uint8List key, Uint8List data) {
  134. // final hmac = Hmac(sha256, key);
  135. // final digest = hmac.convert(data);
  136. // return Uint8List.fromList(digest.bytes);
  137. // }
  138. //
  139. // // 将整数编码为大端 4 字节(符合 RFC 2898)
  140. // Uint8List _encodeInt(int i) {
  141. // return Uint8List.fromList([
  142. // (i >> 24) & 0xFF,
  143. // (i >> 16) & 0xFF,
  144. // (i >> 8) & 0xFF,
  145. // i & 0xFF,
  146. // ]);
  147. // }
  148. //
  149. // // 拼接两个 Uint8List
  150. // Uint8List _concat(Uint8List a, Uint8List b) {
  151. // final result = Uint8List(a.length + b.length);
  152. // result.setAll(0, a);
  153. // result.setAll(a.length, b);
  154. // return result;
  155. // }
  156. //
  157. // // 按字节异或两个等长 Uint8List
  158. // Uint8List _xor(Uint8List a, Uint8List b) {
  159. // if (a.length != b.length) {
  160. // throw ArgumentError('XOR requires equal-length inputs');
  161. // }
  162. // final result = Uint8List(a.length);
  163. // for (int i = 0; i < a.length; i++) {
  164. // result[i] = a[i] ^ b[i];
  165. // }
  166. // return result;
  167. // }