UNPKG

@zlattice/lattice-js

Version:

Lattice blockchain TypeScript SDK with dual module support (CJS + ESM)

232 lines 7.54 kB
"use strict"; /* eslint-disable class-methods-use-this */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.bigintToValue = bigintToValue; exports.encodeDer = encodeDer; exports.encodeEnc = encodeEnc; exports.decodeDer = decodeDer; exports.decodeEnc = decodeEnc; const utils = __importStar(require("@noble/curves/abstract/utils")); const bn_1 = require("./bn.js"); function bigintToValue(bigint) { let h = bigint.toString(16); if (h[0] !== '-') { // 正数 if (h.length % 2 === 1) h = `0${h}`; // 补齐到整字节 else if (!h.match(/^[0-7]/)) h = `00${h}`; // 非0开头,则补一个全0字节 } else { // 负数 h = h.substring(1); let len = h.length; if (len % 2 === 1) len += 1; // 补齐到整字节 else if (!h.match(/^[0-7]/)) len += 2; // 非0开头,则补一个全0字节 let maskString = ''; for (let i = 0; i < len; i++) maskString += 'f'; const mask = utils.hexToNumber(maskString); // 对绝对值取反,加1 const output = (mask ^ bigint) + bn_1.ONE; h = output.toString(16).replace(/^-/, ''); } return h; } class ASN1Object { constructor(tlv = null, t = '00', l = '00', v = '') { this.tlv = tlv; this.t = t; this.l = l; this.v = v; } /** * 获取 der 编码比特流16进制串 */ getEncodedHex() { if (!this.tlv) { this.v = this.getValue(); this.l = this.getLength(); this.tlv = this.t + this.l + this.v; } return this.tlv; } getLength() { const n = this.v.length / 2; // 字节数 let nHex = n.toString(16); if (nHex.length % 2 === 1) nHex = `0${nHex}`; // 补齐到整字节 if (n < 128) { // 短格式,以 0 开头 return nHex; } // 长格式,以 1 开头 const head = 128 + nHex.length / 2; // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度 return `${head.toString(16)}${nHex}`; } getValue() { return ''; } } class DERInteger extends ASN1Object { constructor(bigint) { super(); this.t = '02'; // 整型标签说明 if (bigint) this.v = bigintToValue(bigint); } getValue() { return this.v; } } class DEROctetString extends ASN1Object { constructor(s) { super(); this.s = s; this.hV = ''; this.t = '04'; // octstr 标签说明 if (s) this.v = s.toLowerCase(); } getValue() { return this.v; } } class DERSequence extends ASN1Object { constructor(asn1Array) { super(); this.asn1Array = asn1Array; this.t = '30'; } getValue() { this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join(''); return this.v; } } /** * 获取 l 占用字节数 */ function getLenOfL(str, start) { if (+str[start + 2] < 8) return 1; // l 以0开头,则表示短格式,只占一个字节 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身 const encoded = str.slice(start + 2, start + 6); const headHex = encoded.slice(0, 2); const head = Number.parseInt(headHex, 16); const nHexLength = (head - 128) * 2; return nHexLength; } /** * 获取 l */ function getL(str, start) { // 获取 l const len = getLenOfL(str, start); const l = str.substring(start + 2, start + 2 + len * 2); if (!l) return -1; const bigint = +l[0] < 8 ? utils.hexToNumber(l) : utils.hexToNumber(l.substring(2)); return +bigint.toString(); } /** * 获取 v 的位置 */ function getStartOfV(str, start) { const len = getLenOfL(str, start); return start + (len + 1) * 2; } /** * ASN.1 der 编码,针对 sm2 签名 */ function encodeDer(r, s) { const derR = new DERInteger(r); const derS = new DERInteger(s); const derSeq = new DERSequence([derR, derS]); return derSeq.getEncodedHex(); } function encodeEnc(x, y, hash, cipher) { const derX = new DERInteger(x); const derY = new DERInteger(y); const derHash = new DEROctetString(hash); const derCipher = new DEROctetString(cipher); const derSeq = new DERSequence([derX, derY, derHash, derCipher]); return derSeq.getEncodedHex(); } /** * 解析 ASN.1 der,针对 sm2 验签 */ function decodeDer(input) { // 结构: // input = | tSeq | lSeq | vSeq | // vSeq = | tR | lR | vR | tS | lS | vS | const start = getStartOfV(input, 0); const vIndexR = getStartOfV(input, start); const lR = getL(input, start); const vR = input.substring(vIndexR, vIndexR + lR * 2); const nextStart = vIndexR + vR.length; const vIndexS = getStartOfV(input, nextStart); const lS = getL(input, nextStart); const vS = input.substring(vIndexS, vIndexS + lS * 2); // const r = new BigInteger(vR, 16) // const s = new BigInteger(vS, 16) const r = utils.hexToNumber(vR); const s = utils.hexToNumber(vS); return { r, s }; } /** * 解析 ASN.1 der,针对 sm2 加密 */ function decodeEnc(input) { // Extracts a sequence from the input based on the current start index. function extractSequence(input, start) { const vIndex = getStartOfV(input, start); const length = getL(input, start); const value = input.substring(vIndex, vIndex + length * 2); const nextStart = vIndex + value.length; return { value, nextStart }; } const start = getStartOfV(input, 0); const { value: vR, nextStart: startS } = extractSequence(input, start); const { value: vS, nextStart: startHash } = extractSequence(input, startS); const { value: hash, nextStart: startCipher } = extractSequence(input, startHash); const { value: cipher } = extractSequence(input, startCipher); const x = utils.hexToNumber(vR); const y = utils.hexToNumber(vS); return { x, y, hash, cipher }; } //# sourceMappingURL=asn1.js.map