UNPKG

@indrajala/asn1der

Version:

parse ASN.1 DER structures

139 lines 7.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Asn1Node = exports.parseGeneralizedTimeString = exports.parseUtcString = void 0; const asn1der_1 = require("../asn1der"); const descriptions_1 = require("./descriptions"); const enums_1 = require("./enums"); const oid_1 = require("./oid"); // 'YYMMDD 000000 Z' exports.parseUtcString = (s) => { const yyyy = 2000 + parseInt(s.substring(0, 2)); const mm = parseInt(s.substring(2, 4)); const dd = parseInt(s.substring(4, 6)); const hours = parseInt(s.substring(6, 8)); const mins = parseInt(s.substring(8, 10)); const seconds = parseInt(s.substring(10, 12)); // console.log(`${yyyy}/${mm}/${dd} ${hours}:${mins}:${seconds}`); return new Date(Date.UTC(yyyy, mm - 1, dd, hours, mins, seconds)); }; // YYYYMMDD000000Z // YYYY MM DD 00 00 00 Z // e.g. // 19920521000000Z // 19920622123421Z // 19920722132100.3Z // exports.parseGeneralizedTimeString = (s) => { const yyyy = parseInt(s.substring(0, 4)); const mm = parseInt(s.substring(4, 6)); const dd = parseInt(s.substring(6, 8)); const hours = parseInt(s.substring(8, 10)); const mins = parseInt(s.substring(10, 12)); const seconds = parseInt(s.substring(12, 14)); const hasFractionalSeconds = s[14] == '.'; const ms = (hasFractionalSeconds) ? parseInt(s.substring(15, s.length - 1)) * 1000 : 0; // console.log(`${yyyy}/${mm}/${dd} ${hours}:${mins}:${seconds}`); return new Date(Date.UTC(yyyy, mm - 1, dd, hours, mins, seconds, ms)); }; class Asn1Node { constructor(raw, identifier, length, content, children) { this.toString = (tagNumberLookup = null) => { const tagNumberLookupIsRelevant = [ enums_1.Asn1Class.Application, enums_1.Asn1Class.ContextSpecific, enums_1.Asn1Class.Private ].includes(this.identifier.class); // console.log(`tag number: ${this.identifier.tagNumber}`); // console.log(`lookup has: ${tagNumberLookup?.has(this.identifier.tagNumber)}`); const tagDescription = ((tagNumberLookup != null) && (tagNumberLookup.has(this.identifier.tagNumber)) && tagNumberLookupIsRelevant) ? tagNumberLookup.get(this.identifier.tagNumber) + ` [${this.identifier.tagNumber}]` : (descriptions_1.asn1TagDescription.has(this.identifier.tagNumber)) ? descriptions_1.asn1TagDescription.get(this.identifier.tagNumber) : null; const label = (tagDescription != null) ? tagDescription : `${this.identifier.tagNumber}`; const oidStr = (this.identifier.tagNumber == enums_1.Asn1Tag.ObjectIdentifier) ? asn1der_1.parseOID(this.content) : 'badly formed OID'; const oidDescription = (oid_1.x509OIDs.has(oidStr)) ? oid_1.x509OIDs.get(oidStr) : 'unknown OID'; const contentHex = this.getContentAsHex(); const hexLimit = 20; const cleanContentHex = (contentHex.length > hexLimit) ? contentHex.substring(0, hexLimit) + '...' : contentHex; const universalContentStr = (this.identifier.tagNumber == enums_1.Asn1Tag.ObjectIdentifier) ? `${oidStr} (${oidDescription})` : (this.identifier.tagNumber == enums_1.Asn1Tag.UTF8String) ? this.getUTF8String() : (this.identifier.tagNumber == enums_1.Asn1Tag.PrintableString) ? this.getPrintableString() : (this.identifier.tagNumber == enums_1.Asn1Tag.UTCTime) ? this.getUTCTime().toString() : (this.identifier.tagNumber == enums_1.Asn1Tag.Integer) ? this.getInteger().toString() : (this.identifier.tagNumber == enums_1.Asn1Tag.IA5String) ? this.getIA5String() : (this.identifier.tagNumber == enums_1.Asn1Tag.Boolean) ? this.getBoolean() : (this.identifier.tagNumber == enums_1.Asn1Tag.GeneralizedTime) ? this.getGeneralizedTime().toString() : cleanContentHex; const contentStr = (this.identifier.class == enums_1.Asn1Class.Universal) ? universalContentStr : cleanContentHex; return `${label} - ${contentStr}`; }; this.getUTF8String = () => this.content.toString('utf-8'); this.getPrintableString = () => this.content.toString('ascii'); this.getUTCTime = () => exports.parseUtcString(this.content.toString('ascii')); this.getGeneralizedTime = () => exports.parseGeneralizedTimeString(this.content.toString('ascii')); this.getIA5String = () => this.content.toString('ascii'); this.getBoolean = () => !(this.content.readInt8(0) == 0); this.getInteger = () => parseInt(this.content.toString('hex'), 16); this.getSetElementsAsIntegers = () => this.children.map(child => child.getInteger()); this.getSetElements = () => this.children; this.getNull = () => this.identifier.tagNumber == enums_1.Asn1Tag.Null; this.getContentAsHex = () => this.content.toString('hex'); // TODO fix argument order this.summary = (indent, tagNumberLookup) => { const childrenReport = []; this.children .forEach(child => childrenReport.push(...child.summary(indent, tagNumberLookup))); return [ this.toString(tagNumberLookup), ...childrenReport.map(line => ' '.repeat(indent) + line) ]; }; this.getChildAtZIndex = (zindex) => this.children[zindex]; this.getChildWithTagNumber = (tagNumber) => this.children.find(it => it.identifier.tagNumber == tagNumber); this.get = (path) => { const steps = path.split('.'); const firstStep = steps[0]; const firstStepTarget = (firstStep.startsWith('#')) ? this.getChildWithTagNumber(parseInt(firstStep.substring(1))) : this.getChildAtZIndex(parseInt(firstStep)); return (steps.length == 1) ? firstStepTarget : (firstStepTarget) ? firstStepTarget.get(steps.slice(1).join('.')) : null; }; this.reparse = () => { this.children = asn1der_1.parseDER(this.content); }; this.raw = raw; this.identifier = identifier; this.length = length; this.content = content; this.children = children; } } exports.Asn1Node = Asn1Node; //# sourceMappingURL=Asn1Node.js.map