UNPKG

ecdsa-node-ts

Version:

TypeScript implementation of the Elliptic Curve Digital Signature Algorithm (ECDSA)

273 lines (272 loc) 9.39 kB
"use strict"; 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; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.encodeSequence = encodeSequence; exports.encodeInteger = encodeInteger; exports.encodeOid = encodeOid; exports.encodeBitstring = encodeBitstring; exports.encodeOctetString = encodeOctetString; exports.encodeConstructed = encodeConstructed; exports.removeSequence = removeSequence; exports.removeInteger = removeInteger; exports.removeObject = removeObject; exports.removeBitString = removeBitString; exports.removeOctetString = removeOctetString; exports.removeConstructed = removeConstructed; exports.fromPem = fromPem; exports.toPem = toPem; const Base64 = __importStar(require("./base")); const BinaryAscii = __importStar(require("./binary")); const big_integer_1 = __importDefault(require("big-integer")); const hexAt = Buffer.from([0x00]); const hexB = Buffer.from([0x02]); const hexC = Buffer.from([0x03]); const hexD = Buffer.from([0x04]); const hexF = Buffer.from([0x06]); const hex0 = Buffer.from([0x30]); const hex31 = 0x1f; const hex127 = 0x7f; const hex129 = 0xa0; const hex160 = 0x80; const hex224 = 0xe0; const bytesHex0 = hex0; const bytesHexB = hexB; const bytesHexC = hexC; const bytesHexD = hexD; const bytesHexF = hexF; function encodeSequence(...args) { const buffers = args.map((arg) => Buffer.isBuffer(arg) ? arg : Buffer.from(arg, "binary")); let totalLength = buffers.reduce((acc, curr) => acc + curr.length, 0); return Buffer.concat([hex0, _encodeLength(totalLength), ...buffers]); } function encodeInteger(x) { if (x.lesser(0)) { throw new Error("x cannot be negative"); } let t = x.toString(16); if (t.length % 2) { t = "0" + t; } let xBinary = BinaryAscii.binaryFromHex(t); let num = xBinary[0]; if (num <= hex127) { return Buffer.concat([hexB, Buffer.from([xBinary.length]), xBinary]); } return Buffer.concat([ hexB, Buffer.from([xBinary.length + 1]), hexAt, xBinary, ]); } function encodeOid(pieces) { let [first, second, ...rest] = pieces; if (first > 2) { throw new Error("first has to be <= 2"); } if (second > 39) { throw new Error("second has to be <= 39"); } let encodedPieces = rest.map(_encodeNumber); let firstByte = Buffer.from([40 * first + second]); let body = Buffer.concat([ firstByte, ...encodedPieces.map((p) => Buffer.from(p)), ]); return Buffer.concat([hexF, _encodeLength(body.length), body]); } function encodeBitstring(t) { const data = Buffer.isBuffer(t) ? t : Buffer.from(t, "binary"); return Buffer.concat([hexC, _encodeLength(data.length), data]); } function encodeOctetString(t) { const data = Buffer.isBuffer(t) ? t : Buffer.from(t, "binary"); return Buffer.concat([hexD, _encodeLength(data.length), data]); } function encodeConstructed(tag, value) { const data = Buffer.isBuffer(value) ? value : Buffer.from(value, "binary"); return Buffer.concat([ Buffer.from([hex129 + tag]), _encodeLength(data.length), data, ]); } function removeSequence(data) { const buf = Buffer.isBuffer(data) ? data : Buffer.from(data, "binary"); _checkSequenceError(buf, bytesHex0, "30"); let [length, lengthLen] = _readLength(buf.slice(1)); let endSeq = 1 + lengthLen + length; return [buf.slice(1 + lengthLen, endSeq), buf.slice(endSeq)]; } function removeInteger(data) { const buf = Buffer.isBuffer(data) ? data : Buffer.from(data, "binary"); _checkSequenceError(buf, bytesHexB, "02"); let [length, lengthLen] = _readLength(buf.slice(1)); let numberBytes = buf.slice(1 + lengthLen, 1 + lengthLen + length); let rest = buf.slice(1 + lengthLen + length); if (numberBytes[0] >= hex160) { throw new Error("nBytes must be < 160"); } return [(0, big_integer_1.default)(numberBytes.toString("hex"), 16), rest]; } function removeObject(data) { const buf = Buffer.isBuffer(data) ? data : Buffer.from(data, "binary"); _checkSequenceError(buf, bytesHexF, "06"); let [length, lengthLen] = _readLength(buf.slice(1)); let body = buf.slice(1 + lengthLen, 1 + lengthLen + length); let rest = buf.slice(1 + lengthLen + length); let numbers = []; let remaining = body; while (remaining.length > 0) { let [n, lengthLength] = _readNumber(remaining); numbers.push(n); remaining = remaining.slice(lengthLength); } let n0 = numbers.shift(); let first = Math.floor(n0 / 40); let second = n0 - 40 * first; return [[first, second, ...numbers], rest]; } function removeBitString(data) { const buf = Buffer.isBuffer(data) ? data : Buffer.from(data, "binary"); _checkSequenceError(buf, bytesHexC, "03"); let [length, lengthLen] = _readLength(buf.slice(1)); let body = buf.slice(1 + lengthLen, 1 + lengthLen + length); let rest = buf.slice(1 + lengthLen + length); return [body, rest]; } function removeOctetString(data) { const buf = Buffer.isBuffer(data) ? data : Buffer.from(data, "binary"); _checkSequenceError(buf, bytesHexD, "04"); let [length, lengthLen] = _readLength(buf.slice(1)); let body = buf.slice(1 + lengthLen, 1 + lengthLen + length); let rest = buf.slice(1 + lengthLen + length); return [body, rest]; } function removeConstructed(data) { const buf = Buffer.isBuffer(data) ? data : Buffer.from(data, "binary"); let s0 = buf[0]; if ((s0 & hex224) != hex129) { throw new Error("wanted constructed tag (0xa0-0xbf), got 0x" + s0.toString(16)); } let tag = s0 & hex31; let [length, lengthLen] = _readLength(buf.slice(1)); let body = buf.slice(1 + lengthLen, 1 + lengthLen + length); let rest = buf.slice(1 + lengthLen + length); return [tag, body, rest]; } function fromPem(pem) { let stripped = pem .split("\n") .filter((line) => !line.startsWith("-----")) .join("") .trim(); return Base64.decode(stripped); } function toPem(der, name) { let b64 = Base64.encode(der); let lines = [`-----BEGIN ${name}-----\n`]; for (let start = 0; start <= b64.length; start += 64) { lines.push(b64.slice(start, start + 64) + "\n"); } lines.push(`-----END ${name}-----\n`); return lines.join(""); } function _encodeLength(length) { if (length < 0) { throw new Error("length cannot be negative"); } if (length < hex160) { return Buffer.from([length]); } let hexLength = length.toString(16); if (hexLength.length % 2) { hexLength = "0" + hexLength; } let lengthBytes = Buffer.from(hexLength, "hex"); return Buffer.concat([ Buffer.from([hex160 + lengthBytes.length]), lengthBytes, ]); } function _encodeNumber(n) { if (n < 0) { throw new Error("n cannot be negative"); } if (n === 0) { return Buffer.from([0]); } let l = []; while (n > 0) { l.unshift(n & hex127); n = n >> 7; } for (let i = 0; i < l.length - 1; i++) { l[i] = l[i] | hex160; } return Buffer.from(l); } function _readLength(buf) { let num = buf[0]; if (!(num & hex160)) { return [num, 1]; } let lengthLen = num - hex160; let numberBytes = buf.slice(1, 1 + lengthLen); return [parseInt(numberBytes.toString("hex"), 16), 1 + lengthLen]; } function _readNumber(buf) { let num = buf[0]; let length = 1; let n = num & hex127; while (num & hex160) { buf = buf.slice(1); num = buf[0]; n = (n << 7) | (num & hex127); length += 1; } return [n, length]; } function _checkSequenceError(buf, start, expected) { if (buf[0] !== start[0]) { throw new Error(`wanted sequence starting with ${expected}`); } } function _extractFirstInt(buf) { return buf[0]; }