diff options
Diffstat (limited to 'ext/node/polyfills/_crypto/crypto_browserify/asn1.js')
9 files changed, 2022 insertions, 0 deletions
diff --git a/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/base/buffer.js b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/base/buffer.js new file mode 100644 index 000000000..cb01476cd --- /dev/null +++ b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/base/buffer.js @@ -0,0 +1,167 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2017 Fedor Indutny. All rights reserved. MIT license. + +import { Reporter } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/base/reporter.js"; +import { Buffer } from "internal:deno_node/polyfills/buffer.ts"; + +export 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); +DecoderBuffer.prototype = Object.create(Reporter.prototype, { + constructor: { + value: DecoderBuffer, + enumerable: false, + writable: true, + configurable: true, + }, +}); + +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); +}; + +export 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); + } +} + +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; +}; diff --git a/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/base/node.js b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/base/node.js new file mode 100644 index 000000000..027778155 --- /dev/null +++ b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/base/node.js @@ -0,0 +1,734 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2017 Fedor Indutny. All rights reserved. MIT license. + +import { Reporter } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/base/reporter.js"; +import { + DecoderBuffer, + EncoderBuffer, +} from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/base/buffer.js"; +import { assert } from "internal:deno_node/polyfills/_util/asserts.ts"; + +// 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", +]; + +export 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(); + } +} + +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(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); +}; diff --git a/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/base/reporter.js b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/base/reporter.js new file mode 100644 index 000000000..509f6c5b3 --- /dev/null +++ b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/base/reporter.js @@ -0,0 +1,138 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2017 Fedor Indutny. All rights reserved. MIT license. + +export function Reporter(options) { + this._reporterState = { + obj: null, + path: [], + options: options || {}, + errors: [], + }; +} + +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 = Object.create(Error.prototype, { + constructor: { + value: ReporterError, + enumerable: false, + writable: true, + configurable: true, + }, +}); + +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; +}; diff --git a/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/constants/der.js b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/constants/der.js new file mode 100644 index 000000000..807a97864 --- /dev/null +++ b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/constants/der.js @@ -0,0 +1,60 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2017 Fedor Indutny. All rights reserved. MIT license. + +// 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; +} + +export const tagClass = { + 0: "universal", + 1: "application", + 2: "context", + 3: "private", +}; +export const tagClassByName = reverse(tagClass); + +export const 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", +}; +export const tagByName = reverse(tag); diff --git a/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/decoders/der.js b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/decoders/der.js new file mode 100644 index 000000000..9ab811507 --- /dev/null +++ b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/decoders/der.js @@ -0,0 +1,386 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2017 Fedor Indutny. All rights reserved. MIT license. + +import bignum from "internal:deno_node/polyfills/_crypto/crypto_browserify/bn.js/bn.js"; +import { DecoderBuffer } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/base/buffer.js"; +import { Node } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/base/node.js"; +import * as der from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/constants/der.js"; + +export 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); +} + +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 = Object.create(Node.prototype, { + constructor: { + value: DERNode, + enumerable: false, + writable: true, + configurable: true, + }, +}); + +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; +} diff --git a/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/decoders/pem.js b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/decoders/pem.js new file mode 100644 index 000000000..3dedfb293 --- /dev/null +++ b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/decoders/pem.js @@ -0,0 +1,63 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2017 Fedor Indutny. All rights reserved. MIT license. + +import { Buffer } from "internal:deno_node/polyfills/buffer.ts"; + +import { DERDecoder } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/decoders/der.js"; + +export function PEMDecoder(entity) { + DERDecoder.call(this, entity); + this.enc = "pem"; +} +// inherits(PEMDecoder, DERDecoder); +PEMDecoder.prototype = Object.create(DERDecoder.prototype, { + constructor: { + value: PEMDecoder, + enumerable: false, + writable: true, + configurable: true, + }, +}); + +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); +}; diff --git a/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/encoders/der.js b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/encoders/der.js new file mode 100644 index 000000000..3f03ef347 --- /dev/null +++ b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/encoders/der.js @@ -0,0 +1,348 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2017 Fedor Indutny. All rights reserved. MIT license. + +import { Buffer } from "internal:deno_node/polyfills/buffer.ts"; +import { Node } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/base/node.js"; + +// Import DER constants +import * as der from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/constants/der.js"; + +export 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); +} + +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 = Object.create(Node.prototype, { + constructor: { + value: DERNode, + enumerable: false, + writable: true, + configurable: true, + }, +}); + +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 required 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 " + + "parenthesis, plus sign, comma, hyphen, " + + "dot, slash, colon, equal sign, " + + "question mark", + ); + } + return this._createEncoderBuffer(str); + } else if (/str$/.test(tag)) { + return this._createEncoderBuffer(str); + } else if (tag === "objDesc") { + return this._createEncoderBuffer(str); + } else { + return this.reporter.error( + "Encoding of string type: " + tag + + " unsupported", + ); + } +}; + +DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) { + if (typeof id === "string") { + if (!values) { + return this.reporter.error("string objid given, but no values map found"); + } + // deno-lint-ignore no-prototype-builtins + if (!values.hasOwnProperty(id)) { + return this.reporter.error("objid not found in values map"); + } + id = values[id].split(/[\s.]+/g); + for (let i = 0; i < id.length; i++) { + id[i] |= 0; + } + } else if (Array.isArray(id)) { + id = id.slice(); + for (let i = 0; i < id.length; i++) { + id[i] |= 0; + } + } + + if (!Array.isArray(id)) { + return this.reporter.error( + "objid() should be either array or string, " + + "got: " + JSON.stringify(id), + ); + } + + if (!relative) { + if (id[1] >= 40) { + return this.reporter.error("Second objid identifier OOB"); + } + id.splice(0, 2, id[0] * 40 + id[1]); + } + + // Count number of octets + let size = 0; + for (let i = 0; i < id.length; i++) { + let ident = id[i]; + for (size++; ident >= 0x80; ident >>= 7) { + size++; + } + } + + const objid = Buffer.alloc(size); + let offset = objid.length - 1; + for (let i = id.length - 1; i >= 0; i--) { + let ident = id[i]; + objid[offset--] = ident & 0x7f; + while ((ident >>= 7) > 0) { + objid[offset--] = 0x80 | (ident & 0x7f); + } + } + + return this._createEncoderBuffer(objid); +}; + +function two(num) { + if (num < 10) { + return "0" + num; + } else { + return num; + } +} + +DERNode.prototype._encodeTime = function encodeTime(time, tag) { + let str; + const date = new Date(time); + + if (tag === "gentime") { + str = [ + two(date.getUTCFullYear()), + two(date.getUTCMonth() + 1), + two(date.getUTCDate()), + two(date.getUTCHours()), + two(date.getUTCMinutes()), + two(date.getUTCSeconds()), + "Z", + ].join(""); + } else if (tag === "utctime") { + str = [ + two(date.getUTCFullYear() % 100), + two(date.getUTCMonth() + 1), + two(date.getUTCDate()), + two(date.getUTCHours()), + two(date.getUTCMinutes()), + two(date.getUTCSeconds()), + "Z", + ].join(""); + } else { + this.reporter.error("Encoding " + tag + " time is not supported yet"); + } + + return this._encodeStr(str, "octstr"); +}; + +DERNode.prototype._encodeNull = function encodeNull() { + return this._createEncoderBuffer(""); +}; + +DERNode.prototype._encodeInt = function encodeInt(num, values) { + if (typeof num === "string") { + if (!values) { + return this.reporter.error("String int or enum given, but no values map"); + } + // deno-lint-ignore no-prototype-builtins + if (!values.hasOwnProperty(num)) { + return this.reporter.error( + "Values map doesn't contain: " + + JSON.stringify(num), + ); + } + num = values[num]; + } + + // Bignum, assume big endian + if (typeof num !== "number" && !Buffer.isBuffer(num)) { + const numArray = num.toArray(); + if (!num.sign && numArray[0] & 0x80) { + numArray.unshift(0); + } + num = Buffer.from(numArray); + } + + if (Buffer.isBuffer(num)) { + let size = num.length; + if (num.length === 0) { + size++; + } + + const out = Buffer.alloc(size); + num.copy(out); + if (num.length === 0) { + out[0] = 0; + } + return this._createEncoderBuffer(out); + } + + if (num < 0x80) { + return this._createEncoderBuffer(num); + } + + if (num < 0x100) { + return this._createEncoderBuffer([0, num]); + } + + let size = 1; + for (let i = num; i >= 0x100; i >>= 8) { + size++; + } + + const out = new Array(size); + for (let i = out.length - 1; i >= 0; i--) { + out[i] = num & 0xff; + num >>= 8; + } + if (out[0] & 0x80) { + out.unshift(0); + } + + return this._createEncoderBuffer(Buffer.from(out)); +}; + +DERNode.prototype._encodeBool = function encodeBool(value) { + return this._createEncoderBuffer(value ? 0xff : 0); +}; + +DERNode.prototype._use = function use(entity, obj) { + if (typeof entity === "function") { + entity = entity(obj); + } + return entity._getEncoder("der").tree; +}; + +DERNode.prototype._skipDefault = function skipDefault( + dataBuffer, + reporter, + parent, +) { + const state = this._baseState; + let i; + if (state["default"] === null) { + return false; + } + + const data = dataBuffer.join(); + if (state.defaultBuffer === undefined) { + state.defaultBuffer = this._encodeValue(state["default"], reporter, parent) + .join(); + } + + if (data.length !== state.defaultBuffer.length) { + return false; + } + + for (i = 0; i < data.length; i++) { + if (data[i] !== state.defaultBuffer[i]) { + return false; + } + } + + return true; +}; + +// Utility methods + +function encodeTag(tag, primitive, cls, reporter) { + let res; + + if (tag === "seqof") { + tag = "seq"; + } else if (tag === "setof") { + tag = "set"; + } + + // deno-lint-ignore no-prototype-builtins + if (der.tagByName.hasOwnProperty(tag)) { + res = der.tagByName[tag]; + } else if (typeof tag === "number" && (tag | 0) === tag) { + res = tag; + } else { + return reporter.error("Unknown tag: " + tag); + } + + if (res >= 0x1f) { + return reporter.error("Multi-octet tag encoding unsupported"); + } + + if (!primitive) { + res |= 0x20; + } + + res |= der.tagClassByName[cls || "universal"] << 6; + + return res; +} diff --git a/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/encoders/pem.js b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/encoders/pem.js new file mode 100644 index 000000000..d2487e1ce --- /dev/null +++ b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/encoders/pem.js @@ -0,0 +1,30 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2017 Fedor Indutny. All rights reserved. MIT license. + +import { DEREncoder } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/encoders/der.js"; + +export function PEMEncoder(entity) { + DEREncoder.call(this, entity); + this.enc = "pem"; +} +// inherits(PEMEncoder, DEREncoder); +PEMEncoder.prototype = Object.create(DEREncoder.prototype, { + constructor: { + value: PEMEncoder, + enumerable: false, + writable: true, + configurable: true, + }, +}); + +PEMEncoder.prototype.encode = function encode(data, options) { + const buf = DEREncoder.prototype.encode.call(this, data); + + const p = buf.toString("base64"); + const out = ["-----BEGIN " + options.label + "-----"]; + for (let i = 0; i < p.length; i += 64) { + out.push(p.slice(i, i + 64)); + } + out.push("-----END " + options.label + "-----"); + return out.join("\n"); +}; diff --git a/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/mod.js b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/mod.js new file mode 100644 index 000000000..23cf79ca0 --- /dev/null +++ b/ext/node/polyfills/_crypto/crypto_browserify/asn1.js/mod.js @@ -0,0 +1,96 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2017 Fedor Indutny. All rights reserved. MIT license. + +import bignum from "internal:deno_node/polyfills/_crypto/crypto_browserify/bn.js/bn.js"; +import { Node } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/base/node.js"; +import { + DecoderBuffer, + EncoderBuffer, +} from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/base/buffer.js"; +import { Reporter } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/base/reporter.js"; +import { DEREncoder } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/encoders/der.js"; +import { PEMEncoder } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/encoders/pem.js"; +import { DERDecoder } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/decoders/der.js"; +import { PEMDecoder } from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/decoders/pem.js"; +import * as der from "internal:deno_node/polyfills/_crypto/crypto_browserify/asn1.js/constants/der.js"; + +export const base = { + DecoderBuffer, + EncoderBuffer, + Node, + Reporter, +}; +export const encoders = { der: DEREncoder, pem: PEMEncoder }; +export const decoders = { der: DERDecoder, pem: PEMDecoder }; +export const constants = { der }; +export { bignum }; + +export 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 = Object.create(Base.prototype, { + constructor: { + value: Generated, + enumerable: false, + writable: true, + configurable: true, + }, + }); + 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 + // deno-lint-ignore no-prototype-builtins + 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 + // deno-lint-ignore no-prototype-builtins + 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); +}; + +export default { + base, + bignum, + constants, + decoders, + define, + encoders, +}; |