150 lines
3.6 KiB
Dart
Raw Normal View History

class _ASN1Object {
_ASN1Object() {
tlv = null;
}
String? tlv;
String t = '00';
String l = '00';
String v = '';
/// 获取 der 编码比特流16进制串
String getEncodedHex() {
if (tlv == null) {
v = getValue();
l = getLength();
tlv = t + l + v;
}
return tlv!;
}
String getLength() {
int n = v.length ~/ 2; // 字节数
String nHex = n.toRadixString(16);
if (nHex.length % 2 == 1) nHex = '0$nHex';
if (n < 128) {
return nHex;
} else {
int head = 128 + nHex.length ~/ 2;
return head.toRadixString(16) + nHex;
}
}
String getValue() {
return '';
}
}
class _DERInteger extends _ASN1Object {
_DERInteger(BigInt? bigint) : super() {
t = '02'; // 整型标签说明
if (bigint != null) v = bigintToValue(bigint);
}
@override
String getValue() {
return v;
}
String bigintToValue(BigInt inputBigInt) {
String hexString = inputBigInt.toRadixString(16);
if (!hexString.startsWith('-')) {
if (hexString.length % 2 == 1) {
hexString = '0$hexString';
} else if (!RegExp(r'^[0-7]').hasMatch(hexString)) {
hexString = '00$hexString';
}
} else {
// Negative number
hexString = hexString.substring(1);
int paddedLength = hexString.length;
if (paddedLength % 2 == 1) {
paddedLength += 1; // Pad to a whole byte
} else if (!RegExp(r'^[0-7]').hasMatch(hexString)) {
paddedLength += 2;
}
String bitmask = '';
for (int i = 0; i < paddedLength; i++) {
bitmask += 'f';
}
BigInt bitmaskBigInt = BigInt.parse(bitmask, radix: 16);
BigInt twosComplementBigInt = bitmaskBigInt ^ inputBigInt;
twosComplementBigInt = twosComplementBigInt + BigInt.one;
hexString = twosComplementBigInt.toRadixString(16).replaceAll(RegExp(r'^-'), '');
}
return hexString;
}
}
class _DERSequence extends _ASN1Object {
_DERSequence(this.asn1Array) : super() {
t = '30'; // 序列标签说明
}
List<_ASN1Object> asn1Array;
@override
String getValue() {
v = asn1Array.map((asn1Object) => asn1Object.getEncodedHex()).join('');
return v;
}
}
int getLenOfL(String str, int start) {
if (int.parse(str[start + 2]) < 8) return 1;
return int.parse(str.substring(start + 2, start + 4)) & 0x7f + 1;
}
int getL(String str, int start) {
// 获取 l
int len = getLenOfL(str, start);
String l = str.substring(start + 2, start + 2 + len * 2);
if (l.isEmpty) return -1;
BigInt bigint = int.parse(l[0]) < 8
? BigInt.parse(l, radix: 16)
: BigInt.parse(l.substring(2), radix: 16);
return bigint.toInt();
}
int getStartOfV(String str, int start) {
int len = getLenOfL(str, start);
return start + (len + 1) * 2;
}
class ASN1Utils {
/// ASN.1 der 编码,针对 sm2 签名
static String encodeDer(BigInt r, BigInt s) {
final derR = _DERInteger(r);
final derS = _DERInteger(s);
final derSeq = _DERSequence([derR, derS]);
return derSeq.getEncodedHex();
}
/// 解析 ASN.1 der针对 sm2 验签
static Map<String, BigInt> decodeDer(String input) {
int start = getStartOfV(input, 0);
int vIndexR = getStartOfV(input, start);
int lR = getL(input, start);
String vR = input.substring(vIndexR, vIndexR + lR * 2);
int nextStart = vIndexR + vR.length;
int vIndexS = getStartOfV(input, nextStart);
int lS = getL(input, nextStart);
String vS = input.substring(vIndexS, vIndexS + lS * 2);
BigInt r = BigInt.parse(vR, radix: 16);
BigInt s = BigInt.parse(vS, radix: 16);
return {'r': r, 's': s};
}
}