150 lines
5.1 KiB
Dart
150 lines
5.1 KiB
Dart
import 'dart:async';
|
||
|
||
import 'dart:typed_data';
|
||
import 'package:convert/convert.dart';
|
||
// import 'package:fast_rsa/fast_rsa.dart' as fastRsa;
|
||
import 'package:flutter/services.dart';
|
||
import 'package:pointycastle/export.dart' as pc;
|
||
import 'dart:convert';
|
||
import 'package:asn1lib/asn1lib.dart' as asn1lib;
|
||
import 'package:star_lock/talk/starChart/exception/start_chart_message_exception.dart'; // Prefix for asn1lib
|
||
|
||
class DoSign {
|
||
// 生成签名sing
|
||
// Future<String> generateSign({
|
||
// required int currentTimestamp,
|
||
// required String privateKeyHex,
|
||
// }) async {
|
||
// String resultSign = '';
|
||
// try {
|
||
// // 1. 将 32 位时间戳以小端字节序编码为二进制数据
|
||
// Uint8List signData = encodeTimestampToLittleEndianBytes(currentTimestamp);
|
||
//
|
||
// // 2.将十六进制字符串转换为字节数组
|
||
// List<int> privateKeyBytes = hexToBytes(privateKeyHex);
|
||
//
|
||
// // 3.将私钥转换为 PEM 格式
|
||
// final pemPrivateKey =
|
||
// convertToPemPrivateKey(privateKeyBytes, isPKCS8: true);
|
||
// // 4.签名
|
||
// var result = await fastRsa.RSA
|
||
// .signPKCS1v15Bytes(signData, fastRsa.Hash.SHA256, pemPrivateKey);
|
||
// resultSign = hex.encode(result);
|
||
// } catch (e) {
|
||
// throw StartChartMessageException('❌--->上报信息生成签名时出现错误: $e');
|
||
// }
|
||
// return resultSign ?? '';
|
||
// }
|
||
|
||
Future<String> generateSign({
|
||
required int currentTimestamp,
|
||
required String privateKeyHex,
|
||
}) async {
|
||
String resultSign = '';
|
||
try {
|
||
// 1. 将 32 位时间戳以小端字节序编码为二进制数据
|
||
Uint8List signData = encodeTimestampToLittleEndianBytes(currentTimestamp);
|
||
|
||
// 2. 加载私钥
|
||
final privateKey = loadPrivateKey(privateKeyHex);
|
||
|
||
// 3. 创建 RSA 签名器
|
||
final signer = pc.RSASigner(pc.SHA256Digest(), '0609608648016503040201');
|
||
signer.init(true, pc.PrivateKeyParameter<pc.RSAPrivateKey>(privateKey));
|
||
|
||
// 4. 生成签名
|
||
final signature = signer.generateSignature(signData);
|
||
resultSign = hex.encode(signature.bytes);
|
||
} catch (e) {
|
||
throw StartChartMessageException('❌--->上报信息生成签名时出现错误: $e');
|
||
}
|
||
return resultSign;
|
||
}
|
||
|
||
// 将 32 位时间戳以小端字节序编码为二进制数据
|
||
Uint8List encodeTimestampToLittleEndianBytes(int timestamp) {
|
||
// 创建一个 4 字节的 ByteData 对象
|
||
ByteData byteData = ByteData(4);
|
||
|
||
// 将 32 位时间戳写入 ByteData,使用小端字节序
|
||
byteData.setUint32(0, timestamp, Endian.little);
|
||
|
||
// 将 ByteData 转换为 Uint8List
|
||
Uint8List bytes = byteData.buffer.asUint8List();
|
||
|
||
return bytes;
|
||
}
|
||
|
||
/// 转换私钥格式
|
||
String convertToPemPrivateKey(List<int> privateKeyBytes,
|
||
{bool isPKCS8 = true}) {
|
||
// 将字节数组转换为Base64编码的字符串
|
||
String base64PrivateKey = base64Encode(privateKeyBytes);
|
||
|
||
// 添加PEM格式的头尾标签
|
||
String pemHeader;
|
||
String pemFooter;
|
||
|
||
if (isPKCS8) {
|
||
pemHeader = "-----BEGIN PRIVATE KEY-----";
|
||
pemFooter = "-----END PRIVATE KEY-----";
|
||
} else {
|
||
pemHeader = "-----BEGIN RSA PRIVATE KEY-----";
|
||
pemFooter = "-----END RSA PRIVATE KEY-----";
|
||
}
|
||
|
||
// 将Base64字符串分行为每行64个字符
|
||
const lineLength = 64;
|
||
List<String> lines = []; // 用于存储每一行
|
||
|
||
for (int i = 0; i < base64PrivateKey.length; i += lineLength) {
|
||
int end = (i + lineLength < base64PrivateKey.length)
|
||
? i + lineLength
|
||
: base64PrivateKey.length;
|
||
lines.add(base64PrivateKey.substring(i, end));
|
||
}
|
||
|
||
// 组合成完整的PEM格式字符串
|
||
return "$pemHeader\n${lines.join('\n')}\n$pemFooter";
|
||
}
|
||
|
||
/// 自定义 PEM 格式的 RSA 私钥解析器
|
||
pc.RSAPrivateKey loadPrivateKey(String privateKeyHex) {
|
||
// 将十六进制字符串转换为字节数组
|
||
final uint8list = Uint8List.fromList(hexToBytes(privateKeyHex));
|
||
try {
|
||
// 使用 asn1lib 的 ASN1Parser 解析
|
||
final asn1Parser = asn1lib.ASN1Parser(uint8list);
|
||
final topLevelSeq = asn1Parser.nextObject() as asn1lib.ASN1Sequence;
|
||
|
||
final modulus = bytesToBigInt(
|
||
(topLevelSeq.elements[1] as asn1lib.ASN1Integer).valueBytes());
|
||
final privateExponent = bytesToBigInt(
|
||
(topLevelSeq.elements[3] as asn1lib.ASN1Integer).valueBytes());
|
||
final p = bytesToBigInt(
|
||
(topLevelSeq.elements[4] as asn1lib.ASN1Integer).valueBytes());
|
||
final q = bytesToBigInt(
|
||
(topLevelSeq.elements[5] as asn1lib.ASN1Integer).valueBytes());
|
||
|
||
return pc.RSAPrivateKey(modulus, privateExponent, p, q);
|
||
} catch (e) {
|
||
// 如果发生解码错误,打印错误信息
|
||
print("Error decoding private key: $e");
|
||
rethrow;
|
||
}
|
||
}
|
||
|
||
// 将十六进制字符串转换为字节数组
|
||
List<int> hexToBytes(String hex) {
|
||
return List<int>.generate(hex.length ~/ 2,
|
||
(i) => int.parse(hex.substring(i * 2, i * 2 + 2), radix: 16));
|
||
}
|
||
|
||
BigInt bytesToBigInt(Uint8List bytes) {
|
||
return BigInt.parse(
|
||
bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(),
|
||
radix: 16,
|
||
);
|
||
}
|
||
}
|