using System; using System.Text; using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Crypto.Signers; public class TokenGenerator { // 1. 获取当前时间的毫秒级时间戳 A public static long GetCurrentTimestamp() { return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } // 2. 拼接 B + A 得到 C public static string ConcatenateCodeAndTimestamp(string codeB, long timestampA) { return $"{codeB}{timestampA}"; } // 3. 获取 C 的 UTF-8 字节数组 D public static byte[] GetUtf8Bytes(string input) { return Encoding.UTF8.GetBytes(input); } // 4. 将 Hex 或 Base64 字符串私钥转换为 ECPrivateKeyParameters public static ECPrivateKeyParameters ParsePrivateKey(string privateKeyStr) { // 假设私钥是 Hex 字符串(如 "ABCD1234...") byte[] privateKeyBytes = HexToBytes(privateKeyStr); // 如果是 Base64,用 Convert.FromBase64String // SM2 曲线参数 var curve = ECNamedCurveTable.GetByName("sm2p256v1"); var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H); // 创建私钥 var privateKey = new ECPrivateKeyParameters(new BigInteger(1, privateKeyBytes), domainParams); return privateKey; } // 5. 使用 SM2 私钥签名 D 得到 E public static byte[] SignWithSm2(byte[] data, ECPrivateKeyParameters privateKey) { var signer = new SM2Signer(); signer.Init(true, privateKey); signer.BlockUpdate(data, 0, data.Length); return signer.GenerateSignature(); } // 6. 对 E 进行 Base64 编码得到 F public static string Base64Encode(byte[] data) { return Convert.ToBase64String(data); } // 7. 组装 Token: {B}.{A}.{F} public static string GenerateToken(string codeB, string privateKeyStr) { // 1. 获取时间戳 A long timestampA = GetCurrentTimestamp(); // 2. 拼接 B + A 得到 C string c = ConcatenateCodeAndTimestamp(codeB, timestampA); // 3. 获取 UTF-8 字节数组 D byte[] d = GetUtf8Bytes(c); // 4. 解析私钥字符串 ECPrivateKeyParameters privateKey = ParsePrivateKey(privateKeyStr); // 5. SM2 签名得到 E byte[] e = SignWithSm2(d, privateKey); // 6. Base64 编码得到 F string f = Base64Encode(e); // 7. 组装 Token return $"{codeB}.{timestampA}.{f}"; } // 辅助方法:Hex 字符串转字节数组 private static byte[] HexToBytes(string hex) { if (hex.Length % 2 != 0) throw new ArgumentException("Hex 字符串长度必须是偶数"); byte[] bytes = new byte[hex.Length / 2]; for (int i = 0; i < bytes.Length; i++) { bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16); } return bytes; } }