react-native-scryptsy
Version:
Pure JavaScript implementation of the scrypt key deriviation function that is fully compatible with Node.js and the browser.
1,573 lines (1,291 loc) • 939 kB
JavaScript
var crypto;
(function () {
function r(e, n, t) {
function o(i, f) {
if (!n[i]) {
if (!e[i]) {
var c = 'function' == typeof requirex && requirex;
if (!f && c) return c(i, !0);
if (u) return u(i, !0);
var a = new Error("Cannot find module '" + i + "'");
throw ((a.code = 'MODULE_NOT_FOUND'), a);
}
var p = (n[i] = { exports: {} });
e[i][0].call(
p.exports,
function (r) {
var n = e[i][1][r];
return o(n || r);
},
p,
p.exports,
r,
e,
n,
t,
);
}
return n[i].exports;
}
for (var u = 'function' == typeof requirex && requirex, i = 0; i < t.length; i++) o(t[i]);
return o;
}
return r;
})()(
{
1: [
function (requirex, module, exports) {
'use strict';
const asn1 = exports;
asn1.bignum = requirex('bn.js');
asn1.define = requirex('./asn1/api').define;
asn1.base = requirex('./asn1/base');
asn1.constants = requirex('./asn1/constants');
asn1.decoders = requirex('./asn1/decoders');
asn1.encoders = requirex('./asn1/encoders');
},
{
'./asn1/api': 2,
'./asn1/base': 4,
'./asn1/constants': 8,
'./asn1/decoders': 10,
'./asn1/encoders': 13,
'bn.js': 15,
},
],
2: [
function (requirex, module, exports) {
'use strict';
const encoders = requirex('./encoders');
const decoders = requirex('./decoders');
const inherits = requirex('inherits');
const api = exports;
api.define = function define(name, body) {
return new Entity(name, body);
};
function Entity(name, body) {
this.name = name;
this.body = body;
this.decoders = {};
this.encoders = {};
}
Entity.prototype._createNamed = function createNamed(Base) {
const name = this.name;
function Generated(entity) {
this._initNamed(entity, name);
}
inherits(Generated, Base);
Generated.prototype._initNamed = function _initNamed(entity, name) {
Base.call(this, entity, name);
};
return new Generated(this);
};
Entity.prototype._getDecoder = function _getDecoder(enc) {
enc = enc || 'der';
// Lazily create decoder
if (!this.decoders.hasOwnProperty(enc)) this.decoders[enc] = this._createNamed(decoders[enc]);
return this.decoders[enc];
};
Entity.prototype.decode = function decode(data, enc, options) {
return this._getDecoder(enc).decode(data, options);
};
Entity.prototype._getEncoder = function _getEncoder(enc) {
enc = enc || 'der';
// Lazily create encoder
if (!this.encoders.hasOwnProperty(enc)) this.encoders[enc] = this._createNamed(encoders[enc]);
return this.encoders[enc];
};
Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) {
return this._getEncoder(enc).encode(data, reporter);
};
},
{ './decoders': 10, './encoders': 13, inherits: 132 },
],
3: [
function (requirex, module, exports) {
'use strict';
const inherits = requirex('inherits');
const Reporter = requirex('../base/reporter').Reporter;
const Buffer = requirex('safer-buffer').Buffer;
function DecoderBuffer(base, options) {
Reporter.call(this, options);
if (!Buffer.isBuffer(base)) {
this.error('Input not Buffer');
return;
}
this.base = base;
this.offset = 0;
this.length = base.length;
}
inherits(DecoderBuffer, Reporter);
exports.DecoderBuffer = DecoderBuffer;
DecoderBuffer.isDecoderBuffer = function isDecoderBuffer(data) {
if (data instanceof DecoderBuffer) {
return true;
}
// Or accept compatible API
const isCompatible =
typeof data === 'object' &&
Buffer.isBuffer(data.base) &&
data.constructor.name === 'DecoderBuffer' &&
typeof data.offset === 'number' &&
typeof data.length === 'number' &&
typeof data.save === 'function' &&
typeof data.restore === 'function' &&
typeof data.isEmpty === 'function' &&
typeof data.readUInt8 === 'function' &&
typeof data.skip === 'function' &&
typeof data.raw === 'function';
return isCompatible;
};
DecoderBuffer.prototype.save = function save() {
return { offset: this.offset, reporter: Reporter.prototype.save.call(this) };
};
DecoderBuffer.prototype.restore = function restore(save) {
// Return skipped data
const res = new DecoderBuffer(this.base);
res.offset = save.offset;
res.length = this.offset;
this.offset = save.offset;
Reporter.prototype.restore.call(this, save.reporter);
return res;
};
DecoderBuffer.prototype.isEmpty = function isEmpty() {
return this.offset === this.length;
};
DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) {
if (this.offset + 1 <= this.length) return this.base.readUInt8(this.offset++, true);
else return this.error(fail || 'DecoderBuffer overrun');
};
DecoderBuffer.prototype.skip = function skip(bytes, fail) {
if (!(this.offset + bytes <= this.length)) return this.error(fail || 'DecoderBuffer overrun');
const res = new DecoderBuffer(this.base);
// Share reporter state
res._reporterState = this._reporterState;
res.offset = this.offset;
res.length = this.offset + bytes;
this.offset += bytes;
return res;
};
DecoderBuffer.prototype.raw = function raw(save) {
return this.base.slice(save ? save.offset : this.offset, this.length);
};
function EncoderBuffer(value, reporter) {
if (Array.isArray(value)) {
this.length = 0;
this.value = value.map(function (item) {
if (!EncoderBuffer.isEncoderBuffer(item)) item = new EncoderBuffer(item, reporter);
this.length += item.length;
return item;
}, this);
} else if (typeof value === 'number') {
if (!(0 <= value && value <= 0xff)) return reporter.error('non-byte EncoderBuffer value');
this.value = value;
this.length = 1;
} else if (typeof value === 'string') {
this.value = value;
this.length = Buffer.byteLength(value);
} else if (Buffer.isBuffer(value)) {
this.value = value;
this.length = value.length;
} else {
return reporter.error('Unsupported type: ' + typeof value);
}
}
exports.EncoderBuffer = EncoderBuffer;
EncoderBuffer.isEncoderBuffer = function isEncoderBuffer(data) {
if (data instanceof EncoderBuffer) {
return true;
}
// Or accept compatible API
const isCompatible =
typeof data === 'object' &&
data.constructor.name === 'EncoderBuffer' &&
typeof data.length === 'number' &&
typeof data.join === 'function';
return isCompatible;
};
EncoderBuffer.prototype.join = function join(out, offset) {
if (!out) out = Buffer.alloc(this.length);
if (!offset) offset = 0;
if (this.length === 0) return out;
if (Array.isArray(this.value)) {
this.value.forEach(function (item) {
item.join(out, offset);
offset += item.length;
});
} else {
if (typeof this.value === 'number') out[offset] = this.value;
else if (typeof this.value === 'string') out.write(this.value, offset);
else if (Buffer.isBuffer(this.value)) this.value.copy(out, offset);
offset += this.length;
}
return out;
};
},
{ '../base/reporter': 6, inherits: 132, 'safer-buffer': 161 },
],
4: [
function (requirex, module, exports) {
'use strict';
const base = exports;
base.Reporter = requirex('./reporter').Reporter;
base.DecoderBuffer = requirex('./buffer').DecoderBuffer;
base.EncoderBuffer = requirex('./buffer').EncoderBuffer;
base.Node = requirex('./node');
},
{ './buffer': 3, './node': 5, './reporter': 6 },
],
5: [
function (requirex, module, exports) {
'use strict';
const Reporter = requirex('../base/reporter').Reporter;
const EncoderBuffer = requirex('../base/buffer').EncoderBuffer;
const DecoderBuffer = requirex('../base/buffer').DecoderBuffer;
const assert = requirex('minimalistic-assert');
// Supported tags
const tags = [
'seq',
'seqof',
'set',
'setof',
'objid',
'bool',
'gentime',
'utctime',
'null_',
'enum',
'int',
'objDesc',
'bitstr',
'bmpstr',
'charstr',
'genstr',
'graphstr',
'ia5str',
'iso646str',
'numstr',
'octstr',
'printstr',
't61str',
'unistr',
'utf8str',
'videostr',
];
// Public methods list
const methods = [
'key',
'obj',
'use',
'optional',
'explicit',
'implicit',
'def',
'choice',
'any',
'contains',
].concat(tags);
// Overrided methods list
const overrided = [
'_peekTag',
'_decodeTag',
'_use',
'_decodeStr',
'_decodeObjid',
'_decodeTime',
'_decodeNull',
'_decodeInt',
'_decodeBool',
'_decodeList',
'_encodeComposite',
'_encodeStr',
'_encodeObjid',
'_encodeTime',
'_encodeNull',
'_encodeInt',
'_encodeBool',
];
function Node(enc, parent, name) {
const state = {};
this._baseState = state;
state.name = name;
state.enc = enc;
state.parent = parent || null;
state.children = null;
// State
state.tag = null;
state.args = null;
state.reverseArgs = null;
state.choice = null;
state.optional = false;
state.any = false;
state.obj = false;
state.use = null;
state.useDecoder = null;
state.key = null;
state['default'] = null;
state.explicit = null;
state.implicit = null;
state.contains = null;
// Should create new instance on each method
if (!state.parent) {
state.children = [];
this._wrap();
}
}
module.exports = Node;
const stateProps = [
'enc',
'parent',
'children',
'tag',
'args',
'reverseArgs',
'choice',
'optional',
'any',
'obj',
'use',
'alteredUse',
'key',
'default',
'explicit',
'implicit',
'contains',
];
Node.prototype.clone = function clone() {
const state = this._baseState;
const cstate = {};
stateProps.forEach(function (prop) {
cstate[prop] = state[prop];
});
const res = new this.constructor(cstate.parent);
res._baseState = cstate;
return res;
};
Node.prototype._wrap = function wrap() {
const state = this._baseState;
methods.forEach(function (method) {
this[method] = function _wrappedMethod() {
const clone = new this.constructor(this);
state.children.push(clone);
return clone[method].apply(clone, arguments);
};
}, this);
};
Node.prototype._init = function init(body) {
const state = this._baseState;
assert(state.parent === null);
body.call(this);
// Filter children
state.children = state.children.filter(function (child) {
return child._baseState.parent === this;
}, this);
assert.equal(state.children.length, 1, 'Root node can have only one child');
};
Node.prototype._useArgs = function useArgs(args) {
const state = this._baseState;
// Filter children and args
const children = args.filter(function (arg) {
return arg instanceof this.constructor;
}, this);
args = args.filter(function (arg) {
return !(arg instanceof this.constructor);
}, this);
if (children.length !== 0) {
assert(state.children === null);
state.children = children;
// Replace parent to maintain backward link
children.forEach(function (child) {
child._baseState.parent = this;
}, this);
}
if (args.length !== 0) {
assert(state.args === null);
state.args = args;
state.reverseArgs = args.map(function (arg) {
if (typeof arg !== 'object' || arg.constructor !== Object) return arg;
const res = {};
Object.keys(arg).forEach(function (key) {
if (key == (key | 0)) key |= 0;
const value = arg[key];
res[value] = key;
});
return res;
});
}
};
//
// Overrided methods
//
overrided.forEach(function (method) {
Node.prototype[method] = function _overrided() {
const state = this._baseState;
throw new Error(method + ' not implemented for encoding: ' + state.enc);
};
});
//
// Public methods
//
tags.forEach(function (tag) {
Node.prototype[tag] = function _tagMethod() {
const state = this._baseState;
const args = Array.prototype.slice.call(arguments);
assert(state.tag === null);
state.tag = tag;
this._useArgs(args);
return this;
};
});
Node.prototype.use = function use(item) {
assert(item);
const state = this._baseState;
assert(state.use === null);
state.use = item;
return this;
};
Node.prototype.optional = function optional() {
const state = this._baseState;
state.optional = true;
return this;
};
Node.prototype.def = function def(val) {
const state = this._baseState;
assert(state['default'] === null);
state['default'] = val;
state.optional = true;
return this;
};
Node.prototype.explicit = function explicit(num) {
const state = this._baseState;
assert(state.explicit === null && state.implicit === null);
state.explicit = num;
return this;
};
Node.prototype.implicit = function implicit(num) {
const state = this._baseState;
assert(state.explicit === null && state.implicit === null);
state.implicit = num;
return this;
};
Node.prototype.obj = function obj() {
const state = this._baseState;
const args = Array.prototype.slice.call(arguments);
state.obj = true;
if (args.length !== 0) this._useArgs(args);
return this;
};
Node.prototype.key = function key(newKey) {
const state = this._baseState;
assert(state.key === null);
state.key = newKey;
return this;
};
Node.prototype.any = function any() {
const state = this._baseState;
state.any = true;
return this;
};
Node.prototype.choice = function choice(obj) {
const state = this._baseState;
assert(state.choice === null);
state.choice = obj;
this._useArgs(
Object.keys(obj).map(function (key) {
return obj[key];
}),
);
return this;
};
Node.prototype.contains = function contains(item) {
const state = this._baseState;
assert(state.use === null);
state.contains = item;
return this;
};
//
// Decoding
//
Node.prototype._decode = function decode(input, options) {
const state = this._baseState;
// Decode root node
if (state.parent === null) return input.wrapResult(state.children[0]._decode(input, options));
let result = state['default'];
let present = true;
let prevKey = null;
if (state.key !== null) prevKey = input.enterKey(state.key);
// Check if tag is there
if (state.optional) {
let tag = null;
if (state.explicit !== null) tag = state.explicit;
else if (state.implicit !== null) tag = state.implicit;
else if (state.tag !== null) tag = state.tag;
if (tag === null && !state.any) {
// Trial and Error
const save = input.save();
try {
if (state.choice === null) this._decodeGeneric(state.tag, input, options);
else this._decodeChoice(input, options);
present = true;
} catch (e) {
present = false;
}
input.restore(save);
} else {
present = this._peekTag(input, tag, state.any);
if (input.isError(present)) return present;
}
}
// Push object on stack
let prevObj;
if (state.obj && present) prevObj = input.enterObject();
if (present) {
// Unwrap explicit values
if (state.explicit !== null) {
const explicit = this._decodeTag(input, state.explicit);
if (input.isError(explicit)) return explicit;
input = explicit;
}
const start = input.offset;
// Unwrap implicit and normal values
if (state.use === null && state.choice === null) {
let save;
if (state.any) save = input.save();
const body = this._decodeTag(input, state.implicit !== null ? state.implicit : state.tag, state.any);
if (input.isError(body)) return body;
if (state.any) result = input.raw(save);
else input = body;
}
if (options && options.track && state.tag !== null)
options.track(input.path(), start, input.length, 'tagged');
if (options && options.track && state.tag !== null)
options.track(input.path(), input.offset, input.length, 'content');
// Select proper method for tag
if (state.any) {
// no-op
} else if (state.choice === null) {
result = this._decodeGeneric(state.tag, input, options);
} else {
result = this._decodeChoice(input, options);
}
if (input.isError(result)) return result;
// Decode children
if (!state.any && state.choice === null && state.children !== null) {
state.children.forEach(function decodeChildren(child) {
// NOTE: We are ignoring errors here, to let parser continue with other
// parts of encoded data
child._decode(input, options);
});
}
// Decode contained/encoded by schema, only in bit or octet strings
if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) {
const data = new DecoderBuffer(result);
result = this._getUse(state.contains, input._reporterState.obj)._decode(data, options);
}
}
// Pop object
if (state.obj && present) result = input.leaveObject(prevObj);
// Set key
if (state.key !== null && (result !== null || present === true)) input.leaveKey(prevKey, state.key, result);
else if (prevKey !== null) input.exitKey(prevKey);
return result;
};
Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) {
const state = this._baseState;
if (tag === 'seq' || tag === 'set') return null;
if (tag === 'seqof' || tag === 'setof') return this._decodeList(input, tag, state.args[0], options);
else if (/str$/.test(tag)) return this._decodeStr(input, tag, options);
else if (tag === 'objid' && state.args)
return this._decodeObjid(input, state.args[0], state.args[1], options);
else if (tag === 'objid') return this._decodeObjid(input, null, null, options);
else if (tag === 'gentime' || tag === 'utctime') return this._decodeTime(input, tag, options);
else if (tag === 'null_') return this._decodeNull(input, options);
else if (tag === 'bool') return this._decodeBool(input, options);
else if (tag === 'objDesc') return this._decodeStr(input, tag, options);
else if (tag === 'int' || tag === 'enum') return this._decodeInt(input, state.args && state.args[0], options);
if (state.use !== null) {
return this._getUse(state.use, input._reporterState.obj)._decode(input, options);
} else {
return input.error('unknown tag: ' + tag);
}
};
Node.prototype._getUse = function _getUse(entity, obj) {
const state = this._baseState;
// Create altered use decoder if implicit is set
state.useDecoder = this._use(entity, obj);
assert(state.useDecoder._baseState.parent === null);
state.useDecoder = state.useDecoder._baseState.children[0];
if (state.implicit !== state.useDecoder._baseState.implicit) {
state.useDecoder = state.useDecoder.clone();
state.useDecoder._baseState.implicit = state.implicit;
}
return state.useDecoder;
};
Node.prototype._decodeChoice = function decodeChoice(input, options) {
const state = this._baseState;
let result = null;
let match = false;
Object.keys(state.choice).some(function (key) {
const save = input.save();
const node = state.choice[key];
try {
const value = node._decode(input, options);
if (input.isError(value)) return false;
result = { type: key, value: value };
match = true;
} catch (e) {
input.restore(save);
return false;
}
return true;
}, this);
if (!match) return input.error('Choice not matched');
return result;
};
//
// Encoding
//
Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) {
return new EncoderBuffer(data, this.reporter);
};
Node.prototype._encode = function encode(data, reporter, parent) {
const state = this._baseState;
if (state['default'] !== null && state['default'] === data) return;
const result = this._encodeValue(data, reporter, parent);
if (result === undefined) return;
if (this._skipDefault(result, reporter, parent)) return;
return result;
};
Node.prototype._encodeValue = function encode(data, reporter, parent) {
const state = this._baseState;
// Decode root node
if (state.parent === null) return state.children[0]._encode(data, reporter || new Reporter());
let result = null;
// Set reporter to share it with a child class
this.reporter = reporter;
// Check if data is there
if (state.optional && data === undefined) {
if (state['default'] !== null) data = state['default'];
else return;
}
// Encode children first
let content = null;
let primitive = false;
if (state.any) {
// Anything that was given is translated to buffer
result = this._createEncoderBuffer(data);
} else if (state.choice) {
result = this._encodeChoice(data, reporter);
} else if (state.contains) {
content = this._getUse(state.contains, parent)._encode(data, reporter);
primitive = true;
} else if (state.children) {
content = state.children
.map(function (child) {
if (child._baseState.tag === 'null_') return child._encode(null, reporter, data);
if (child._baseState.key === null) return reporter.error('Child should have a key');
const prevKey = reporter.enterKey(child._baseState.key);
if (typeof data !== 'object') return reporter.error('Child expected, but input is not object');
const res = child._encode(data[child._baseState.key], reporter, data);
reporter.leaveKey(prevKey);
return res;
}, this)
.filter(function (child) {
return child;
});
content = this._createEncoderBuffer(content);
} else {
if (state.tag === 'seqof' || state.tag === 'setof') {
// TODO(indutny): this should be thrown on DSL level
if (!(state.args && state.args.length === 1)) return reporter.error('Too many args for : ' + state.tag);
if (!Array.isArray(data)) return reporter.error('seqof/setof, but data is not Array');
const child = this.clone();
child._baseState.implicit = null;
content = this._createEncoderBuffer(
data.map(function (item) {
const state = this._baseState;
return this._getUse(state.args[0], data)._encode(item, reporter);
}, child),
);
} else if (state.use !== null) {
result = this._getUse(state.use, parent)._encode(data, reporter);
} else {
content = this._encodePrimitive(state.tag, data);
primitive = true;
}
}
// Encode data itself
if (!state.any && state.choice === null) {
const tag = state.implicit !== null ? state.implicit : state.tag;
const cls = state.implicit === null ? 'universal' : 'context';
if (tag === null) {
if (state.use === null) reporter.error('Tag could be omitted only for .use()');
} else {
if (state.use === null) result = this._encodeComposite(tag, primitive, cls, content);
}
}
// Wrap in explicit
if (state.explicit !== null) result = this._encodeComposite(state.explicit, false, 'context', result);
return result;
};
Node.prototype._encodeChoice = function encodeChoice(data, reporter) {
const state = this._baseState;
const node = state.choice[data.type];
if (!node) {
assert(false, data.type + ' not found in ' + JSON.stringify(Object.keys(state.choice)));
}
return node._encode(data.value, reporter);
};
Node.prototype._encodePrimitive = function encodePrimitive(tag, data) {
const state = this._baseState;
if (/str$/.test(tag)) return this._encodeStr(data, tag);
else if (tag === 'objid' && state.args) return this._encodeObjid(data, state.reverseArgs[0], state.args[1]);
else if (tag === 'objid') return this._encodeObjid(data, null, null);
else if (tag === 'gentime' || tag === 'utctime') return this._encodeTime(data, tag);
else if (tag === 'null_') return this._encodeNull();
else if (tag === 'int' || tag === 'enum') return this._encodeInt(data, state.args && state.reverseArgs[0]);
else if (tag === 'bool') return this._encodeBool(data);
else if (tag === 'objDesc') return this._encodeStr(data, tag);
else throw new Error('Unsupported tag: ' + tag);
};
Node.prototype._isNumstr = function isNumstr(str) {
return /^[0-9 ]*$/.test(str);
};
Node.prototype._isPrintstr = function isPrintstr(str) {
return /^[A-Za-z0-9 '()+,-./:=?]*$/.test(str);
};
},
{ '../base/buffer': 3, '../base/reporter': 6, 'minimalistic-assert': 136 },
],
6: [
function (requirex, module, exports) {
'use strict';
const inherits = requirex('inherits');
function Reporter(options) {
this._reporterState = {
obj: null,
path: [],
options: options || {},
errors: [],
};
}
exports.Reporter = Reporter;
Reporter.prototype.isError = function isError(obj) {
return obj instanceof ReporterError;
};
Reporter.prototype.save = function save() {
const state = this._reporterState;
return { obj: state.obj, pathLen: state.path.length };
};
Reporter.prototype.restore = function restore(data) {
const state = this._reporterState;
state.obj = data.obj;
state.path = state.path.slice(0, data.pathLen);
};
Reporter.prototype.enterKey = function enterKey(key) {
return this._reporterState.path.push(key);
};
Reporter.prototype.exitKey = function exitKey(index) {
const state = this._reporterState;
state.path = state.path.slice(0, index - 1);
};
Reporter.prototype.leaveKey = function leaveKey(index, key, value) {
const state = this._reporterState;
this.exitKey(index);
if (state.obj !== null) state.obj[key] = value;
};
Reporter.prototype.path = function path() {
return this._reporterState.path.join('/');
};
Reporter.prototype.enterObject = function enterObject() {
const state = this._reporterState;
const prev = state.obj;
state.obj = {};
return prev;
};
Reporter.prototype.leaveObject = function leaveObject(prev) {
const state = this._reporterState;
const now = state.obj;
state.obj = prev;
return now;
};
Reporter.prototype.error = function error(msg) {
let err;
const state = this._reporterState;
const inherited = msg instanceof ReporterError;
if (inherited) {
err = msg;
} else {
err = new ReporterError(
state.path
.map(function (elem) {
return '[' + JSON.stringify(elem) + ']';
})
.join(''),
msg.message || msg,
msg.stack,
);
}
if (!state.options.partial) throw err;
if (!inherited) state.errors.push(err);
return err;
};
Reporter.prototype.wrapResult = function wrapResult(result) {
const state = this._reporterState;
if (!state.options.partial) return result;
return {
result: this.isError(result) ? null : result,
errors: state.errors,
};
};
function ReporterError(path, msg) {
this.path = path;
this.rethrow(msg);
}
inherits(ReporterError, Error);
ReporterError.prototype.rethrow = function rethrow(msg) {
this.message = msg + ' at: ' + (this.path || '(shallow)');
if (Error.captureStackTrace) Error.captureStackTrace(this, ReporterError);
if (!this.stack) {
try {
// IE only adds stack when thrown
throw new Error(this.message);
} catch (e) {
this.stack = e.stack;
}
}
return this;
};
},
{ inherits: 132 },
],
7: [
function (requirex, module, exports) {
'use strict';
// Helper
function reverse(map) {
const res = {};
Object.keys(map).forEach(function (key) {
// Convert key to integer if it is stringified
if ((key | 0) == key) key = key | 0;
const value = map[key];
res[value] = key;
});
return res;
}
exports.tagClass = {
0: 'universal',
1: 'application',
2: 'context',
3: 'private',
};
exports.tagClassByName = reverse(exports.tagClass);
exports.tag = {
0x00: 'end',
0x01: 'bool',
0x02: 'int',
0x03: 'bitstr',
0x04: 'octstr',
0x05: 'null_',
0x06: 'objid',
0x07: 'objDesc',
0x08: 'external',
0x09: 'real',
0x0a: 'enum',
0x0b: 'embed',
0x0c: 'utf8str',
0x0d: 'relativeOid',
0x10: 'seq',
0x11: 'set',
0x12: 'numstr',
0x13: 'printstr',
0x14: 't61str',
0x15: 'videostr',
0x16: 'ia5str',
0x17: 'utctime',
0x18: 'gentime',
0x19: 'graphstr',
0x1a: 'iso646str',
0x1b: 'genstr',
0x1c: 'unistr',
0x1d: 'charstr',
0x1e: 'bmpstr',
};
exports.tagByName = reverse(exports.tag);
},
{},
],
8: [
function (requirex, module, exports) {
'use strict';
const constants = exports;
// Helper
constants._reverse = function reverse(map) {
const res = {};
Object.keys(map).forEach(function (key) {
// Convert key to integer if it is stringified
if ((key | 0) == key) key = key | 0;
const value = map[key];
res[value] = key;
});
return res;
};
constants.der = requirex('./der');
},
{ './der': 7 },
],
9: [
function (requirex, module, exports) {
'use strict';
const inherits = requirex('inherits');
const bignum = requirex('bn.js');
const DecoderBuffer = requirex('../base/buffer').DecoderBuffer;
const Node = requirex('../base/node');
// Import DER constants
const der = requirex('../constants/der');
function DERDecoder(entity) {
this.enc = 'der';
this.name = entity.name;
this.entity = entity;
// Construct base tree
this.tree = new DERNode();
this.tree._init(entity.body);
}
module.exports = DERDecoder;
DERDecoder.prototype.decode = function decode(data, options) {
if (!DecoderBuffer.isDecoderBuffer(data)) {
data = new DecoderBuffer(data, options);
}
return this.tree._decode(data, options);
};
// Tree methods
function DERNode(parent) {
Node.call(this, 'der', parent);
}
inherits(DERNode, Node);
DERNode.prototype._peekTag = function peekTag(buffer, tag, any) {
if (buffer.isEmpty()) return false;
const state = buffer.save();
const decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"');
if (buffer.isError(decodedTag)) return decodedTag;
buffer.restore(state);
return decodedTag.tag === tag || decodedTag.tagStr === tag || decodedTag.tagStr + 'of' === tag || any;
};
DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) {
const decodedTag = derDecodeTag(buffer, 'Failed to decode tag of "' + tag + '"');
if (buffer.isError(decodedTag)) return decodedTag;
let len = derDecodeLen(buffer, decodedTag.primitive, 'Failed to get length of "' + tag + '"');
// Failure
if (buffer.isError(len)) return len;
if (!any && decodedTag.tag !== tag && decodedTag.tagStr !== tag && decodedTag.tagStr + 'of' !== tag) {
return buffer.error('Failed to match tag: "' + tag + '"');
}
if (decodedTag.primitive || len !== null) return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
// Indefinite length... find END tag
const state = buffer.save();
const res = this._skipUntilEnd(buffer, 'Failed to skip indefinite length body: "' + this.tag + '"');
if (buffer.isError(res)) return res;
len = buffer.offset - state.offset;
buffer.restore(state);
return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
};
DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) {
for (;;) {
const tag = derDecodeTag(buffer, fail);
if (buffer.isError(tag)) return tag;
const len = derDecodeLen(buffer, tag.primitive, fail);
if (buffer.isError(len)) return len;
let res;
if (tag.primitive || len !== null) res = buffer.skip(len);
else res = this._skipUntilEnd(buffer, fail);
// Failure
if (buffer.isError(res)) return res;
if (tag.tagStr === 'end') break;
}
};
DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder, options) {
const result = [];
while (!buffer.isEmpty()) {
const possibleEnd = this._peekTag(buffer, 'end');
if (buffer.isError(possibleEnd)) return possibleEnd;
const res = decoder.decode(buffer, 'der', options);
if (buffer.isError(res) && possibleEnd) break;
result.push(res);
}
return result;
};
DERNode.prototype._decodeStr = function decodeStr(buffer, tag) {
if (tag === 'bitstr') {
const unused = buffer.readUInt8();
if (buffer.isError(unused)) return unused;
return { unused: unused, data: buffer.raw() };
} else if (tag === 'bmpstr') {
const raw = buffer.raw();
if (raw.length % 2 === 1) return buffer.error('Decoding of string type: bmpstr length mismatch');
let str = '';
for (let i = 0; i < raw.length / 2; i++) {
str += String.fromCharCode(raw.readUInt16BE(i * 2));
}
return str;
} else if (tag === 'numstr') {
const numstr = buffer.raw().toString('ascii');
if (!this._isNumstr(numstr)) {
return buffer.error('Decoding of string type: ' + 'numstr unsupported characters');
}
return numstr;
} else if (tag === 'octstr') {
return buffer.raw();
} else if (tag === 'objDesc') {
return buffer.raw();
} else if (tag === 'printstr') {
const printstr = buffer.raw().toString('ascii');
if (!this._isPrintstr(printstr)) {
return buffer.error('Decoding of string type: ' + 'printstr unsupported characters');
}
return printstr;
} else if (/str$/.test(tag)) {
return buffer.raw().toString();
} else {
return buffer.error('Decoding of string type: ' + tag + ' unsupported');
}
};
DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) {
let result;
const identifiers = [];
let ident = 0;
let subident = 0;
while (!buffer.isEmpty()) {
subident = buffer.readUInt8();
ident <<= 7;
ident |= subident & 0x7f;
if ((subident & 0x80) === 0) {
identifiers.push(ident);
ident = 0;
}
}
if (subident & 0x80) identifiers.push(ident);
const first = (identifiers[0] / 40) | 0;
const second = identifiers[0] % 40;
if (relative) result = identifiers;
else result = [first, second].concat(identifiers.slice(1));
if (values) {
let tmp = values[result.join(' ')];
if (tmp === undefined) tmp = values[result.join('.')];
if (tmp !== undefined) result = tmp;
}
return result;
};
DERNode.prototype._decodeTime = function decodeTime(buffer, tag) {
const str = buffer.raw().toString();
let year;
let mon;
let day;
let hour;
let min;
let sec;
if (tag === 'gentime') {
year = str.slice(0, 4) | 0;
mon = str.slice(4, 6) | 0;
day = str.slice(6, 8) | 0;
hour = str.slice(8, 10) | 0;
min = str.slice(10, 12) | 0;
sec = str.slice(12, 14) | 0;
} else if (tag === 'utctime') {
year = str.slice(0, 2) | 0;
mon = str.slice(2, 4) | 0;
day = str.slice(4, 6) | 0;
hour = str.slice(6, 8) | 0;
min = str.slice(8, 10) | 0;
sec = str.slice(10, 12) | 0;
if (year < 70) year = 2000 + year;
else year = 1900 + year;
} else {
return buffer.error('Decoding ' + tag + ' time is not supported yet');
}
return Date.UTC(year, mon - 1, day, hour, min, sec, 0);
};
DERNode.prototype._decodeNull = function decodeNull() {
return null;
};
DERNode.prototype._decodeBool = function decodeBool(buffer) {
const res = buffer.readUInt8();
if (buffer.isError(res)) return res;
else return res !== 0;
};
DERNode.prototype._decodeInt = function decodeInt(buffer, values) {
// Bigint, return as it is (assume big endian)
const raw = buffer.raw();
let res = new bignum(raw);
if (values) res = values[res.toString(10)] || res;
return res;
};
DERNode.prototype._use = function use(entity, obj) {
if (typeof entity === 'function') entity = entity(obj);
return entity._getDecoder('der').tree;
};
// Utility methods
function derDecodeTag(buf, fail) {
let tag = buf.readUInt8(fail);
if (buf.isError(tag)) return tag;
const cls = der.tagClass[tag >> 6];
const primitive = (tag & 0x20) === 0;
// Multi-octet tag - load
if ((tag & 0x1f) === 0x1f) {
let oct = tag;
tag = 0;
while ((oct & 0x80) === 0x80) {
oct = buf.readUInt8(fail);
if (buf.isError(oct)) return oct;
tag <<= 7;
tag |= oct & 0x7f;
}
} else {
tag &= 0x1f;
}
const tagStr = der.tag[tag];
return {
cls: cls,
primitive: primitive,
tag: tag,
tagStr: tagStr,
};
}
function derDecodeLen(buf, primitive, fail) {
let len = buf.readUInt8(fail);
if (buf.isError(len)) return len;
// Indefinite form
if (!primitive && len === 0x80) return null;
// Definite form
if ((len & 0x80) === 0) {
// Short form
return len;
}
// Long form
const num = len & 0x7f;
if (num > 4) return buf.error('length octect is too long');
len = 0;
for (let i = 0; i < num; i++) {
len <<= 8;
const j = buf.readUInt8(fail);
if (buf.isError(j)) return j;
len |= j;
}
return len;
}
},
{ '../base/buffer': 3, '../base/node': 5, '../constants/der': 7, 'bn.js': 15, inherits: 132 },
],
10: [
function (requirex, module, exports) {
'use strict';
const decoders = exports;
decoders.der = requirex('./der');
decoders.pem = requirex('./pem');
},
{ './der': 9, './pem': 11 },
],
11: [
function (requirex, module, exports) {
'use strict';
const inherits = requirex('inherits');
const Buffer = requirex('safer-buffer').Buffer;
const DERDecoder = requirex('./der');
function PEMDecoder(entity) {
DERDecoder.call(this, entity);
this.enc = 'pem';
}
inherits(PEMDecoder, DERDecoder);
module.exports = PEMDecoder;
PEMDecoder.prototype.decode = function decode(data, options) {
const lines = data.toString().split(/[\r\n]+/g);
const label = options.label.toUpperCase();
const re = /^-----(BEGIN|END) ([^-]+)-----$/;
let start = -1;
let end = -1;
for (let i = 0; i < lines.length; i++) {
const match = lines[i].match(re);
if (match === null) continue;
if (match[2] !== label) continue;
if (start === -1) {
if (match[1] !== 'BEGIN') break;
start = i;
} else {
if (match[1] !== 'END') break;
end = i;
break;
}
}
if (start === -1 || end === -1) throw new Error('PEM section not found for: ' + label);
const base64 = lines.slice(start + 1, end).join('');
// Remove excessive symbols
base64.replace(/[^a-z0-9+/=]+/gi, '');
const input = Buffer.from(base64, 'base64');
return DERDecoder.prototype.decode.call(this, input, options);
};
},
{ './der': 9, inherits: 132, 'safer-buffer': 161 },
],
12: [
function (requirex, module, exports) {
'use strict';
const inherits = requirex('inherits');
const Buffer = requirex('safer-buffer').Buffer;
const Node = requirex('../base/node');
// Import DER constants
const der = requirex('../constants/der');
function DEREncoder(entity) {
this.enc = 'der';
this.name = entity.name;
this.entity = entity;
// Construct base tree
this.tree = new DERNode();
this.tree._init(entity.body);
}
module.exports = DEREncoder;
DEREncoder.prototype.encode = function encode(data, reporter) {
return this.tree._encode(data, reporter).join();
};
// Tree methods
function DERNode(parent) {
Node.call(this, 'der', parent);
}
inherits(DERNode, Node);
DERNode.prototype._encodeComposite = function encodeComposite(tag, primitive, cls, content) {
const encodedTag = encodeTag(tag, primitive, cls, this.reporter);
// Short form
if (content.length < 0x80) {
const header = Buffer.alloc(2);
header[0] = encodedTag;
header[1] = content.length;
return this._createEncoderBuffer([header, content]);
}
// Long form
// Count octets requirexd to store length
let lenOctets = 1;
for (let i = content.length; i >= 0x100; i >>= 8) lenOctets++;
const header = Buffer.alloc(1 + 1 + lenOctets);
header[0] = encodedTag;
header[1] = 0x80 | lenOctets;
for (let i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8) header[i] = j & 0xff;
return this._createEncoderBuffer([header, content]);
};
DERNode.prototype._encodeStr = function encodeStr(str, tag) {
if (tag === 'bitstr') {
return this._createEncoderBuffer([str.unused | 0, str.data]);
} else if (tag === 'bmpstr') {
const buf = Buffer.alloc(str.length * 2);
for (let i = 0; i < str.length; i++) {
buf.writeUInt16BE(str.charCodeAt(i), i * 2);
}
return this._createEncoderBuffer(buf);
} else if (tag === 'numstr') {
if (!this._isNumstr(str)) {
return this.reporter.error('Encoding of string type: numstr supports ' + 'only digits and space');
}
return this._createEncoderBuffer(str);
} else if (tag === 'printstr') {
if (!this._isPrintstr(str)) {
return this.reporter.error(
'Encoding of string type: printstr supports ' +
'only latin upper and lower case letters, ' +
'digits, space, apostrophe, left and rigth ' +