react / wstein / node_modules / browserify / node_modules / crypto-browserify / node_modules / public-encrypt / node_modules / parse-asn1 / node_modules / asn1.js / lib / asn1 / decoders / der.js
80647 viewsvar inherits = require('inherits');12var asn1 = require('../../asn1');3var base = asn1.base;4var bignum = asn1.bignum;56// Import DER constants7var der = asn1.constants.der;89function DERDecoder(entity) {10this.enc = 'der';11this.name = entity.name;12this.entity = entity;1314// Construct base tree15this.tree = new DERNode();16this.tree._init(entity.body);17};18module.exports = DERDecoder;1920DERDecoder.prototype.decode = function decode(data, options) {21if (!(data instanceof base.DecoderBuffer))22data = new base.DecoderBuffer(data, options);2324return this.tree._decode(data, options);25};2627// Tree methods2829function DERNode(parent) {30base.Node.call(this, 'der', parent);31}32inherits(DERNode, base.Node);3334DERNode.prototype._peekTag = function peekTag(buffer, tag, any) {35if (buffer.isEmpty())36return false;3738var state = buffer.save();39var decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"');40if (buffer.isError(decodedTag))41return decodedTag;4243buffer.restore(state);4445return decodedTag.tag === tag || decodedTag.tagStr === tag || any;46};4748DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) {49var decodedTag = derDecodeTag(buffer,50'Failed to decode tag of "' + tag + '"');51if (buffer.isError(decodedTag))52return decodedTag;5354var len = derDecodeLen(buffer,55decodedTag.primitive,56'Failed to get length of "' + tag + '"');5758// Failure59if (buffer.isError(len))60return len;6162if (!any &&63decodedTag.tag !== tag &&64decodedTag.tagStr !== tag &&65decodedTag.tagStr + 'of' !== tag) {66return buffer.error('Failed to match tag: "' + tag + '"');67}6869if (decodedTag.primitive || len !== null)70return buffer.skip(len, 'Failed to match body of: "' + tag + '"');7172// Indefinite length... find END tag73var state = buffer.start();74var res = this._skipUntilEnd(75buffer,76'Failed to skip indefinite length body: "' + this.tag + '"');77if (buffer.isError(res))78return res;7980return buffer.cut(state);81};8283DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) {84while (true) {85var tag = derDecodeTag(buffer, fail);86if (buffer.isError(tag))87return tag;88var len = derDecodeLen(buffer, tag.primitive, fail);89if (buffer.isError(len))90return len;9192var res;93if (tag.primitive || len !== null)94res = buffer.skip(len)95else96res = this._skipUntilEnd(buffer, fail);9798// Failure99if (buffer.isError(res))100return res;101102if (tag.tagStr === 'end')103break;104}105};106107DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder) {108var result = [];109while (!buffer.isEmpty()) {110var possibleEnd = this._peekTag(buffer, 'end');111if (buffer.isError(possibleEnd))112return possibleEnd;113114var res = decoder.decode(buffer, 'der');115if (buffer.isError(res) && possibleEnd)116break;117result.push(res);118}119return result;120};121122DERNode.prototype._decodeStr = function decodeStr(buffer, tag) {123if (tag === 'octstr') {124return buffer.raw();125} else if (tag === 'bitstr') {126var unused = buffer.readUInt8();127if (buffer.isError(unused))128return unused;129130return { unused: unused, data: buffer.raw() };131} else if (tag === 'ia5str') {132return buffer.raw().toString();133} else {134return this.error('Decoding of string type: ' + tag + ' unsupported');135}136};137138DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) {139var identifiers = [];140var ident = 0;141while (!buffer.isEmpty()) {142var subident = buffer.readUInt8();143ident <<= 7;144ident |= subident & 0x7f;145if ((subident & 0x80) === 0) {146identifiers.push(ident);147ident = 0;148}149}150if (subident & 0x80)151identifiers.push(ident);152153var first = (identifiers[0] / 40) | 0;154var second = identifiers[0] % 40;155156if (relative)157result = identifiers;158else159result = [first, second].concat(identifiers.slice(1));160161if (values)162result = values[result.join(' ')];163164return result;165};166167DERNode.prototype._decodeTime = function decodeTime(buffer, tag) {168var str = buffer.raw().toString();169if (tag === 'gentime') {170var year = str.slice(0, 4) | 0;171var mon = str.slice(4, 6) | 0;172var day = str.slice(6, 8) | 0;173var hour = str.slice(8, 10) | 0;174var min = str.slice(10, 12) | 0;175var sec = str.slice(12, 14) | 0;176} else if (tag === 'utctime') {177var year = str.slice(0, 2) | 0;178var mon = str.slice(2, 4) | 0;179var day = str.slice(4, 6) | 0;180var hour = str.slice(6, 8) | 0;181var min = str.slice(8, 10) | 0;182var sec = str.slice(10, 12) | 0;183if (year < 70)184year = 2000 + year;185else186year = 1900 + year;187} else {188return this.error('Decoding ' + tag + ' time is not supported yet');189}190191return Date.UTC(year, mon - 1, day, hour, min, sec, 0);192};193194DERNode.prototype._decodeNull = function decodeNull(buffer) {195return null;196};197198DERNode.prototype._decodeBool = function decodeBool(buffer) {199var res = buffer.readUInt8();200if (buffer.isError(res))201return res;202else203return res !== 0;204};205206DERNode.prototype._decodeInt = function decodeInt(buffer, values) {207// Bigint, return as it is (assume big endian)208var raw = buffer.raw();209var res = new bignum(raw);210211if (values)212res = values[res.toString(10)] || res;213214return res;215};216217DERNode.prototype._use = function use(entity, obj) {218if (typeof entity === 'function')219entity = entity(obj);220return entity._getDecoder('der').tree;221};222223// Utility methods224225function derDecodeTag(buf, fail) {226var tag = buf.readUInt8(fail);227if (buf.isError(tag))228return tag;229230var cls = der.tagClass[tag >> 6];231var primitive = (tag & 0x20) === 0;232233// Multi-octet tag - load234if ((tag & 0x1f) === 0x1f) {235var oct = tag;236tag = 0;237while ((oct & 0x80) === 0x80) {238oct = buf.readUInt8(fail);239if (buf.isError(oct))240return oct;241242tag <<= 7;243tag |= oct & 0x7f;244}245} else {246tag &= 0x1f;247}248var tagStr = der.tag[tag];249250return {251cls: cls,252primitive: primitive,253tag: tag,254tagStr: tagStr255};256}257258function derDecodeLen(buf, primitive, fail) {259var len = buf.readUInt8(fail);260if (buf.isError(len))261return len;262263// Indefinite form264if (!primitive && len === 0x80)265return null;266267// Definite form268if ((len & 0x80) === 0) {269// Short form270return len;271}272273// Long form274var num = len & 0x7f;275if (num >= 4)276return buf.error('length octect is too long');277278len = 0;279for (var i = 0; i < num; i++) {280len <<= 8;281var j = buf.readUInt8(fail);282if (buf.isError(j))283return j;284len |= j;285}286287return len;288}289290291