Son CV dans un terminal web en Javascript!
https://terminal-cv.gregandev.fr
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
35938 lines
1.4 MiB
35938 lines
1.4 MiB
var $8C1kk$path = require("path"); |
|
var $8C1kk$stream = require("stream"); |
|
var $8C1kk$parcelsourcemap = require("@parcel/source-map"); |
|
var $8C1kk$parcellogger = require("@parcel/logger"); |
|
var $8C1kk$crypto = require("crypto"); |
|
var $8C1kk$os = require("os"); |
|
var $8C1kk$util = require("util"); |
|
var $8C1kk$fs = require("fs"); |
|
var $8C1kk$events = require("events"); |
|
var $8C1kk$parcelcodeframe = require("@parcel/codeframe"); |
|
var $8C1kk$parcelmarkdownansi = require("@parcel/markdown-ansi"); |
|
var $8C1kk$chalk = require("chalk"); |
|
var $8C1kk$tty = require("tty"); |
|
var $8C1kk$assert = require("assert"); |
|
var $8C1kk$parceldiagnostic = require("@parcel/diagnostic"); |
|
var $8C1kk$url = require("url"); |
|
var $8C1kk$child_process = require("child_process"); |
|
var $8C1kk$buffer = require("buffer"); |
|
var $8C1kk$parcelhash = require("@parcel/hash"); |
|
var $8C1kk$http = require("http"); |
|
var $8C1kk$https = require("https"); |
|
|
|
function $parcel$export(e, n, v, s) { |
|
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true}); |
|
} |
|
var $parcel$global = |
|
typeof globalThis !== 'undefined' |
|
? globalThis |
|
: typeof self !== 'undefined' |
|
? self |
|
: typeof window !== 'undefined' |
|
? window |
|
: typeof global !== 'undefined' |
|
? global |
|
: {}; |
|
function $parcel$interopDefault(a) { |
|
return a && a.__esModule ? a.default : a; |
|
} |
|
var $parcel$modules = {}; |
|
var $parcel$inits = {}; |
|
|
|
var parcelRequire = $parcel$global["parcelRequire0b48"]; |
|
if (parcelRequire == null) { |
|
parcelRequire = function(id) { |
|
if (id in $parcel$modules) { |
|
return $parcel$modules[id].exports; |
|
} |
|
if (id in $parcel$inits) { |
|
var init = $parcel$inits[id]; |
|
delete $parcel$inits[id]; |
|
var module = {id: id, exports: {}}; |
|
$parcel$modules[id] = module; |
|
init.call(module.exports, module, module.exports); |
|
return module.exports; |
|
} |
|
var err = new Error("Cannot find module '" + id + "'"); |
|
err.code = 'MODULE_NOT_FOUND'; |
|
throw err; |
|
}; |
|
|
|
parcelRequire.register = function register(id, init) { |
|
$parcel$inits[id] = init; |
|
}; |
|
|
|
$parcel$global["parcelRequire0b48"] = parcelRequire; |
|
} |
|
parcelRequire.register("iGlOy", function(module, exports) { |
|
/** |
|
* Node.js module for Forge. |
|
* |
|
* @author Dave Longley |
|
* |
|
* Copyright 2011-2016 Digital Bazaar, Inc. |
|
*/ module.exports = { |
|
// default options |
|
options: { |
|
usePureJavaScript: false |
|
} |
|
}; |
|
|
|
}); |
|
|
|
parcelRequire.register("ai0Z9", function(module, exports) { |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
module.exports = $iGlOy.md = $iGlOy.md || { |
|
}; |
|
$iGlOy.md.algorithms = $iGlOy.md.algorithms || { |
|
}; |
|
|
|
}); |
|
|
|
parcelRequire.register("4997P", function(module, exports) { |
|
'use strict'; |
|
|
|
|
|
var $2zM8v = parcelRequire("2zM8v"); |
|
|
|
var $lKEF0 = parcelRequire("lKEF0"); |
|
|
|
var $5MQDC = parcelRequire("5MQDC"); |
|
|
|
var $7XmS6 = parcelRequire("7XmS6"); |
|
const $304f14c7e435813f$var$isObject = (val)=>val && typeof val === 'object' && !Array.isArray(val) |
|
; |
|
/** |
|
* Creates a matcher function from one or more glob patterns. The |
|
* returned function takes a string to match as its first argument, |
|
* and returns true if the string is a match. The returned matcher |
|
* function also takes a boolean as the second argument that, when true, |
|
* returns an object with additional information. |
|
* |
|
* ```js |
|
* const picomatch = require('picomatch'); |
|
* // picomatch(glob[, options]); |
|
* |
|
* const isMatch = picomatch('*.!(*a)'); |
|
* console.log(isMatch('a.a')); //=> false |
|
* console.log(isMatch('a.b')); //=> true |
|
* ``` |
|
* @name picomatch |
|
* @param {String|Array} `globs` One or more glob patterns. |
|
* @param {Object=} `options` |
|
* @return {Function=} Returns a matcher function. |
|
* @api public |
|
*/ const $304f14c7e435813f$var$picomatch = (glob, options, returnState = false)=>{ |
|
if (Array.isArray(glob)) { |
|
const fns = glob.map((input)=>$304f14c7e435813f$var$picomatch(input, options, returnState) |
|
); |
|
const arrayMatcher = (str)=>{ |
|
for (const isMatch of fns){ |
|
const state = isMatch(str); |
|
if (state) return state; |
|
} |
|
return false; |
|
}; |
|
return arrayMatcher; |
|
} |
|
const isState = $304f14c7e435813f$var$isObject(glob) && glob.tokens && glob.input; |
|
if (glob === '' || typeof glob !== 'string' && !isState) throw new TypeError('Expected pattern to be a non-empty string'); |
|
const opts = options || { |
|
}; |
|
const posix = $5MQDC.isWindows(options); |
|
const regex = isState ? $304f14c7e435813f$var$picomatch.compileRe(glob, options) : $304f14c7e435813f$var$picomatch.makeRe(glob, options, false, true); |
|
const state1 = regex.state; |
|
delete regex.state; |
|
let isIgnored = ()=>false |
|
; |
|
if (opts.ignore) { |
|
const ignoreOpts = { |
|
...options, |
|
ignore: null, |
|
onMatch: null, |
|
onResult: null |
|
}; |
|
isIgnored = $304f14c7e435813f$var$picomatch(opts.ignore, ignoreOpts, returnState); |
|
} |
|
const matcher = (input, returnObject = false)=>{ |
|
const { isMatch: isMatch , match: match , output: output } = $304f14c7e435813f$var$picomatch.test(input, regex, options, { |
|
glob: glob, |
|
posix: posix |
|
}); |
|
const result = { |
|
glob: glob, |
|
state: state1, |
|
regex: regex, |
|
posix: posix, |
|
input: input, |
|
output: output, |
|
match: match, |
|
isMatch: isMatch |
|
}; |
|
if (typeof opts.onResult === 'function') opts.onResult(result); |
|
if (isMatch === false) { |
|
result.isMatch = false; |
|
return returnObject ? result : false; |
|
} |
|
if (isIgnored(input)) { |
|
if (typeof opts.onIgnore === 'function') opts.onIgnore(result); |
|
result.isMatch = false; |
|
return returnObject ? result : false; |
|
} |
|
if (typeof opts.onMatch === 'function') opts.onMatch(result); |
|
return returnObject ? result : true; |
|
}; |
|
if (returnState) matcher.state = state1; |
|
return matcher; |
|
}; |
|
/** |
|
* Test `input` with the given `regex`. This is used by the main |
|
* `picomatch()` function to test the input string. |
|
* |
|
* ```js |
|
* const picomatch = require('picomatch'); |
|
* // picomatch.test(input, regex[, options]); |
|
* |
|
* console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/)); |
|
* // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' } |
|
* ``` |
|
* @param {String} `input` String to test. |
|
* @param {RegExp} `regex` |
|
* @return {Object} Returns an object with matching info. |
|
* @api public |
|
*/ $304f14c7e435813f$var$picomatch.test = (input, regex, options, { glob: glob , posix: posix } = { |
|
})=>{ |
|
if (typeof input !== 'string') throw new TypeError('Expected input to be a string'); |
|
if (input === '') return { |
|
isMatch: false, |
|
output: '' |
|
}; |
|
const opts = options || { |
|
}; |
|
const format = opts.format || (posix ? $5MQDC.toPosixSlashes : null); |
|
let match = input === glob; |
|
let output = match && format ? format(input) : input; |
|
if (match === false) { |
|
output = format ? format(input) : input; |
|
match = output === glob; |
|
} |
|
if (match === false || opts.capture === true) { |
|
if (opts.matchBase === true || opts.basename === true) match = $304f14c7e435813f$var$picomatch.matchBase(input, regex, options, posix); |
|
else match = regex.exec(output); |
|
} |
|
return { |
|
isMatch: Boolean(match), |
|
match: match, |
|
output: output |
|
}; |
|
}; |
|
/** |
|
* Match the basename of a filepath. |
|
* |
|
* ```js |
|
* const picomatch = require('picomatch'); |
|
* // picomatch.matchBase(input, glob[, options]); |
|
* console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true |
|
* ``` |
|
* @param {String} `input` String to test. |
|
* @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe). |
|
* @return {Boolean} |
|
* @api public |
|
*/ $304f14c7e435813f$var$picomatch.matchBase = (input, glob, options, posix = $5MQDC.isWindows(options))=>{ |
|
const regex = glob instanceof RegExp ? glob : $304f14c7e435813f$var$picomatch.makeRe(glob, options); |
|
return regex.test($8C1kk$path.basename(input)); |
|
}; |
|
/** |
|
* Returns true if **any** of the given glob `patterns` match the specified `string`. |
|
* |
|
* ```js |
|
* const picomatch = require('picomatch'); |
|
* // picomatch.isMatch(string, patterns[, options]); |
|
* |
|
* console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true |
|
* console.log(picomatch.isMatch('a.a', 'b.*')); //=> false |
|
* ``` |
|
* @param {String|Array} str The string to test. |
|
* @param {String|Array} patterns One or more glob patterns to use for matching. |
|
* @param {Object} [options] See available [options](#options). |
|
* @return {Boolean} Returns true if any patterns match `str` |
|
* @api public |
|
*/ $304f14c7e435813f$var$picomatch.isMatch = (str, patterns, options)=>$304f14c7e435813f$var$picomatch(patterns, options)(str) |
|
; |
|
/** |
|
* Parse a glob pattern to create the source string for a regular |
|
* expression. |
|
* |
|
* ```js |
|
* const picomatch = require('picomatch'); |
|
* const result = picomatch.parse(pattern[, options]); |
|
* ``` |
|
* @param {String} `pattern` |
|
* @param {Object} `options` |
|
* @return {Object} Returns an object with useful properties and output to be used as a regex source string. |
|
* @api public |
|
*/ $304f14c7e435813f$var$picomatch.parse = (pattern, options)=>{ |
|
if (Array.isArray(pattern)) return pattern.map((p)=>$304f14c7e435813f$var$picomatch.parse(p, options) |
|
); |
|
return $lKEF0(pattern, { |
|
...options, |
|
fastpaths: false |
|
}); |
|
}; |
|
/** |
|
* Scan a glob pattern to separate the pattern into segments. |
|
* |
|
* ```js |
|
* const picomatch = require('picomatch'); |
|
* // picomatch.scan(input[, options]); |
|
* |
|
* const result = picomatch.scan('!./foo/*.js'); |
|
* console.log(result); |
|
* { prefix: '!./', |
|
* input: '!./foo/*.js', |
|
* start: 3, |
|
* base: 'foo', |
|
* glob: '*.js', |
|
* isBrace: false, |
|
* isBracket: false, |
|
* isGlob: true, |
|
* isExtglob: false, |
|
* isGlobstar: false, |
|
* negated: true } |
|
* ``` |
|
* @param {String} `input` Glob pattern to scan. |
|
* @param {Object} `options` |
|
* @return {Object} Returns an object with |
|
* @api public |
|
*/ $304f14c7e435813f$var$picomatch.scan = (input, options)=>$2zM8v(input, options) |
|
; |
|
/** |
|
* Compile a regular expression from the `state` object returned by the |
|
* [parse()](#parse) method. |
|
* |
|
* @param {Object} `state` |
|
* @param {Object} `options` |
|
* @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser. |
|
* @param {Boolean} `returnState` Adds the state to a `state` property on the returned regex. Useful for implementors and debugging. |
|
* @return {RegExp} |
|
* @api public |
|
*/ $304f14c7e435813f$var$picomatch.compileRe = (state, options, returnOutput = false, returnState = false)=>{ |
|
if (returnOutput === true) return state.output; |
|
const opts = options || { |
|
}; |
|
const prepend = opts.contains ? '' : '^'; |
|
const append = opts.contains ? '' : '$'; |
|
let source = `${prepend}(?:${state.output})${append}`; |
|
if (state && state.negated === true) source = `^(?!${source}).*$`; |
|
const regex = $304f14c7e435813f$var$picomatch.toRegex(source, options); |
|
if (returnState === true) regex.state = state; |
|
return regex; |
|
}; |
|
/** |
|
* Create a regular expression from a parsed glob pattern. |
|
* |
|
* ```js |
|
* const picomatch = require('picomatch'); |
|
* const state = picomatch.parse('*.js'); |
|
* // picomatch.compileRe(state[, options]); |
|
* |
|
* console.log(picomatch.compileRe(state)); |
|
* //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ |
|
* ``` |
|
* @param {String} `state` The object returned from the `.parse` method. |
|
* @param {Object} `options` |
|
* @param {Boolean} `returnOutput` Implementors may use this argument to return the compiled output, instead of a regular expression. This is not exposed on the options to prevent end-users from mutating the result. |
|
* @param {Boolean} `returnState` Implementors may use this argument to return the state from the parsed glob with the returned regular expression. |
|
* @return {RegExp} Returns a regex created from the given pattern. |
|
* @api public |
|
*/ $304f14c7e435813f$var$picomatch.makeRe = (input, options = { |
|
}, returnOutput = false, returnState = false)=>{ |
|
if (!input || typeof input !== 'string') throw new TypeError('Expected a non-empty string'); |
|
let parsed = { |
|
negated: false, |
|
fastpaths: true |
|
}; |
|
if (options.fastpaths !== false && (input[0] === '.' || input[0] === '*')) parsed.output = $lKEF0.fastpaths(input, options); |
|
if (!parsed.output) parsed = $lKEF0(input, options); |
|
return $304f14c7e435813f$var$picomatch.compileRe(parsed, options, returnOutput, returnState); |
|
}; |
|
/** |
|
* Create a regular expression from the given regex source string. |
|
* |
|
* ```js |
|
* const picomatch = require('picomatch'); |
|
* // picomatch.toRegex(source[, options]); |
|
* |
|
* const { output } = picomatch.parse('*.js'); |
|
* console.log(picomatch.toRegex(output)); |
|
* //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ |
|
* ``` |
|
* @param {String} `source` Regular expression source string. |
|
* @param {Object} `options` |
|
* @return {RegExp} |
|
* @api public |
|
*/ $304f14c7e435813f$var$picomatch.toRegex = (source, options)=>{ |
|
try { |
|
const opts = options || { |
|
}; |
|
return new RegExp(source, opts.flags || (opts.nocase ? 'i' : '')); |
|
} catch (err) { |
|
if (options && options.debug === true) throw err; |
|
return /$^/; |
|
} |
|
}; |
|
/** |
|
* Picomatch constants. |
|
* @return {Object} |
|
*/ $304f14c7e435813f$var$picomatch.constants = $7XmS6; |
|
/** |
|
* Expose "picomatch" |
|
*/ module.exports = $304f14c7e435813f$var$picomatch; |
|
|
|
}); |
|
parcelRequire.register("2zM8v", function(module, exports) { |
|
'use strict'; |
|
|
|
var $5MQDC = parcelRequire("5MQDC"); |
|
|
|
var $7XmS6 = parcelRequire("7XmS6"); |
|
var $1e0430853cfb927a$require$CHAR_ASTERISK = $7XmS6.CHAR_ASTERISK; |
|
var $1e0430853cfb927a$require$CHAR_AT = $7XmS6.CHAR_AT; |
|
var $1e0430853cfb927a$require$CHAR_BACKWARD_SLASH = $7XmS6.CHAR_BACKWARD_SLASH; |
|
var $1e0430853cfb927a$require$CHAR_COMMA = $7XmS6.CHAR_COMMA; |
|
var $1e0430853cfb927a$require$CHAR_DOT = $7XmS6.CHAR_DOT; |
|
var $1e0430853cfb927a$require$CHAR_EXCLAMATION_MARK = $7XmS6.CHAR_EXCLAMATION_MARK; |
|
var $1e0430853cfb927a$require$CHAR_FORWARD_SLASH = $7XmS6.CHAR_FORWARD_SLASH; |
|
var $1e0430853cfb927a$require$CHAR_LEFT_CURLY_BRACE = $7XmS6.CHAR_LEFT_CURLY_BRACE; |
|
var $1e0430853cfb927a$require$CHAR_LEFT_PARENTHESES = $7XmS6.CHAR_LEFT_PARENTHESES; |
|
var $1e0430853cfb927a$require$CHAR_LEFT_SQUARE_BRACKET = $7XmS6.CHAR_LEFT_SQUARE_BRACKET; |
|
var $1e0430853cfb927a$require$CHAR_PLUS = $7XmS6.CHAR_PLUS; |
|
var $1e0430853cfb927a$require$CHAR_QUESTION_MARK = $7XmS6.CHAR_QUESTION_MARK; |
|
var $1e0430853cfb927a$require$CHAR_RIGHT_CURLY_BRACE = $7XmS6.CHAR_RIGHT_CURLY_BRACE; |
|
var $1e0430853cfb927a$require$CHAR_RIGHT_PARENTHESES = $7XmS6.CHAR_RIGHT_PARENTHESES; |
|
var $1e0430853cfb927a$require$CHAR_RIGHT_SQUARE_BRACKET = $7XmS6.CHAR_RIGHT_SQUARE_BRACKET; |
|
const $1e0430853cfb927a$var$isPathSeparator = (code)=>{ |
|
return code === $1e0430853cfb927a$require$CHAR_FORWARD_SLASH || code === $1e0430853cfb927a$require$CHAR_BACKWARD_SLASH; |
|
}; |
|
const $1e0430853cfb927a$var$depth = (token)=>{ |
|
if (token.isPrefix !== true) token.depth = token.isGlobstar ? Infinity : 1; |
|
}; |
|
/** |
|
* Quickly scans a glob pattern and returns an object with a handful of |
|
* useful properties, like `isGlob`, `path` (the leading non-glob, if it exists), |
|
* `glob` (the actual pattern), `negated` (true if the path starts with `!` but not |
|
* with `!(`) and `negatedExtglob` (true if the path starts with `!(`). |
|
* |
|
* ```js |
|
* const pm = require('picomatch'); |
|
* console.log(pm.scan('foo/bar/*.js')); |
|
* { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' } |
|
* ``` |
|
* @param {String} `str` |
|
* @param {Object} `options` |
|
* @return {Object} Returns an object with tokens and regex source string. |
|
* @api public |
|
*/ const $1e0430853cfb927a$var$scan = (input, options)=>{ |
|
const opts = options || { |
|
}; |
|
const length = input.length - 1; |
|
const scanToEnd = opts.parts === true || opts.scanToEnd === true; |
|
const slashes = []; |
|
const tokens = []; |
|
const parts = []; |
|
let str = input; |
|
let index = -1; |
|
let start = 0; |
|
let lastIndex = 0; |
|
let isBrace = false; |
|
let isBracket = false; |
|
let isGlob = false; |
|
let isExtglob = false; |
|
let isGlobstar = false; |
|
let braceEscaped = false; |
|
let backslashes = false; |
|
let negated = false; |
|
let negatedExtglob = false; |
|
let finished = false; |
|
let braces = 0; |
|
let prev; |
|
let code; |
|
let token = { |
|
value: '', |
|
depth: 0, |
|
isGlob: false |
|
}; |
|
const eos = ()=>index >= length |
|
; |
|
const peek = ()=>str.charCodeAt(index + 1) |
|
; |
|
const advance = ()=>{ |
|
prev = code; |
|
return str.charCodeAt(++index); |
|
}; |
|
while(index < length){ |
|
code = advance(); |
|
let next; |
|
if (code === $1e0430853cfb927a$require$CHAR_BACKWARD_SLASH) { |
|
backslashes = token.backslashes = true; |
|
code = advance(); |
|
if (code === $1e0430853cfb927a$require$CHAR_LEFT_CURLY_BRACE) braceEscaped = true; |
|
continue; |
|
} |
|
if (braceEscaped === true || code === $1e0430853cfb927a$require$CHAR_LEFT_CURLY_BRACE) { |
|
braces++; |
|
while(eos() !== true && (code = advance())){ |
|
if (code === $1e0430853cfb927a$require$CHAR_BACKWARD_SLASH) { |
|
backslashes = token.backslashes = true; |
|
advance(); |
|
continue; |
|
} |
|
if (code === $1e0430853cfb927a$require$CHAR_LEFT_CURLY_BRACE) { |
|
braces++; |
|
continue; |
|
} |
|
if (braceEscaped !== true && code === $1e0430853cfb927a$require$CHAR_DOT && (code = advance()) === $1e0430853cfb927a$require$CHAR_DOT) { |
|
isBrace = token.isBrace = true; |
|
isGlob = token.isGlob = true; |
|
finished = true; |
|
if (scanToEnd === true) continue; |
|
break; |
|
} |
|
if (braceEscaped !== true && code === $1e0430853cfb927a$require$CHAR_COMMA) { |
|
isBrace = token.isBrace = true; |
|
isGlob = token.isGlob = true; |
|
finished = true; |
|
if (scanToEnd === true) continue; |
|
break; |
|
} |
|
if (code === $1e0430853cfb927a$require$CHAR_RIGHT_CURLY_BRACE) { |
|
braces--; |
|
if (braces === 0) { |
|
braceEscaped = false; |
|
isBrace = token.isBrace = true; |
|
finished = true; |
|
break; |
|
} |
|
} |
|
} |
|
if (scanToEnd === true) continue; |
|
break; |
|
} |
|
if (code === $1e0430853cfb927a$require$CHAR_FORWARD_SLASH) { |
|
slashes.push(index); |
|
tokens.push(token); |
|
token = { |
|
value: '', |
|
depth: 0, |
|
isGlob: false |
|
}; |
|
if (finished === true) continue; |
|
if (prev === $1e0430853cfb927a$require$CHAR_DOT && index === start + 1) { |
|
start += 2; |
|
continue; |
|
} |
|
lastIndex = index + 1; |
|
continue; |
|
} |
|
if (opts.noext !== true) { |
|
const isExtglobChar = code === $1e0430853cfb927a$require$CHAR_PLUS || code === $1e0430853cfb927a$require$CHAR_AT || code === $1e0430853cfb927a$require$CHAR_ASTERISK || code === $1e0430853cfb927a$require$CHAR_QUESTION_MARK || code === $1e0430853cfb927a$require$CHAR_EXCLAMATION_MARK; |
|
if (isExtglobChar === true && peek() === $1e0430853cfb927a$require$CHAR_LEFT_PARENTHESES) { |
|
isGlob = token.isGlob = true; |
|
isExtglob = token.isExtglob = true; |
|
finished = true; |
|
if (code === $1e0430853cfb927a$require$CHAR_EXCLAMATION_MARK && index === start) negatedExtglob = true; |
|
if (scanToEnd === true) { |
|
while(eos() !== true && (code = advance())){ |
|
if (code === $1e0430853cfb927a$require$CHAR_BACKWARD_SLASH) { |
|
backslashes = token.backslashes = true; |
|
code = advance(); |
|
continue; |
|
} |
|
if (code === $1e0430853cfb927a$require$CHAR_RIGHT_PARENTHESES) { |
|
isGlob = token.isGlob = true; |
|
finished = true; |
|
break; |
|
} |
|
} |
|
continue; |
|
} |
|
break; |
|
} |
|
} |
|
if (code === $1e0430853cfb927a$require$CHAR_ASTERISK) { |
|
if (prev === $1e0430853cfb927a$require$CHAR_ASTERISK) isGlobstar = token.isGlobstar = true; |
|
isGlob = token.isGlob = true; |
|
finished = true; |
|
if (scanToEnd === true) continue; |
|
break; |
|
} |
|
if (code === $1e0430853cfb927a$require$CHAR_QUESTION_MARK) { |
|
isGlob = token.isGlob = true; |
|
finished = true; |
|
if (scanToEnd === true) continue; |
|
break; |
|
} |
|
if (code === $1e0430853cfb927a$require$CHAR_LEFT_SQUARE_BRACKET) { |
|
while(eos() !== true && (next = advance())){ |
|
if (next === $1e0430853cfb927a$require$CHAR_BACKWARD_SLASH) { |
|
backslashes = token.backslashes = true; |
|
advance(); |
|
continue; |
|
} |
|
if (next === $1e0430853cfb927a$require$CHAR_RIGHT_SQUARE_BRACKET) { |
|
isBracket = token.isBracket = true; |
|
isGlob = token.isGlob = true; |
|
finished = true; |
|
break; |
|
} |
|
} |
|
if (scanToEnd === true) continue; |
|
break; |
|
} |
|
if (opts.nonegate !== true && code === $1e0430853cfb927a$require$CHAR_EXCLAMATION_MARK && index === start) { |
|
negated = token.negated = true; |
|
start++; |
|
continue; |
|
} |
|
if (opts.noparen !== true && code === $1e0430853cfb927a$require$CHAR_LEFT_PARENTHESES) { |
|
isGlob = token.isGlob = true; |
|
if (scanToEnd === true) { |
|
while(eos() !== true && (code = advance())){ |
|
if (code === $1e0430853cfb927a$require$CHAR_LEFT_PARENTHESES) { |
|
backslashes = token.backslashes = true; |
|
code = advance(); |
|
continue; |
|
} |
|
if (code === $1e0430853cfb927a$require$CHAR_RIGHT_PARENTHESES) { |
|
finished = true; |
|
break; |
|
} |
|
} |
|
continue; |
|
} |
|
break; |
|
} |
|
if (isGlob === true) { |
|
finished = true; |
|
if (scanToEnd === true) continue; |
|
break; |
|
} |
|
} |
|
if (opts.noext === true) { |
|
isExtglob = false; |
|
isGlob = false; |
|
} |
|
let base = str; |
|
let prefix = ''; |
|
let glob = ''; |
|
if (start > 0) { |
|
prefix = str.slice(0, start); |
|
str = str.slice(start); |
|
lastIndex -= start; |
|
} |
|
if (base && isGlob === true && lastIndex > 0) { |
|
base = str.slice(0, lastIndex); |
|
glob = str.slice(lastIndex); |
|
} else if (isGlob === true) { |
|
base = ''; |
|
glob = str; |
|
} else base = str; |
|
if (base && base !== '' && base !== '/' && base !== str) { |
|
if ($1e0430853cfb927a$var$isPathSeparator(base.charCodeAt(base.length - 1))) base = base.slice(0, -1); |
|
} |
|
if (opts.unescape === true) { |
|
if (glob) glob = $5MQDC.removeBackslashes(glob); |
|
if (base && backslashes === true) base = $5MQDC.removeBackslashes(base); |
|
} |
|
const state = { |
|
prefix: prefix, |
|
input: input, |
|
start: start, |
|
base: base, |
|
glob: glob, |
|
isBrace: isBrace, |
|
isBracket: isBracket, |
|
isGlob: isGlob, |
|
isExtglob: isExtglob, |
|
isGlobstar: isGlobstar, |
|
negated: negated, |
|
negatedExtglob: negatedExtglob |
|
}; |
|
if (opts.tokens === true) { |
|
state.maxDepth = 0; |
|
if (!$1e0430853cfb927a$var$isPathSeparator(code)) tokens.push(token); |
|
state.tokens = tokens; |
|
} |
|
if (opts.parts === true || opts.tokens === true) { |
|
let prevIndex; |
|
for(let idx = 0; idx < slashes.length; idx++){ |
|
const n = prevIndex ? prevIndex + 1 : start; |
|
const i = slashes[idx]; |
|
const value = input.slice(n, i); |
|
if (opts.tokens) { |
|
if (idx === 0 && start !== 0) { |
|
tokens[idx].isPrefix = true; |
|
tokens[idx].value = prefix; |
|
} else tokens[idx].value = value; |
|
$1e0430853cfb927a$var$depth(tokens[idx]); |
|
state.maxDepth += tokens[idx].depth; |
|
} |
|
if (idx !== 0 || value !== '') parts.push(value); |
|
prevIndex = i; |
|
} |
|
if (prevIndex && prevIndex + 1 < input.length) { |
|
const value = input.slice(prevIndex + 1); |
|
parts.push(value); |
|
if (opts.tokens) { |
|
tokens[tokens.length - 1].value = value; |
|
$1e0430853cfb927a$var$depth(tokens[tokens.length - 1]); |
|
state.maxDepth += tokens[tokens.length - 1].depth; |
|
} |
|
} |
|
state.slashes = slashes; |
|
state.parts = parts; |
|
} |
|
return state; |
|
}; |
|
module.exports = $1e0430853cfb927a$var$scan; |
|
|
|
}); |
|
parcelRequire.register("5MQDC", function(module, exports) { |
|
|
|
$parcel$export(module.exports, "isObject", () => $436a44408af843d4$export$a6cdc56e425d0d0a, (v) => $436a44408af843d4$export$a6cdc56e425d0d0a = v); |
|
$parcel$export(module.exports, "hasRegexChars", () => $436a44408af843d4$export$6540a013a39bb50d, (v) => $436a44408af843d4$export$6540a013a39bb50d = v); |
|
$parcel$export(module.exports, "escapeRegex", () => $436a44408af843d4$export$104ed90cc1a13451, (v) => $436a44408af843d4$export$104ed90cc1a13451 = v); |
|
$parcel$export(module.exports, "toPosixSlashes", () => $436a44408af843d4$export$e610e037975797ee, (v) => $436a44408af843d4$export$e610e037975797ee = v); |
|
$parcel$export(module.exports, "removeBackslashes", () => $436a44408af843d4$export$f403de0a7ba7a743, (v) => $436a44408af843d4$export$f403de0a7ba7a743 = v); |
|
$parcel$export(module.exports, "supportsLookbehinds", () => $436a44408af843d4$export$bcf709e5e3483cdb, (v) => $436a44408af843d4$export$bcf709e5e3483cdb = v); |
|
$parcel$export(module.exports, "isWindows", () => $436a44408af843d4$export$f993c945890e93ba, (v) => $436a44408af843d4$export$f993c945890e93ba = v); |
|
$parcel$export(module.exports, "escapeLast", () => $436a44408af843d4$export$13d0f4185f159c8, (v) => $436a44408af843d4$export$13d0f4185f159c8 = v); |
|
$parcel$export(module.exports, "removePrefix", () => $436a44408af843d4$export$f2888183a34644d4, (v) => $436a44408af843d4$export$f2888183a34644d4 = v); |
|
$parcel$export(module.exports, "wrapOutput", () => $436a44408af843d4$export$25bddda26836484b, (v) => $436a44408af843d4$export$25bddda26836484b = v); |
|
var $436a44408af843d4$export$a6cdc56e425d0d0a; |
|
var $436a44408af843d4$export$6540a013a39bb50d; |
|
var $436a44408af843d4$export$a92319f7ab133839; |
|
var $436a44408af843d4$export$104ed90cc1a13451; |
|
var $436a44408af843d4$export$e610e037975797ee; |
|
var $436a44408af843d4$export$f403de0a7ba7a743; |
|
var $436a44408af843d4$export$bcf709e5e3483cdb; |
|
var $436a44408af843d4$export$f993c945890e93ba; |
|
var $436a44408af843d4$export$13d0f4185f159c8; |
|
var $436a44408af843d4$export$f2888183a34644d4; |
|
var $436a44408af843d4$export$25bddda26836484b; |
|
'use strict'; |
|
|
|
const $436a44408af843d4$var$win32 = process.platform === 'win32'; |
|
|
|
var $7XmS6 = parcelRequire("7XmS6"); |
|
var $436a44408af843d4$require$REGEX_BACKSLASH = $7XmS6.REGEX_BACKSLASH; |
|
var $436a44408af843d4$require$REGEX_REMOVE_BACKSLASH = $7XmS6.REGEX_REMOVE_BACKSLASH; |
|
var $436a44408af843d4$require$REGEX_SPECIAL_CHARS = $7XmS6.REGEX_SPECIAL_CHARS; |
|
var $436a44408af843d4$require$REGEX_SPECIAL_CHARS_GLOBAL = $7XmS6.REGEX_SPECIAL_CHARS_GLOBAL; |
|
$436a44408af843d4$export$a6cdc56e425d0d0a = (val)=>val !== null && typeof val === 'object' && !Array.isArray(val) |
|
; |
|
$436a44408af843d4$export$6540a013a39bb50d = (str)=>$436a44408af843d4$require$REGEX_SPECIAL_CHARS.test(str) |
|
; |
|
$436a44408af843d4$export$a92319f7ab133839 = (str)=>str.length === 1 && $436a44408af843d4$export$6540a013a39bb50d(str) |
|
; |
|
$436a44408af843d4$export$104ed90cc1a13451 = (str)=>str.replace($436a44408af843d4$require$REGEX_SPECIAL_CHARS_GLOBAL, '\\$1') |
|
; |
|
$436a44408af843d4$export$e610e037975797ee = (str)=>str.replace($436a44408af843d4$require$REGEX_BACKSLASH, '/') |
|
; |
|
$436a44408af843d4$export$f403de0a7ba7a743 = (str)=>{ |
|
return str.replace($436a44408af843d4$require$REGEX_REMOVE_BACKSLASH, (match)=>{ |
|
return match === '\\' ? '' : match; |
|
}); |
|
}; |
|
$436a44408af843d4$export$bcf709e5e3483cdb = ()=>{ |
|
const segs = process.version.slice(1).split('.').map(Number); |
|
if (segs.length === 3 && segs[0] >= 9 || segs[0] === 8 && segs[1] >= 10) return true; |
|
return false; |
|
}; |
|
$436a44408af843d4$export$f993c945890e93ba = (options)=>{ |
|
if (options && typeof options.windows === 'boolean') return options.windows; |
|
return $436a44408af843d4$var$win32 === true || $8C1kk$path.sep === '\\'; |
|
}; |
|
$436a44408af843d4$export$13d0f4185f159c8 = (input, char, lastIdx)=>{ |
|
const idx = input.lastIndexOf(char, lastIdx); |
|
if (idx === -1) return input; |
|
if (input[idx - 1] === '\\') return $436a44408af843d4$export$13d0f4185f159c8(input, char, idx - 1); |
|
return `${input.slice(0, idx)}\\${input.slice(idx)}`; |
|
}; |
|
$436a44408af843d4$export$f2888183a34644d4 = (input, state = { |
|
})=>{ |
|
let output = input; |
|
if (output.startsWith('./')) { |
|
output = output.slice(2); |
|
state.prefix = './'; |
|
} |
|
return output; |
|
}; |
|
$436a44408af843d4$export$25bddda26836484b = (input, state = { |
|
}, options = { |
|
})=>{ |
|
const prepend = options.contains ? '' : '^'; |
|
const append = options.contains ? '' : '$'; |
|
let output = `${prepend}(?:${input})${append}`; |
|
if (state.negated === true) output = `(?:^(?!${output}).*$)`; |
|
return output; |
|
}; |
|
|
|
}); |
|
parcelRequire.register("7XmS6", function(module, exports) { |
|
'use strict'; |
|
|
|
const $017eb4c9ec326d4f$var$WIN_SLASH = '\\\\/'; |
|
const $017eb4c9ec326d4f$var$WIN_NO_SLASH = `[^${$017eb4c9ec326d4f$var$WIN_SLASH}]`; |
|
/** |
|
* Posix glob regex |
|
*/ const $017eb4c9ec326d4f$var$DOT_LITERAL = '\\.'; |
|
const $017eb4c9ec326d4f$var$PLUS_LITERAL = '\\+'; |
|
const $017eb4c9ec326d4f$var$QMARK_LITERAL = '\\?'; |
|
const $017eb4c9ec326d4f$var$SLASH_LITERAL = '\\/'; |
|
const $017eb4c9ec326d4f$var$ONE_CHAR = '(?=.)'; |
|
const $017eb4c9ec326d4f$var$QMARK = '[^/]'; |
|
const $017eb4c9ec326d4f$var$END_ANCHOR = `(?:${$017eb4c9ec326d4f$var$SLASH_LITERAL}|$)`; |
|
const $017eb4c9ec326d4f$var$START_ANCHOR = `(?:^|${$017eb4c9ec326d4f$var$SLASH_LITERAL})`; |
|
const $017eb4c9ec326d4f$var$DOTS_SLASH = `${$017eb4c9ec326d4f$var$DOT_LITERAL}{1,2}${$017eb4c9ec326d4f$var$END_ANCHOR}`; |
|
const $017eb4c9ec326d4f$var$NO_DOT = `(?!${$017eb4c9ec326d4f$var$DOT_LITERAL})`; |
|
const $017eb4c9ec326d4f$var$NO_DOTS = `(?!${$017eb4c9ec326d4f$var$START_ANCHOR}${$017eb4c9ec326d4f$var$DOTS_SLASH})`; |
|
const $017eb4c9ec326d4f$var$NO_DOT_SLASH = `(?!${$017eb4c9ec326d4f$var$DOT_LITERAL}{0,1}${$017eb4c9ec326d4f$var$END_ANCHOR})`; |
|
const $017eb4c9ec326d4f$var$NO_DOTS_SLASH = `(?!${$017eb4c9ec326d4f$var$DOTS_SLASH})`; |
|
const $017eb4c9ec326d4f$var$QMARK_NO_DOT = `[^.${$017eb4c9ec326d4f$var$SLASH_LITERAL}]`; |
|
const $017eb4c9ec326d4f$var$STAR = `${$017eb4c9ec326d4f$var$QMARK}*?`; |
|
const $017eb4c9ec326d4f$var$POSIX_CHARS = { |
|
DOT_LITERAL: $017eb4c9ec326d4f$var$DOT_LITERAL, |
|
PLUS_LITERAL: $017eb4c9ec326d4f$var$PLUS_LITERAL, |
|
QMARK_LITERAL: $017eb4c9ec326d4f$var$QMARK_LITERAL, |
|
SLASH_LITERAL: $017eb4c9ec326d4f$var$SLASH_LITERAL, |
|
ONE_CHAR: $017eb4c9ec326d4f$var$ONE_CHAR, |
|
QMARK: $017eb4c9ec326d4f$var$QMARK, |
|
END_ANCHOR: $017eb4c9ec326d4f$var$END_ANCHOR, |
|
DOTS_SLASH: $017eb4c9ec326d4f$var$DOTS_SLASH, |
|
NO_DOT: $017eb4c9ec326d4f$var$NO_DOT, |
|
NO_DOTS: $017eb4c9ec326d4f$var$NO_DOTS, |
|
NO_DOT_SLASH: $017eb4c9ec326d4f$var$NO_DOT_SLASH, |
|
NO_DOTS_SLASH: $017eb4c9ec326d4f$var$NO_DOTS_SLASH, |
|
QMARK_NO_DOT: $017eb4c9ec326d4f$var$QMARK_NO_DOT, |
|
STAR: $017eb4c9ec326d4f$var$STAR, |
|
START_ANCHOR: $017eb4c9ec326d4f$var$START_ANCHOR |
|
}; |
|
/** |
|
* Windows glob regex |
|
*/ const $017eb4c9ec326d4f$var$WINDOWS_CHARS = { |
|
...$017eb4c9ec326d4f$var$POSIX_CHARS, |
|
SLASH_LITERAL: `[${$017eb4c9ec326d4f$var$WIN_SLASH}]`, |
|
QMARK: $017eb4c9ec326d4f$var$WIN_NO_SLASH, |
|
STAR: `${$017eb4c9ec326d4f$var$WIN_NO_SLASH}*?`, |
|
DOTS_SLASH: `${$017eb4c9ec326d4f$var$DOT_LITERAL}{1,2}(?:[${$017eb4c9ec326d4f$var$WIN_SLASH}]|$)`, |
|
NO_DOT: `(?!${$017eb4c9ec326d4f$var$DOT_LITERAL})`, |
|
NO_DOTS: `(?!(?:^|[${$017eb4c9ec326d4f$var$WIN_SLASH}])${$017eb4c9ec326d4f$var$DOT_LITERAL}{1,2}(?:[${$017eb4c9ec326d4f$var$WIN_SLASH}]|$))`, |
|
NO_DOT_SLASH: `(?!${$017eb4c9ec326d4f$var$DOT_LITERAL}{0,1}(?:[${$017eb4c9ec326d4f$var$WIN_SLASH}]|$))`, |
|
NO_DOTS_SLASH: `(?!${$017eb4c9ec326d4f$var$DOT_LITERAL}{1,2}(?:[${$017eb4c9ec326d4f$var$WIN_SLASH}]|$))`, |
|
QMARK_NO_DOT: `[^.${$017eb4c9ec326d4f$var$WIN_SLASH}]`, |
|
START_ANCHOR: `(?:^|[${$017eb4c9ec326d4f$var$WIN_SLASH}])`, |
|
END_ANCHOR: `(?:[${$017eb4c9ec326d4f$var$WIN_SLASH}]|$)` |
|
}; |
|
/** |
|
* POSIX Bracket Regex |
|
*/ const $017eb4c9ec326d4f$var$POSIX_REGEX_SOURCE = { |
|
alnum: 'a-zA-Z0-9', |
|
alpha: 'a-zA-Z', |
|
ascii: '\\x00-\\x7F', |
|
blank: ' \\t', |
|
cntrl: '\\x00-\\x1F\\x7F', |
|
digit: '0-9', |
|
graph: '\\x21-\\x7E', |
|
lower: 'a-z', |
|
print: '\\x20-\\x7E ', |
|
punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~', |
|
space: ' \\t\\r\\n\\v\\f', |
|
upper: 'A-Z', |
|
word: 'A-Za-z0-9_', |
|
xdigit: 'A-Fa-f0-9' |
|
}; |
|
module.exports = { |
|
MAX_LENGTH: 65536, |
|
POSIX_REGEX_SOURCE: $017eb4c9ec326d4f$var$POSIX_REGEX_SOURCE, |
|
// regular expressions |
|
REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, |
|
REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/, |
|
REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, |
|
REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, |
|
REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, |
|
REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, |
|
// Replace globs with equivalent patterns to reduce parsing time. |
|
REPLACEMENTS: { |
|
'***': '*', |
|
'**/**': '**', |
|
'**/**/**': '**' |
|
}, |
|
// Digits |
|
CHAR_0: 48, |
|
/* 0 */ CHAR_9: 57, |
|
/* 9 */ // Alphabet chars. |
|
CHAR_UPPERCASE_A: 65, |
|
/* A */ CHAR_LOWERCASE_A: 97, |
|
/* a */ CHAR_UPPERCASE_Z: 90, |
|
/* Z */ CHAR_LOWERCASE_Z: 122, |
|
/* z */ CHAR_LEFT_PARENTHESES: 40, |
|
/* ( */ CHAR_RIGHT_PARENTHESES: 41, |
|
/* ) */ CHAR_ASTERISK: 42, |
|
/* * */ // Non-alphabetic chars. |
|
CHAR_AMPERSAND: 38, |
|
/* & */ CHAR_AT: 64, |
|
/* @ */ CHAR_BACKWARD_SLASH: 92, |
|
/* \ */ CHAR_CARRIAGE_RETURN: 13, |
|
/* \r */ CHAR_CIRCUMFLEX_ACCENT: 94, |
|
/* ^ */ CHAR_COLON: 58, |
|
/* : */ CHAR_COMMA: 44, |
|
/* , */ CHAR_DOT: 46, |
|
/* . */ CHAR_DOUBLE_QUOTE: 34, |
|
/* " */ CHAR_EQUAL: 61, |
|
/* = */ CHAR_EXCLAMATION_MARK: 33, |
|
/* ! */ CHAR_FORM_FEED: 12, |
|
/* \f */ CHAR_FORWARD_SLASH: 47, |
|
/* / */ CHAR_GRAVE_ACCENT: 96, |
|
/* ` */ CHAR_HASH: 35, |
|
/* # */ CHAR_HYPHEN_MINUS: 45, |
|
/* - */ CHAR_LEFT_ANGLE_BRACKET: 60, |
|
/* < */ CHAR_LEFT_CURLY_BRACE: 123, |
|
/* { */ CHAR_LEFT_SQUARE_BRACKET: 91, |
|
/* [ */ CHAR_LINE_FEED: 10, |
|
/* \n */ CHAR_NO_BREAK_SPACE: 160, |
|
/* \u00A0 */ CHAR_PERCENT: 37, |
|
/* % */ CHAR_PLUS: 43, |
|
/* + */ CHAR_QUESTION_MARK: 63, |
|
/* ? */ CHAR_RIGHT_ANGLE_BRACKET: 62, |
|
/* > */ CHAR_RIGHT_CURLY_BRACE: 125, |
|
/* } */ CHAR_RIGHT_SQUARE_BRACKET: 93, |
|
/* ] */ CHAR_SEMICOLON: 59, |
|
/* ; */ CHAR_SINGLE_QUOTE: 39, |
|
/* ' */ CHAR_SPACE: 32, |
|
/* */ CHAR_TAB: 9, |
|
/* \t */ CHAR_UNDERSCORE: 95, |
|
/* _ */ CHAR_VERTICAL_LINE: 124, |
|
/* | */ CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, |
|
/* \uFEFF */ SEP: $8C1kk$path.sep, |
|
/** |
|
* Create EXTGLOB_CHARS |
|
*/ extglobChars (chars) { |
|
return { |
|
'!': { |
|
type: 'negate', |
|
open: '(?:(?!(?:', |
|
close: `))${chars.STAR})` |
|
}, |
|
'?': { |
|
type: 'qmark', |
|
open: '(?:', |
|
close: ')?' |
|
}, |
|
'+': { |
|
type: 'plus', |
|
open: '(?:', |
|
close: ')+' |
|
}, |
|
'*': { |
|
type: 'star', |
|
open: '(?:', |
|
close: ')*' |
|
}, |
|
'@': { |
|
type: 'at', |
|
open: '(?:', |
|
close: ')' |
|
} |
|
}; |
|
}, |
|
/** |
|
* Create GLOB_CHARS |
|
*/ globChars (win32) { |
|
return win32 === true ? $017eb4c9ec326d4f$var$WINDOWS_CHARS : $017eb4c9ec326d4f$var$POSIX_CHARS; |
|
} |
|
}; |
|
|
|
}); |
|
|
|
|
|
|
|
parcelRequire.register("lKEF0", function(module, exports) { |
|
'use strict'; |
|
|
|
var $7XmS6 = parcelRequire("7XmS6"); |
|
|
|
var $5MQDC = parcelRequire("5MQDC"); |
|
/** |
|
* Constants |
|
*/ const { MAX_LENGTH: $fd5d6f248e5b4a63$var$MAX_LENGTH , POSIX_REGEX_SOURCE: $fd5d6f248e5b4a63$var$POSIX_REGEX_SOURCE , REGEX_NON_SPECIAL_CHARS: $fd5d6f248e5b4a63$var$REGEX_NON_SPECIAL_CHARS , REGEX_SPECIAL_CHARS_BACKREF: $fd5d6f248e5b4a63$var$REGEX_SPECIAL_CHARS_BACKREF , REPLACEMENTS: $fd5d6f248e5b4a63$var$REPLACEMENTS } = $7XmS6; |
|
/** |
|
* Helpers |
|
*/ const $fd5d6f248e5b4a63$var$expandRange = (args, options)=>{ |
|
if (typeof options.expandRange === 'function') return options.expandRange(...args, options); |
|
args.sort(); |
|
const value = `[${args.join('-')}]`; |
|
try { |
|
/* eslint-disable-next-line no-new */ new RegExp(value); |
|
} catch (ex) { |
|
return args.map((v)=>$5MQDC.escapeRegex(v) |
|
).join('..'); |
|
} |
|
return value; |
|
}; |
|
/** |
|
* Create the message for a syntax error |
|
*/ const $fd5d6f248e5b4a63$var$syntaxError = (type, char)=>{ |
|
return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; |
|
}; |
|
/** |
|
* Parse the given input string. |
|
* @param {String} input |
|
* @param {Object} options |
|
* @return {Object} |
|
*/ const $fd5d6f248e5b4a63$var$parse = (input, options)=>{ |
|
if (typeof input !== 'string') throw new TypeError('Expected a string'); |
|
input = $fd5d6f248e5b4a63$var$REPLACEMENTS[input] || input; |
|
const opts1 = { |
|
...options |
|
}; |
|
const max = typeof opts1.maxLength === 'number' ? Math.min($fd5d6f248e5b4a63$var$MAX_LENGTH, opts1.maxLength) : $fd5d6f248e5b4a63$var$MAX_LENGTH; |
|
let len = input.length; |
|
if (len > max) throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); |
|
const bos = { |
|
type: 'bos', |
|
value: '', |
|
output: opts1.prepend || '' |
|
}; |
|
const tokens = [ |
|
bos |
|
]; |
|
const capture = opts1.capture ? '' : '?:'; |
|
const win32 = $5MQDC.isWindows(options); |
|
// create constants based on platform, for windows or posix |
|
const PLATFORM_CHARS = $7XmS6.globChars(win32); |
|
const EXTGLOB_CHARS = $7XmS6.extglobChars(PLATFORM_CHARS); |
|
const { DOT_LITERAL: DOT_LITERAL , PLUS_LITERAL: PLUS_LITERAL , SLASH_LITERAL: SLASH_LITERAL , ONE_CHAR: ONE_CHAR , DOTS_SLASH: DOTS_SLASH , NO_DOT: NO_DOT , NO_DOT_SLASH: NO_DOT_SLASH , NO_DOTS_SLASH: NO_DOTS_SLASH , QMARK: QMARK , QMARK_NO_DOT: QMARK_NO_DOT , STAR: STAR , START_ANCHOR: START_ANCHOR } = PLATFORM_CHARS; |
|
const globstar = (opts)=>{ |
|
return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; |
|
}; |
|
const nodot = opts1.dot ? '' : NO_DOT; |
|
const qmarkNoDot = opts1.dot ? QMARK : QMARK_NO_DOT; |
|
let star = opts1.bash === true ? globstar(opts1) : STAR; |
|
if (opts1.capture) star = `(${star})`; |
|
// minimatch options support |
|
if (typeof opts1.noext === 'boolean') opts1.noextglob = opts1.noext; |
|
const state = { |
|
input: input, |
|
index: -1, |
|
start: 0, |
|
dot: opts1.dot === true, |
|
consumed: '', |
|
output: '', |
|
prefix: '', |
|
backtrack: false, |
|
negated: false, |
|
brackets: 0, |
|
braces: 0, |
|
parens: 0, |
|
quotes: 0, |
|
globstar: false, |
|
tokens: tokens |
|
}; |
|
input = $5MQDC.removePrefix(input, state); |
|
len = input.length; |
|
const extglobs = []; |
|
const braces = []; |
|
const stack = []; |
|
let prev = bos; |
|
let value1; |
|
/** |
|
* Tokenizing helpers |
|
*/ const eos = ()=>state.index === len - 1 |
|
; |
|
const peek = state.peek = (n = 1)=>input[state.index + n] |
|
; |
|
const advance = state.advance = ()=>input[++state.index] || '' |
|
; |
|
const remaining = ()=>input.slice(state.index + 1) |
|
; |
|
const consume = (value = '', num = 0)=>{ |
|
state.consumed += value; |
|
state.index += num; |
|
}; |
|
const append = (token)=>{ |
|
state.output += token.output != null ? token.output : token.value; |
|
consume(token.value); |
|
}; |
|
const negate = ()=>{ |
|
let count = 1; |
|
while(peek() === '!' && (peek(2) !== '(' || peek(3) === '?')){ |
|
advance(); |
|
state.start++; |
|
count++; |
|
} |
|
if (count % 2 === 0) return false; |
|
state.negated = true; |
|
state.start++; |
|
return true; |
|
}; |
|
const increment = (type)=>{ |
|
state[type]++; |
|
stack.push(type); |
|
}; |
|
const decrement = (type)=>{ |
|
state[type]--; |
|
stack.pop(); |
|
}; |
|
/** |
|
* Push tokens onto the tokens array. This helper speeds up |
|
* tokenizing by 1) helping us avoid backtracking as much as possible, |
|
* and 2) helping us avoid creating extra tokens when consecutive |
|
* characters are plain text. This improves performance and simplifies |
|
* lookbehinds. |
|
*/ const push = (tok)=>{ |
|
if (prev.type === 'globstar') { |
|
const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace'); |
|
const isExtglob = tok.extglob === true || extglobs.length && (tok.type === 'pipe' || tok.type === 'paren'); |
|
if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) { |
|
state.output = state.output.slice(0, -prev.output.length); |
|
prev.type = 'star'; |
|
prev.value = '*'; |
|
prev.output = star; |
|
state.output += prev.output; |
|
} |
|
} |
|
if (extglobs.length && tok.type !== 'paren') extglobs[extglobs.length - 1].inner += tok.value; |
|
if (tok.value || tok.output) append(tok); |
|
if (prev && prev.type === 'text' && tok.type === 'text') { |
|
prev.value += tok.value; |
|
prev.output = (prev.output || '') + tok.value; |
|
return; |
|
} |
|
tok.prev = prev; |
|
tokens.push(tok); |
|
prev = tok; |
|
}; |
|
const extglobOpen = (type, value)=>{ |
|
const token = { |
|
...EXTGLOB_CHARS[value], |
|
conditions: 1, |
|
inner: '' |
|
}; |
|
token.prev = prev; |
|
token.parens = state.parens; |
|
token.output = state.output; |
|
const output = (opts1.capture ? '(' : '') + token.open; |
|
increment('parens'); |
|
push({ |
|
type: type, |
|
value: value, |
|
output: state.output ? '' : ONE_CHAR |
|
}); |
|
push({ |
|
type: 'paren', |
|
extglob: true, |
|
value: advance(), |
|
output: output |
|
}); |
|
extglobs.push(token); |
|
}; |
|
const extglobClose = (token)=>{ |
|
let output = token.close + (opts1.capture ? ')' : ''); |
|
let rest; |
|
if (token.type === 'negate') { |
|
let extglobStar = star; |
|
if (token.inner && token.inner.length > 1 && token.inner.includes('/')) extglobStar = globstar(opts1); |
|
if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) output = token.close = `)$))${extglobStar}`; |
|
if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) output = token.close = `)${rest})${extglobStar})`; |
|
if (token.prev.type === 'bos') state.negatedExtglob = true; |
|
} |
|
push({ |
|
type: 'paren', |
|
extglob: true, |
|
value: value1, |
|
output: output |
|
}); |
|
decrement('parens'); |
|
}; |
|
/** |
|
* Fast paths |
|
*/ if (opts1.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { |
|
let backslashes = false; |
|
let output = input.replace($fd5d6f248e5b4a63$var$REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index)=>{ |
|
if (first === '\\') { |
|
backslashes = true; |
|
return m; |
|
} |
|
if (first === '?') { |
|
if (esc) return esc + first + (rest ? QMARK.repeat(rest.length) : ''); |
|
if (index === 0) return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : ''); |
|
return QMARK.repeat(chars.length); |
|
} |
|
if (first === '.') return DOT_LITERAL.repeat(chars.length); |
|
if (first === '*') { |
|
if (esc) return esc + first + (rest ? star : ''); |
|
return star; |
|
} |
|
return esc ? m : `\\${m}`; |
|
}); |
|
if (backslashes === true) { |
|
if (opts1.unescape === true) output = output.replace(/\\/g, ''); |
|
else output = output.replace(/\\+/g, (m)=>{ |
|
return m.length % 2 === 0 ? '\\\\' : m ? '\\' : ''; |
|
}); |
|
} |
|
if (output === input && opts1.contains === true) { |
|
state.output = input; |
|
return state; |
|
} |
|
state.output = $5MQDC.wrapOutput(output, state, options); |
|
return state; |
|
} |
|
/** |
|
* Tokenize input until we reach end-of-string |
|
*/ while(!eos()){ |
|
value1 = advance(); |
|
if (value1 === '\u0000') continue; |
|
/** |
|
* Escaped characters |
|
*/ if (value1 === '\\') { |
|
const next = peek(); |
|
if (next === '/' && opts1.bash !== true) continue; |
|
if (next === '.' || next === ';') continue; |
|
if (!next) { |
|
value1 += '\\'; |
|
push({ |
|
type: 'text', |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
// collapse slashes to reduce potential for exploits |
|
const match = /^\\+/.exec(remaining()); |
|
let slashes = 0; |
|
if (match && match[0].length > 2) { |
|
slashes = match[0].length; |
|
state.index += slashes; |
|
if (slashes % 2 !== 0) value1 += '\\'; |
|
} |
|
if (opts1.unescape === true) value1 = advance(); |
|
else value1 += advance(); |
|
if (state.brackets === 0) { |
|
push({ |
|
type: 'text', |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
} |
|
/** |
|
* If we're inside a regex character class, continue |
|
* until we reach the closing bracket. |
|
*/ if (state.brackets > 0 && (value1 !== ']' || prev.value === '[' || prev.value === '[^')) { |
|
if (opts1.posix !== false && value1 === ':') { |
|
const inner = prev.value.slice(1); |
|
if (inner.includes('[')) { |
|
prev.posix = true; |
|
if (inner.includes(':')) { |
|
const idx = prev.value.lastIndexOf('['); |
|
const pre = prev.value.slice(0, idx); |
|
const rest = prev.value.slice(idx + 2); |
|
const posix = $fd5d6f248e5b4a63$var$POSIX_REGEX_SOURCE[rest]; |
|
if (posix) { |
|
prev.value = pre + posix; |
|
state.backtrack = true; |
|
advance(); |
|
if (!bos.output && tokens.indexOf(prev) === 1) bos.output = ONE_CHAR; |
|
continue; |
|
} |
|
} |
|
} |
|
} |
|
if (value1 === '[' && peek() !== ':' || value1 === '-' && peek() === ']') value1 = `\\${value1}`; |
|
if (value1 === ']' && (prev.value === '[' || prev.value === '[^')) value1 = `\\${value1}`; |
|
if (opts1.posix === true && value1 === '!' && prev.value === '[') value1 = '^'; |
|
prev.value += value1; |
|
append({ |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
/** |
|
* If we're inside a quoted string, continue |
|
* until we reach the closing double quote. |
|
*/ if (state.quotes === 1 && value1 !== '"') { |
|
value1 = $5MQDC.escapeRegex(value1); |
|
prev.value += value1; |
|
append({ |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Double quotes |
|
*/ if (value1 === '"') { |
|
state.quotes = state.quotes === 1 ? 0 : 1; |
|
if (opts1.keepQuotes === true) push({ |
|
type: 'text', |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Parentheses |
|
*/ if (value1 === '(') { |
|
increment('parens'); |
|
push({ |
|
type: 'paren', |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
if (value1 === ')') { |
|
if (state.parens === 0 && opts1.strictBrackets === true) throw new SyntaxError($fd5d6f248e5b4a63$var$syntaxError('opening', '(')); |
|
const extglob = extglobs[extglobs.length - 1]; |
|
if (extglob && state.parens === extglob.parens + 1) { |
|
extglobClose(extglobs.pop()); |
|
continue; |
|
} |
|
push({ |
|
type: 'paren', |
|
value: value1, |
|
output: state.parens ? ')' : '\\)' |
|
}); |
|
decrement('parens'); |
|
continue; |
|
} |
|
/** |
|
* Square brackets |
|
*/ if (value1 === '[') { |
|
if (opts1.nobracket === true || !remaining().includes(']')) { |
|
if (opts1.nobracket !== true && opts1.strictBrackets === true) throw new SyntaxError($fd5d6f248e5b4a63$var$syntaxError('closing', ']')); |
|
value1 = `\\${value1}`; |
|
} else increment('brackets'); |
|
push({ |
|
type: 'bracket', |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
if (value1 === ']') { |
|
if (opts1.nobracket === true || prev && prev.type === 'bracket' && prev.value.length === 1) { |
|
push({ |
|
type: 'text', |
|
value: value1, |
|
output: `\\${value1}` |
|
}); |
|
continue; |
|
} |
|
if (state.brackets === 0) { |
|
if (opts1.strictBrackets === true) throw new SyntaxError($fd5d6f248e5b4a63$var$syntaxError('opening', '[')); |
|
push({ |
|
type: 'text', |
|
value: value1, |
|
output: `\\${value1}` |
|
}); |
|
continue; |
|
} |
|
decrement('brackets'); |
|
const prevValue = prev.value.slice(1); |
|
if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) value1 = `/${value1}`; |
|
prev.value += value1; |
|
append({ |
|
value: value1 |
|
}); |
|
// when literal brackets are explicitly disabled |
|
// assume we should match with a regex character class |
|
if (opts1.literalBrackets === false || $5MQDC.hasRegexChars(prevValue)) continue; |
|
const escaped = $5MQDC.escapeRegex(prev.value); |
|
state.output = state.output.slice(0, -prev.value.length); |
|
// when literal brackets are explicitly enabled |
|
// assume we should escape the brackets to match literal characters |
|
if (opts1.literalBrackets === true) { |
|
state.output += escaped; |
|
prev.value = escaped; |
|
continue; |
|
} |
|
// when the user specifies nothing, try to match both |
|
prev.value = `(${capture}${escaped}|${prev.value})`; |
|
state.output += prev.value; |
|
continue; |
|
} |
|
/** |
|
* Braces |
|
*/ if (value1 === '{' && opts1.nobrace !== true) { |
|
increment('braces'); |
|
const open = { |
|
type: 'brace', |
|
value: value1, |
|
output: '(', |
|
outputIndex: state.output.length, |
|
tokensIndex: state.tokens.length |
|
}; |
|
braces.push(open); |
|
push(open); |
|
continue; |
|
} |
|
if (value1 === '}') { |
|
const brace = braces[braces.length - 1]; |
|
if (opts1.nobrace === true || !brace) { |
|
push({ |
|
type: 'text', |
|
value: value1, |
|
output: value1 |
|
}); |
|
continue; |
|
} |
|
let output = ')'; |
|
if (brace.dots === true) { |
|
const arr = tokens.slice(); |
|
const range = []; |
|
for(let i = arr.length - 1; i >= 0; i--){ |
|
tokens.pop(); |
|
if (arr[i].type === 'brace') break; |
|
if (arr[i].type !== 'dots') range.unshift(arr[i].value); |
|
} |
|
output = $fd5d6f248e5b4a63$var$expandRange(range, opts1); |
|
state.backtrack = true; |
|
} |
|
if (brace.comma !== true && brace.dots !== true) { |
|
const out = state.output.slice(0, brace.outputIndex); |
|
const toks = state.tokens.slice(brace.tokensIndex); |
|
brace.value = brace.output = '\\{'; |
|
value1 = output = '\\}'; |
|
state.output = out; |
|
for (const t of toks)state.output += t.output || t.value; |
|
} |
|
push({ |
|
type: 'brace', |
|
value: value1, |
|
output: output |
|
}); |
|
decrement('braces'); |
|
braces.pop(); |
|
continue; |
|
} |
|
/** |
|
* Pipes |
|
*/ if (value1 === '|') { |
|
if (extglobs.length > 0) extglobs[extglobs.length - 1].conditions++; |
|
push({ |
|
type: 'text', |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Commas |
|
*/ if (value1 === ',') { |
|
let output = value1; |
|
const brace = braces[braces.length - 1]; |
|
if (brace && stack[stack.length - 1] === 'braces') { |
|
brace.comma = true; |
|
output = '|'; |
|
} |
|
push({ |
|
type: 'comma', |
|
value: value1, |
|
output: output |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Slashes |
|
*/ if (value1 === '/') { |
|
// if the beginning of the glob is "./", advance the start |
|
// to the current index, and don't add the "./" characters |
|
// to the state. This greatly simplifies lookbehinds when |
|
// checking for BOS characters like "!" and "." (not "./") |
|
if (prev.type === 'dot' && state.index === state.start + 1) { |
|
state.start = state.index + 1; |
|
state.consumed = ''; |
|
state.output = ''; |
|
tokens.pop(); |
|
prev = bos; // reset "prev" to the first token |
|
continue; |
|
} |
|
push({ |
|
type: 'slash', |
|
value: value1, |
|
output: SLASH_LITERAL |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Dots |
|
*/ if (value1 === '.') { |
|
if (state.braces > 0 && prev.type === 'dot') { |
|
if (prev.value === '.') prev.output = DOT_LITERAL; |
|
const brace = braces[braces.length - 1]; |
|
prev.type = 'dots'; |
|
prev.output += value1; |
|
prev.value += value1; |
|
brace.dots = true; |
|
continue; |
|
} |
|
if (state.braces + state.parens === 0 && prev.type !== 'bos' && prev.type !== 'slash') { |
|
push({ |
|
type: 'text', |
|
value: value1, |
|
output: DOT_LITERAL |
|
}); |
|
continue; |
|
} |
|
push({ |
|
type: 'dot', |
|
value: value1, |
|
output: DOT_LITERAL |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Question marks |
|
*/ if (value1 === '?') { |
|
const isGroup = prev && prev.value === '('; |
|
if (!isGroup && opts1.noextglob !== true && peek() === '(' && peek(2) !== '?') { |
|
extglobOpen('qmark', value1); |
|
continue; |
|
} |
|
if (prev && prev.type === 'paren') { |
|
const next = peek(); |
|
let output = value1; |
|
if (next === '<' && !$5MQDC.supportsLookbehinds()) throw new Error('Node.js v10 or higher is required for regex lookbehinds'); |
|
if (prev.value === '(' && !/[!=<:]/.test(next) || next === '<' && !/<([!=]|\w+>)/.test(remaining())) output = `\\${value1}`; |
|
push({ |
|
type: 'text', |
|
value: value1, |
|
output: output |
|
}); |
|
continue; |
|
} |
|
if (opts1.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) { |
|
push({ |
|
type: 'qmark', |
|
value: value1, |
|
output: QMARK_NO_DOT |
|
}); |
|
continue; |
|
} |
|
push({ |
|
type: 'qmark', |
|
value: value1, |
|
output: QMARK |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Exclamation |
|
*/ if (value1 === '!') { |
|
if (opts1.noextglob !== true && peek() === '(') { |
|
if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) { |
|
extglobOpen('negate', value1); |
|
continue; |
|
} |
|
} |
|
if (opts1.nonegate !== true && state.index === 0) { |
|
negate(); |
|
continue; |
|
} |
|
} |
|
/** |
|
* Plus |
|
*/ if (value1 === '+') { |
|
if (opts1.noextglob !== true && peek() === '(' && peek(2) !== '?') { |
|
extglobOpen('plus', value1); |
|
continue; |
|
} |
|
if (prev && prev.value === '(' || opts1.regex === false) { |
|
push({ |
|
type: 'plus', |
|
value: value1, |
|
output: PLUS_LITERAL |
|
}); |
|
continue; |
|
} |
|
if (prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace') || state.parens > 0) { |
|
push({ |
|
type: 'plus', |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
push({ |
|
type: 'plus', |
|
value: PLUS_LITERAL |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Plain text |
|
*/ if (value1 === '@') { |
|
if (opts1.noextglob !== true && peek() === '(' && peek(2) !== '?') { |
|
push({ |
|
type: 'at', |
|
extglob: true, |
|
value: value1, |
|
output: '' |
|
}); |
|
continue; |
|
} |
|
push({ |
|
type: 'text', |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Plain text |
|
*/ if (value1 !== '*') { |
|
if (value1 === '$' || value1 === '^') value1 = `\\${value1}`; |
|
const match = $fd5d6f248e5b4a63$var$REGEX_NON_SPECIAL_CHARS.exec(remaining()); |
|
if (match) { |
|
value1 += match[0]; |
|
state.index += match[0].length; |
|
} |
|
push({ |
|
type: 'text', |
|
value: value1 |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Stars |
|
*/ if (prev && (prev.type === 'globstar' || prev.star === true)) { |
|
prev.type = 'star'; |
|
prev.star = true; |
|
prev.value += value1; |
|
prev.output = star; |
|
state.backtrack = true; |
|
state.globstar = true; |
|
consume(value1); |
|
continue; |
|
} |
|
let rest = remaining(); |
|
if (opts1.noextglob !== true && /^\([^?]/.test(rest)) { |
|
extglobOpen('star', value1); |
|
continue; |
|
} |
|
if (prev.type === 'star') { |
|
if (opts1.noglobstar === true) { |
|
consume(value1); |
|
continue; |
|
} |
|
const prior = prev.prev; |
|
const before = prior.prev; |
|
const isStart = prior.type === 'slash' || prior.type === 'bos'; |
|
const afterStar = before && (before.type === 'star' || before.type === 'globstar'); |
|
if (opts1.bash === true && (!isStart || rest[0] && rest[0] !== '/')) { |
|
push({ |
|
type: 'star', |
|
value: value1, |
|
output: '' |
|
}); |
|
continue; |
|
} |
|
const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace'); |
|
const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren'); |
|
if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) { |
|
push({ |
|
type: 'star', |
|
value: value1, |
|
output: '' |
|
}); |
|
continue; |
|
} |
|
// strip consecutive `/**/` |
|
while(rest.slice(0, 3) === '/**'){ |
|
const after = input[state.index + 4]; |
|
if (after && after !== '/') break; |
|
rest = rest.slice(3); |
|
consume('/**', 3); |
|
} |
|
if (prior.type === 'bos' && eos()) { |
|
prev.type = 'globstar'; |
|
prev.value += value1; |
|
prev.output = globstar(opts1); |
|
state.output = prev.output; |
|
state.globstar = true; |
|
consume(value1); |
|
continue; |
|
} |
|
if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) { |
|
state.output = state.output.slice(0, -(prior.output + prev.output).length); |
|
prior.output = `(?:${prior.output}`; |
|
prev.type = 'globstar'; |
|
prev.output = globstar(opts1) + (opts1.strictSlashes ? ')' : '|$)'); |
|
prev.value += value1; |
|
state.globstar = true; |
|
state.output += prior.output + prev.output; |
|
consume(value1); |
|
continue; |
|
} |
|
if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') { |
|
const end = rest[1] !== void 0 ? '|$' : ''; |
|
state.output = state.output.slice(0, -(prior.output + prev.output).length); |
|
prior.output = `(?:${prior.output}`; |
|
prev.type = 'globstar'; |
|
prev.output = `${globstar(opts1)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`; |
|
prev.value += value1; |
|
state.output += prior.output + prev.output; |
|
state.globstar = true; |
|
consume(value1 + advance()); |
|
push({ |
|
type: 'slash', |
|
value: '/', |
|
output: '' |
|
}); |
|
continue; |
|
} |
|
if (prior.type === 'bos' && rest[0] === '/') { |
|
prev.type = 'globstar'; |
|
prev.value += value1; |
|
prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts1)}${SLASH_LITERAL})`; |
|
state.output = prev.output; |
|
state.globstar = true; |
|
consume(value1 + advance()); |
|
push({ |
|
type: 'slash', |
|
value: '/', |
|
output: '' |
|
}); |
|
continue; |
|
} |
|
// remove single star from output |
|
state.output = state.output.slice(0, -prev.output.length); |
|
// reset previous token to globstar |
|
prev.type = 'globstar'; |
|
prev.output = globstar(opts1); |
|
prev.value += value1; |
|
// reset output with globstar |
|
state.output += prev.output; |
|
state.globstar = true; |
|
consume(value1); |
|
continue; |
|
} |
|
const token = { |
|
type: 'star', |
|
value: value1, |
|
output: star |
|
}; |
|
if (opts1.bash === true) { |
|
token.output = '.*?'; |
|
if (prev.type === 'bos' || prev.type === 'slash') token.output = nodot + token.output; |
|
push(token); |
|
continue; |
|
} |
|
if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts1.regex === true) { |
|
token.output = value1; |
|
push(token); |
|
continue; |
|
} |
|
if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') { |
|
if (prev.type === 'dot') { |
|
state.output += NO_DOT_SLASH; |
|
prev.output += NO_DOT_SLASH; |
|
} else if (opts1.dot === true) { |
|
state.output += NO_DOTS_SLASH; |
|
prev.output += NO_DOTS_SLASH; |
|
} else { |
|
state.output += nodot; |
|
prev.output += nodot; |
|
} |
|
if (peek() !== '*') { |
|
state.output += ONE_CHAR; |
|
prev.output += ONE_CHAR; |
|
} |
|
} |
|
push(token); |
|
} |
|
while(state.brackets > 0){ |
|
if (opts1.strictBrackets === true) throw new SyntaxError($fd5d6f248e5b4a63$var$syntaxError('closing', ']')); |
|
state.output = $5MQDC.escapeLast(state.output, '['); |
|
decrement('brackets'); |
|
} |
|
while(state.parens > 0){ |
|
if (opts1.strictBrackets === true) throw new SyntaxError($fd5d6f248e5b4a63$var$syntaxError('closing', ')')); |
|
state.output = $5MQDC.escapeLast(state.output, '('); |
|
decrement('parens'); |
|
} |
|
while(state.braces > 0){ |
|
if (opts1.strictBrackets === true) throw new SyntaxError($fd5d6f248e5b4a63$var$syntaxError('closing', '}')); |
|
state.output = $5MQDC.escapeLast(state.output, '{'); |
|
decrement('braces'); |
|
} |
|
if (opts1.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) push({ |
|
type: 'maybe_slash', |
|
value: '', |
|
output: `${SLASH_LITERAL}?` |
|
}); |
|
// rebuild the output if we had to backtrack at any point |
|
if (state.backtrack === true) { |
|
state.output = ''; |
|
for (const token of state.tokens){ |
|
state.output += token.output != null ? token.output : token.value; |
|
if (token.suffix) state.output += token.suffix; |
|
} |
|
} |
|
return state; |
|
}; |
|
/** |
|
* Fast paths for creating regular expressions for common glob patterns. |
|
* This can significantly speed up processing and has very little downside |
|
* impact when none of the fast paths match. |
|
*/ $fd5d6f248e5b4a63$var$parse.fastpaths = (input, options)=>{ |
|
const opts2 = { |
|
...options |
|
}; |
|
const max = typeof opts2.maxLength === 'number' ? Math.min($fd5d6f248e5b4a63$var$MAX_LENGTH, opts2.maxLength) : $fd5d6f248e5b4a63$var$MAX_LENGTH; |
|
const len = input.length; |
|
if (len > max) throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); |
|
input = $fd5d6f248e5b4a63$var$REPLACEMENTS[input] || input; |
|
const win32 = $5MQDC.isWindows(options); |
|
// create constants based on platform, for windows or posix |
|
const { DOT_LITERAL: DOT_LITERAL , SLASH_LITERAL: SLASH_LITERAL , ONE_CHAR: ONE_CHAR , DOTS_SLASH: DOTS_SLASH , NO_DOT: NO_DOT , NO_DOTS: NO_DOTS , NO_DOTS_SLASH: NO_DOTS_SLASH , STAR: STAR , START_ANCHOR: START_ANCHOR } = $7XmS6.globChars(win32); |
|
const nodot = opts2.dot ? NO_DOTS : NO_DOT; |
|
const slashDot = opts2.dot ? NO_DOTS_SLASH : NO_DOT; |
|
const capture = opts2.capture ? '' : '?:'; |
|
const state = { |
|
negated: false, |
|
prefix: '' |
|
}; |
|
let star = opts2.bash === true ? '.*?' : STAR; |
|
if (opts2.capture) star = `(${star})`; |
|
const globstar = (opts)=>{ |
|
if (opts.noglobstar === true) return star; |
|
return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; |
|
}; |
|
const create = (str)=>{ |
|
switch(str){ |
|
case '*': |
|
return `${nodot}${ONE_CHAR}${star}`; |
|
case '.*': |
|
return `${DOT_LITERAL}${ONE_CHAR}${star}`; |
|
case '*.*': |
|
return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; |
|
case '*/*': |
|
return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`; |
|
case '**': |
|
return nodot + globstar(opts2); |
|
case '**/*': |
|
return `(?:${nodot}${globstar(opts2)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`; |
|
case '**/*.*': |
|
return `(?:${nodot}${globstar(opts2)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; |
|
case '**/.*': |
|
return `(?:${nodot}${globstar(opts2)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`; |
|
default: |
|
{ |
|
const match = /^(.*?)\.(\w+)$/.exec(str); |
|
if (!match) return; |
|
const source = create(match[1]); |
|
if (!source) return; |
|
return source + DOT_LITERAL + match[2]; |
|
} |
|
} |
|
}; |
|
const output = $5MQDC.removePrefix(input, state); |
|
let source1 = create(output); |
|
if (source1 && opts2.strictSlashes !== true) source1 += `${SLASH_LITERAL}?`; |
|
return source1; |
|
}; |
|
module.exports = $fd5d6f248e5b4a63$var$parse; |
|
|
|
}); |
|
|
|
|
|
parcelRequire.register("5SlBN", function(module, exports) { |
|
'use strict'; |
|
|
|
module.exports = (parcelRequire("5cGv8")); |
|
|
|
module.exports.async = (parcelRequire("9s5mZ")); |
|
|
|
module.exports.stream = (parcelRequire("kV1zV")); |
|
|
|
module.exports.prettyError = (parcelRequire("ciuZ9")); |
|
|
|
}); |
|
parcelRequire.register("5cGv8", function(module, exports) { |
|
'use strict'; |
|
module.exports = $3c9f0a8fecf863f4$var$parseString; |
|
|
|
var $1Sf6D = parcelRequire("1Sf6D"); |
|
|
|
var $ciuZ9 = parcelRequire("ciuZ9"); |
|
function $3c9f0a8fecf863f4$var$parseString(str) { |
|
if ($parcel$global.Buffer && $parcel$global.Buffer.isBuffer(str)) str = str.toString('utf8'); |
|
const parser = new $1Sf6D(); |
|
try { |
|
parser.parse(str); |
|
return parser.finish(); |
|
} catch (err) { |
|
throw $ciuZ9(err, str); |
|
} |
|
} |
|
|
|
}); |
|
parcelRequire.register("1Sf6D", function(module, exports) { |
|
'use strict'; |
|
|
|
/* eslint-disable no-new-wrappers, no-eval, camelcase, operator-linebreak */ module.exports = makeParserClass((parcelRequire("8E52p"))); |
|
module.exports.makeParserClass = makeParserClass; |
|
class TomlError extends Error { |
|
constructor(msg){ |
|
super(msg); |
|
this.name = 'TomlError'; |
|
/* istanbul ignore next */ if (Error.captureStackTrace) Error.captureStackTrace(this, TomlError); |
|
this.fromTOML = true; |
|
this.wrapped = null; |
|
} |
|
} |
|
TomlError.wrap = (err)=>{ |
|
const terr = new TomlError(err.message); |
|
terr.code = err.code; |
|
terr.wrapped = err; |
|
return terr; |
|
}; |
|
module.exports.TomlError = TomlError; |
|
|
|
var $bS2MF = parcelRequire("bS2MF"); |
|
|
|
var $9dYMx = parcelRequire("9dYMx"); |
|
|
|
var $gbrcb = parcelRequire("gbrcb"); |
|
|
|
var $636jz = parcelRequire("636jz"); |
|
const CTRL_I = 9; |
|
const CTRL_J = 10; |
|
const CTRL_M = 13; |
|
const CTRL_CHAR_BOUNDARY = 31 // the last non-character in the latin1 region of unicode, except DEL |
|
; |
|
const CHAR_SP = 32; |
|
const CHAR_QUOT = 34; |
|
const CHAR_NUM = 35; |
|
const CHAR_APOS = 39; |
|
const CHAR_PLUS = 43; |
|
const CHAR_COMMA = 44; |
|
const CHAR_HYPHEN = 45; |
|
const CHAR_PERIOD = 46; |
|
const CHAR_0 = 48; |
|
const CHAR_1 = 49; |
|
const CHAR_7 = 55; |
|
const CHAR_9 = 57; |
|
const CHAR_COLON = 58; |
|
const CHAR_EQUALS = 61; |
|
const CHAR_A = 65; |
|
const CHAR_E = 69; |
|
const CHAR_F = 70; |
|
const CHAR_T = 84; |
|
const CHAR_U = 85; |
|
const CHAR_Z = 90; |
|
const CHAR_LOWBAR = 95; |
|
const CHAR_a = 97; |
|
const CHAR_b = 98; |
|
const CHAR_e = 101; |
|
const CHAR_f = 102; |
|
const CHAR_i = 105; |
|
const CHAR_l = 108; |
|
const CHAR_n = 110; |
|
const CHAR_o = 111; |
|
const CHAR_r = 114; |
|
const CHAR_s = 115; |
|
const CHAR_t = 116; |
|
const CHAR_u = 117; |
|
const CHAR_x = 120; |
|
const CHAR_z = 122; |
|
const CHAR_LCUB = 123; |
|
const CHAR_RCUB = 125; |
|
const CHAR_LSQB = 91; |
|
const CHAR_BSOL = 92; |
|
const CHAR_RSQB = 93; |
|
const CHAR_DEL = 127; |
|
const SURROGATE_FIRST = 55296; |
|
const SURROGATE_LAST = 57343; |
|
const escapes = { |
|
[CHAR_b]: '\u0008', |
|
[CHAR_t]: '\u0009', |
|
[CHAR_n]: '\u000A', |
|
[CHAR_f]: '\u000C', |
|
[CHAR_r]: '\u000D', |
|
[CHAR_QUOT]: '\u0022', |
|
[CHAR_BSOL]: '\u005C' |
|
}; |
|
function isDigit(cp) { |
|
return cp >= CHAR_0 && cp <= CHAR_9; |
|
} |
|
function isHexit(cp) { |
|
return cp >= CHAR_A && cp <= CHAR_F || cp >= CHAR_a && cp <= CHAR_f || cp >= CHAR_0 && cp <= CHAR_9; |
|
} |
|
function isBit(cp) { |
|
return cp === CHAR_1 || cp === CHAR_0; |
|
} |
|
function isOctit(cp) { |
|
return cp >= CHAR_0 && cp <= CHAR_7; |
|
} |
|
function isAlphaNumQuoteHyphen(cp) { |
|
return cp >= CHAR_A && cp <= CHAR_Z || cp >= CHAR_a && cp <= CHAR_z || cp >= CHAR_0 && cp <= CHAR_9 || cp === CHAR_APOS || cp === CHAR_QUOT || cp === CHAR_LOWBAR || cp === CHAR_HYPHEN; |
|
} |
|
function isAlphaNumHyphen(cp) { |
|
return cp >= CHAR_A && cp <= CHAR_Z || cp >= CHAR_a && cp <= CHAR_z || cp >= CHAR_0 && cp <= CHAR_9 || cp === CHAR_LOWBAR || cp === CHAR_HYPHEN; |
|
} |
|
const _type = Symbol('type'); |
|
const _declared = Symbol('declared'); |
|
const hasOwnProperty = Object.prototype.hasOwnProperty; |
|
const defineProperty = Object.defineProperty; |
|
const descriptor = { |
|
configurable: true, |
|
enumerable: true, |
|
writable: true, |
|
value: undefined |
|
}; |
|
function hasKey(obj, key) { |
|
if (hasOwnProperty.call(obj, key)) return true; |
|
if (key === '__proto__') defineProperty(obj, '__proto__', descriptor); |
|
return false; |
|
} |
|
const INLINE_TABLE = Symbol('inline-table'); |
|
function InlineTable() { |
|
return Object.defineProperties({ |
|
}, { |
|
[_type]: { |
|
value: INLINE_TABLE |
|
} |
|
}); |
|
} |
|
function isInlineTable(obj) { |
|
if (obj === null || typeof obj !== 'object') return false; |
|
return obj[_type] === INLINE_TABLE; |
|
} |
|
const TABLE = Symbol('table'); |
|
function Table() { |
|
return Object.defineProperties({ |
|
}, { |
|
[_type]: { |
|
value: TABLE |
|
}, |
|
[_declared]: { |
|
value: false, |
|
writable: true |
|
} |
|
}); |
|
} |
|
function isTable(obj) { |
|
if (obj === null || typeof obj !== 'object') return false; |
|
return obj[_type] === TABLE; |
|
} |
|
const _contentType = Symbol('content-type'); |
|
const INLINE_LIST = Symbol('inline-list'); |
|
function InlineList(type) { |
|
return Object.defineProperties([], { |
|
[_type]: { |
|
value: INLINE_LIST |
|
}, |
|
[_contentType]: { |
|
value: type |
|
} |
|
}); |
|
} |
|
function isInlineList(obj) { |
|
if (obj === null || typeof obj !== 'object') return false; |
|
return obj[_type] === INLINE_LIST; |
|
} |
|
const LIST = Symbol('list'); |
|
function List() { |
|
return Object.defineProperties([], { |
|
[_type]: { |
|
value: LIST |
|
} |
|
}); |
|
} |
|
function isList(obj) { |
|
if (obj === null || typeof obj !== 'object') return false; |
|
return obj[_type] === LIST; |
|
} |
|
// in an eval, to let bundlers not slurp in a util proxy |
|
let _custom; |
|
try { |
|
const utilInspect = eval("require('util').inspect"); |
|
_custom = utilInspect.custom; |
|
} catch (_) { |
|
/* eval require not available in transpiled bundle */ } |
|
/* istanbul ignore next */ const _inspect = _custom || 'inspect'; |
|
class BoxedBigInt { |
|
constructor(value){ |
|
try { |
|
this.value = $parcel$global.BigInt.asIntN(64, value); |
|
} catch (_) { |
|
/* istanbul ignore next */ this.value = null; |
|
} |
|
Object.defineProperty(this, _type, { |
|
value: INTEGER |
|
}); |
|
} |
|
isNaN() { |
|
return this.value === null; |
|
} |
|
/* istanbul ignore next */ toString() { |
|
return String(this.value); |
|
} |
|
/* istanbul ignore next */ [_inspect]() { |
|
return `[BigInt: ${this.toString()}]}`; |
|
} |
|
valueOf() { |
|
return this.value; |
|
} |
|
} |
|
const INTEGER = Symbol('integer'); |
|
function Integer(value) { |
|
let num = Number(value); |
|
// -0 is a float thing, not an int thing |
|
if (Object.is(num, -0)) num = 0; |
|
/* istanbul ignore else */ if ($parcel$global.BigInt && !Number.isSafeInteger(num)) return new BoxedBigInt(value); |
|
else /* istanbul ignore next */ return Object.defineProperties(new Number(num), { |
|
isNaN: { |
|
value: function() { |
|
return isNaN(this); |
|
} |
|
}, |
|
[_type]: { |
|
value: INTEGER |
|
}, |
|
[_inspect]: { |
|
value: ()=>`[Integer: ${value}]` |
|
} |
|
}); |
|
} |
|
function isInteger(obj) { |
|
if (obj === null || typeof obj !== 'object') return false; |
|
return obj[_type] === INTEGER; |
|
} |
|
const FLOAT = Symbol('float'); |
|
function Float(value) { |
|
/* istanbul ignore next */ return Object.defineProperties(new Number(value), { |
|
[_type]: { |
|
value: FLOAT |
|
}, |
|
[_inspect]: { |
|
value: ()=>`[Float: ${value}]` |
|
} |
|
}); |
|
} |
|
function isFloat(obj) { |
|
if (obj === null || typeof obj !== 'object') return false; |
|
return obj[_type] === FLOAT; |
|
} |
|
function tomlType(value) { |
|
const type = typeof value; |
|
if (type === 'object') { |
|
/* istanbul ignore if */ if (value === null) return 'null'; |
|
if (value instanceof Date) return 'datetime'; |
|
/* istanbul ignore else */ if (_type in value) switch(value[_type]){ |
|
case INLINE_TABLE: |
|
return 'inline-table'; |
|
case INLINE_LIST: |
|
return 'inline-list'; |
|
/* istanbul ignore next */ case TABLE: |
|
return 'table'; |
|
/* istanbul ignore next */ case LIST: |
|
return 'list'; |
|
case FLOAT: |
|
return 'float'; |
|
case INTEGER: |
|
return 'integer'; |
|
} |
|
} |
|
return type; |
|
} |
|
function makeParserClass(Parser) { |
|
class TOMLParser extends Parser { |
|
constructor(){ |
|
super(); |
|
this.ctx = this.obj = Table(); |
|
} |
|
/* MATCH HELPER */ atEndOfWord() { |
|
return this.char === CHAR_NUM || this.char === CTRL_I || this.char === CHAR_SP || this.atEndOfLine(); |
|
} |
|
atEndOfLine() { |
|
return this.char === Parser.END || this.char === CTRL_J || this.char === CTRL_M; |
|
} |
|
parseStart() { |
|
if (this.char === Parser.END) return null; |
|
else if (this.char === CHAR_LSQB) return this.call(this.parseTableOrList); |
|
else if (this.char === CHAR_NUM) return this.call(this.parseComment); |
|
else if (this.char === CTRL_J || this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M) return null; |
|
else if (isAlphaNumQuoteHyphen(this.char)) return this.callNow(this.parseAssignStatement); |
|
else throw this.error(new TomlError(`Unknown character "${this.char}"`)); |
|
} |
|
// HELPER, this strips any whitespace and comments to the end of the line |
|
// then RETURNS. Last state in a production. |
|
parseWhitespaceToEOL() { |
|
if (this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M) return null; |
|
else if (this.char === CHAR_NUM) return this.goto(this.parseComment); |
|
else if (this.char === Parser.END || this.char === CTRL_J) return this.return(); |
|
else throw this.error(new TomlError('Unexpected character, expected only whitespace or comments till end of line')); |
|
} |
|
/* ASSIGNMENT: key = value */ parseAssignStatement() { |
|
return this.callNow(this.parseAssign, this.recordAssignStatement); |
|
} |
|
recordAssignStatement(kv) { |
|
let target = this.ctx; |
|
let finalKey = kv.key.pop(); |
|
for (let kw of kv.key){ |
|
if (hasKey(target, kw) && (!isTable(target[kw]) || target[kw][_declared])) throw this.error(new TomlError("Can't redefine existing key")); |
|
target = target[kw] = target[kw] || Table(); |
|
} |
|
if (hasKey(target, finalKey)) throw this.error(new TomlError("Can't redefine existing key")); |
|
// unbox our numbers |
|
if (isInteger(kv.value) || isFloat(kv.value)) target[finalKey] = kv.value.valueOf(); |
|
else target[finalKey] = kv.value; |
|
return this.goto(this.parseWhitespaceToEOL); |
|
} |
|
/* ASSSIGNMENT expression, key = value possibly inside an inline table */ parseAssign() { |
|
return this.callNow(this.parseKeyword, this.recordAssignKeyword); |
|
} |
|
recordAssignKeyword(key) { |
|
if (this.state.resultTable) this.state.resultTable.push(key); |
|
else this.state.resultTable = [ |
|
key |
|
]; |
|
return this.goto(this.parseAssignKeywordPreDot); |
|
} |
|
parseAssignKeywordPreDot() { |
|
if (this.char === CHAR_PERIOD) return this.next(this.parseAssignKeywordPostDot); |
|
else if (this.char !== CHAR_SP && this.char !== CTRL_I) return this.goto(this.parseAssignEqual); |
|
} |
|
parseAssignKeywordPostDot() { |
|
if (this.char !== CHAR_SP && this.char !== CTRL_I) return this.callNow(this.parseKeyword, this.recordAssignKeyword); |
|
} |
|
parseAssignEqual() { |
|
if (this.char === CHAR_EQUALS) return this.next(this.parseAssignPreValue); |
|
else throw this.error(new TomlError('Invalid character, expected "="')); |
|
} |
|
parseAssignPreValue() { |
|
if (this.char === CHAR_SP || this.char === CTRL_I) return null; |
|
else return this.callNow(this.parseValue, this.recordAssignValue); |
|
} |
|
recordAssignValue(value) { |
|
return this.returnNow({ |
|
key: this.state.resultTable, |
|
value: value |
|
}); |
|
} |
|
/* COMMENTS: #...eol */ parseComment() { |
|
do { |
|
if (this.char === Parser.END || this.char === CTRL_J) return this.return(); |
|
}while (this.nextChar()) |
|
} |
|
/* TABLES AND LISTS, [foo] and [[foo]] */ parseTableOrList() { |
|
if (this.char === CHAR_LSQB) this.next(this.parseList); |
|
else return this.goto(this.parseTable); |
|
} |
|
/* TABLE [foo.bar.baz] */ parseTable() { |
|
this.ctx = this.obj; |
|
return this.goto(this.parseTableNext); |
|
} |
|
parseTableNext() { |
|
if (this.char === CHAR_SP || this.char === CTRL_I) return null; |
|
else return this.callNow(this.parseKeyword, this.parseTableMore); |
|
} |
|
parseTableMore(keyword) { |
|
if (this.char === CHAR_SP || this.char === CTRL_I) return null; |
|
else if (this.char === CHAR_RSQB) { |
|
if (hasKey(this.ctx, keyword) && (!isTable(this.ctx[keyword]) || this.ctx[keyword][_declared])) throw this.error(new TomlError("Can't redefine existing key")); |
|
else { |
|
this.ctx = this.ctx[keyword] = this.ctx[keyword] || Table(); |
|
this.ctx[_declared] = true; |
|
} |
|
return this.next(this.parseWhitespaceToEOL); |
|
} else if (this.char === CHAR_PERIOD) { |
|
if (!hasKey(this.ctx, keyword)) this.ctx = this.ctx[keyword] = Table(); |
|
else if (isTable(this.ctx[keyword])) this.ctx = this.ctx[keyword]; |
|
else if (isList(this.ctx[keyword])) this.ctx = this.ctx[keyword][this.ctx[keyword].length - 1]; |
|
else throw this.error(new TomlError("Can't redefine existing key")); |
|
return this.next(this.parseTableNext); |
|
} else throw this.error(new TomlError('Unexpected character, expected whitespace, . or ]')); |
|
} |
|
/* LIST [[a.b.c]] */ parseList() { |
|
this.ctx = this.obj; |
|
return this.goto(this.parseListNext); |
|
} |
|
parseListNext() { |
|
if (this.char === CHAR_SP || this.char === CTRL_I) return null; |
|
else return this.callNow(this.parseKeyword, this.parseListMore); |
|
} |
|
parseListMore(keyword) { |
|
if (this.char === CHAR_SP || this.char === CTRL_I) return null; |
|
else if (this.char === CHAR_RSQB) { |
|
if (!hasKey(this.ctx, keyword)) this.ctx[keyword] = List(); |
|
if (isInlineList(this.ctx[keyword])) throw this.error(new TomlError("Can't extend an inline array")); |
|
else if (isList(this.ctx[keyword])) { |
|
const next = Table(); |
|
this.ctx[keyword].push(next); |
|
this.ctx = next; |
|
} else throw this.error(new TomlError("Can't redefine an existing key")); |
|
return this.next(this.parseListEnd); |
|
} else if (this.char === CHAR_PERIOD) { |
|
if (!hasKey(this.ctx, keyword)) this.ctx = this.ctx[keyword] = Table(); |
|
else if (isInlineList(this.ctx[keyword])) throw this.error(new TomlError("Can't extend an inline array")); |
|
else if (isInlineTable(this.ctx[keyword])) throw this.error(new TomlError("Can't extend an inline table")); |
|
else if (isList(this.ctx[keyword])) this.ctx = this.ctx[keyword][this.ctx[keyword].length - 1]; |
|
else if (isTable(this.ctx[keyword])) this.ctx = this.ctx[keyword]; |
|
else throw this.error(new TomlError("Can't redefine an existing key")); |
|
return this.next(this.parseListNext); |
|
} else throw this.error(new TomlError('Unexpected character, expected whitespace, . or ]')); |
|
} |
|
parseListEnd(keyword) { |
|
if (this.char === CHAR_RSQB) return this.next(this.parseWhitespaceToEOL); |
|
else throw this.error(new TomlError('Unexpected character, expected whitespace, . or ]')); |
|
} |
|
/* VALUE string, number, boolean, inline list, inline object */ parseValue() { |
|
if (this.char === Parser.END) throw this.error(new TomlError('Key without value')); |
|
else if (this.char === CHAR_QUOT) return this.next(this.parseDoubleString); |
|
if (this.char === CHAR_APOS) return this.next(this.parseSingleString); |
|
else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) return this.goto(this.parseNumberSign); |
|
else if (this.char === CHAR_i) return this.next(this.parseInf); |
|
else if (this.char === CHAR_n) return this.next(this.parseNan); |
|
else if (isDigit(this.char)) return this.goto(this.parseNumberOrDateTime); |
|
else if (this.char === CHAR_t || this.char === CHAR_f) return this.goto(this.parseBoolean); |
|
else if (this.char === CHAR_LSQB) return this.call(this.parseInlineList, this.recordValue); |
|
else if (this.char === CHAR_LCUB) return this.call(this.parseInlineTable, this.recordValue); |
|
else throw this.error(new TomlError('Unexpected character, expecting string, number, datetime, boolean, inline array or inline table')); |
|
} |
|
recordValue(value) { |
|
return this.returnNow(value); |
|
} |
|
parseInf() { |
|
if (this.char === CHAR_n) return this.next(this.parseInf2); |
|
else throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"')); |
|
} |
|
parseInf2() { |
|
if (this.char === CHAR_f) { |
|
if (this.state.buf === '-') return this.return(-Infinity); |
|
else return this.return(Infinity); |
|
} else throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"')); |
|
} |
|
parseNan() { |
|
if (this.char === CHAR_a) return this.next(this.parseNan2); |
|
else throw this.error(new TomlError('Unexpected character, expected "nan"')); |
|
} |
|
parseNan2() { |
|
if (this.char === CHAR_n) return this.return(NaN); |
|
else throw this.error(new TomlError('Unexpected character, expected "nan"')); |
|
} |
|
/* KEYS, barewords or basic, literal, or dotted */ parseKeyword() { |
|
if (this.char === CHAR_QUOT) return this.next(this.parseBasicString); |
|
else if (this.char === CHAR_APOS) return this.next(this.parseLiteralString); |
|
else return this.goto(this.parseBareKey); |
|
} |
|
/* KEYS: barewords */ parseBareKey() { |
|
do { |
|
if (this.char === Parser.END) throw this.error(new TomlError('Key ended without value')); |
|
else if (isAlphaNumHyphen(this.char)) this.consume(); |
|
else if (this.state.buf.length === 0) throw this.error(new TomlError('Empty bare keys are not allowed')); |
|
else return this.returnNow(); |
|
}while (this.nextChar()) |
|
} |
|
/* STRINGS, single quoted (literal) */ parseSingleString() { |
|
if (this.char === CHAR_APOS) return this.next(this.parseLiteralMultiStringMaybe); |
|
else return this.goto(this.parseLiteralString); |
|
} |
|
parseLiteralString() { |
|
do { |
|
if (this.char === CHAR_APOS) return this.return(); |
|
else if (this.atEndOfLine()) throw this.error(new TomlError('Unterminated string')); |
|
else if (this.char === CHAR_DEL || this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I) throw this.errorControlCharInString(); |
|
else this.consume(); |
|
}while (this.nextChar()) |
|
} |
|
parseLiteralMultiStringMaybe() { |
|
if (this.char === CHAR_APOS) return this.next(this.parseLiteralMultiString); |
|
else return this.returnNow(); |
|
} |
|
parseLiteralMultiString() { |
|
if (this.char === CTRL_M) return null; |
|
else if (this.char === CTRL_J) return this.next(this.parseLiteralMultiStringContent); |
|
else return this.goto(this.parseLiteralMultiStringContent); |
|
} |
|
parseLiteralMultiStringContent() { |
|
do { |
|
if (this.char === CHAR_APOS) return this.next(this.parseLiteralMultiEnd); |
|
else if (this.char === Parser.END) throw this.error(new TomlError('Unterminated multi-line string')); |
|
else if (this.char === CHAR_DEL || this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I && this.char !== CTRL_J && this.char !== CTRL_M) throw this.errorControlCharInString(); |
|
else this.consume(); |
|
}while (this.nextChar()) |
|
} |
|
parseLiteralMultiEnd() { |
|
if (this.char === CHAR_APOS) return this.next(this.parseLiteralMultiEnd2); |
|
else { |
|
this.state.buf += "'"; |
|
return this.goto(this.parseLiteralMultiStringContent); |
|
} |
|
} |
|
parseLiteralMultiEnd2() { |
|
if (this.char === CHAR_APOS) return this.return(); |
|
else { |
|
this.state.buf += "''"; |
|
return this.goto(this.parseLiteralMultiStringContent); |
|
} |
|
} |
|
/* STRINGS double quoted */ parseDoubleString() { |
|
if (this.char === CHAR_QUOT) return this.next(this.parseMultiStringMaybe); |
|
else return this.goto(this.parseBasicString); |
|
} |
|
parseBasicString() { |
|
do { |
|
if (this.char === CHAR_BSOL) return this.call(this.parseEscape, this.recordEscapeReplacement); |
|
else if (this.char === CHAR_QUOT) return this.return(); |
|
else if (this.atEndOfLine()) throw this.error(new TomlError('Unterminated string')); |
|
else if (this.char === CHAR_DEL || this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I) throw this.errorControlCharInString(); |
|
else this.consume(); |
|
}while (this.nextChar()) |
|
} |
|
recordEscapeReplacement(replacement) { |
|
this.state.buf += replacement; |
|
return this.goto(this.parseBasicString); |
|
} |
|
parseMultiStringMaybe() { |
|
if (this.char === CHAR_QUOT) return this.next(this.parseMultiString); |
|
else return this.returnNow(); |
|
} |
|
parseMultiString() { |
|
if (this.char === CTRL_M) return null; |
|
else if (this.char === CTRL_J) return this.next(this.parseMultiStringContent); |
|
else return this.goto(this.parseMultiStringContent); |
|
} |
|
parseMultiStringContent() { |
|
do { |
|
if (this.char === CHAR_BSOL) return this.call(this.parseMultiEscape, this.recordMultiEscapeReplacement); |
|
else if (this.char === CHAR_QUOT) return this.next(this.parseMultiEnd); |
|
else if (this.char === Parser.END) throw this.error(new TomlError('Unterminated multi-line string')); |
|
else if (this.char === CHAR_DEL || this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I && this.char !== CTRL_J && this.char !== CTRL_M) throw this.errorControlCharInString(); |
|
else this.consume(); |
|
}while (this.nextChar()) |
|
} |
|
errorControlCharInString() { |
|
let displayCode = '\\u00'; |
|
if (this.char < 16) displayCode += '0'; |
|
displayCode += this.char.toString(16); |
|
return this.error(new TomlError(`Control characters (codes < 0x1f and 0x7f) are not allowed in strings, use ${displayCode} instead`)); |
|
} |
|
recordMultiEscapeReplacement(replacement) { |
|
this.state.buf += replacement; |
|
return this.goto(this.parseMultiStringContent); |
|
} |
|
parseMultiEnd() { |
|
if (this.char === CHAR_QUOT) return this.next(this.parseMultiEnd2); |
|
else { |
|
this.state.buf += '"'; |
|
return this.goto(this.parseMultiStringContent); |
|
} |
|
} |
|
parseMultiEnd2() { |
|
if (this.char === CHAR_QUOT) return this.return(); |
|
else { |
|
this.state.buf += '""'; |
|
return this.goto(this.parseMultiStringContent); |
|
} |
|
} |
|
parseMultiEscape() { |
|
if (this.char === CTRL_M || this.char === CTRL_J) return this.next(this.parseMultiTrim); |
|
else if (this.char === CHAR_SP || this.char === CTRL_I) return this.next(this.parsePreMultiTrim); |
|
else return this.goto(this.parseEscape); |
|
} |
|
parsePreMultiTrim() { |
|
if (this.char === CHAR_SP || this.char === CTRL_I) return null; |
|
else if (this.char === CTRL_M || this.char === CTRL_J) return this.next(this.parseMultiTrim); |
|
else throw this.error(new TomlError("Can't escape whitespace")); |
|
} |
|
parseMultiTrim() { |
|
// explicitly whitespace here, END should follow the same path as chars |
|
if (this.char === CTRL_J || this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M) return null; |
|
else return this.returnNow(); |
|
} |
|
parseEscape() { |
|
if (this.char in escapes) return this.return(escapes[this.char]); |
|
else if (this.char === CHAR_u) return this.call(this.parseSmallUnicode, this.parseUnicodeReturn); |
|
else if (this.char === CHAR_U) return this.call(this.parseLargeUnicode, this.parseUnicodeReturn); |
|
else throw this.error(new TomlError('Unknown escape character: ' + this.char)); |
|
} |
|
parseUnicodeReturn(char) { |
|
try { |
|
const codePoint = parseInt(char, 16); |
|
if (codePoint >= SURROGATE_FIRST && codePoint <= SURROGATE_LAST) throw this.error(new TomlError('Invalid unicode, character in range 0xD800 - 0xDFFF is reserved')); |
|
return this.returnNow(String.fromCodePoint(codePoint)); |
|
} catch (err) { |
|
throw this.error(TomlError.wrap(err)); |
|
} |
|
} |
|
parseSmallUnicode() { |
|
if (!isHexit(this.char)) throw this.error(new TomlError('Invalid character in unicode sequence, expected hex')); |
|
else { |
|
this.consume(); |
|
if (this.state.buf.length >= 4) return this.return(); |
|
} |
|
} |
|
parseLargeUnicode() { |
|
if (!isHexit(this.char)) throw this.error(new TomlError('Invalid character in unicode sequence, expected hex')); |
|
else { |
|
this.consume(); |
|
if (this.state.buf.length >= 8) return this.return(); |
|
} |
|
} |
|
/* NUMBERS */ parseNumberSign() { |
|
this.consume(); |
|
return this.next(this.parseMaybeSignedInfOrNan); |
|
} |
|
parseMaybeSignedInfOrNan() { |
|
if (this.char === CHAR_i) return this.next(this.parseInf); |
|
else if (this.char === CHAR_n) return this.next(this.parseNan); |
|
else return this.callNow(this.parseNoUnder, this.parseNumberIntegerStart); |
|
} |
|
parseNumberIntegerStart() { |
|
if (this.char === CHAR_0) { |
|
this.consume(); |
|
return this.next(this.parseNumberIntegerExponentOrDecimal); |
|
} else return this.goto(this.parseNumberInteger); |
|
} |
|
parseNumberIntegerExponentOrDecimal() { |
|
if (this.char === CHAR_PERIOD) { |
|
this.consume(); |
|
return this.call(this.parseNoUnder, this.parseNumberFloat); |
|
} else if (this.char === CHAR_E || this.char === CHAR_e) { |
|
this.consume(); |
|
return this.next(this.parseNumberExponentSign); |
|
} else return this.returnNow(Integer(this.state.buf)); |
|
} |
|
parseNumberInteger() { |
|
if (isDigit(this.char)) this.consume(); |
|
else if (this.char === CHAR_LOWBAR) return this.call(this.parseNoUnder); |
|
else if (this.char === CHAR_E || this.char === CHAR_e) { |
|
this.consume(); |
|
return this.next(this.parseNumberExponentSign); |
|
} else if (this.char === CHAR_PERIOD) { |
|
this.consume(); |
|
return this.call(this.parseNoUnder, this.parseNumberFloat); |
|
} else { |
|
const result = Integer(this.state.buf); |
|
/* istanbul ignore if */ if (result.isNaN()) throw this.error(new TomlError('Invalid number')); |
|
else return this.returnNow(result); |
|
} |
|
} |
|
parseNoUnder() { |
|
if (this.char === CHAR_LOWBAR || this.char === CHAR_PERIOD || this.char === CHAR_E || this.char === CHAR_e) throw this.error(new TomlError('Unexpected character, expected digit')); |
|
else if (this.atEndOfWord()) throw this.error(new TomlError('Incomplete number')); |
|
return this.returnNow(); |
|
} |
|
parseNumberFloat() { |
|
if (this.char === CHAR_LOWBAR) return this.call(this.parseNoUnder, this.parseNumberFloat); |
|
else if (isDigit(this.char)) this.consume(); |
|
else if (this.char === CHAR_E || this.char === CHAR_e) { |
|
this.consume(); |
|
return this.next(this.parseNumberExponentSign); |
|
} else return this.returnNow(Float(this.state.buf)); |
|
} |
|
parseNumberExponentSign() { |
|
if (isDigit(this.char)) return this.goto(this.parseNumberExponent); |
|
else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) { |
|
this.consume(); |
|
this.call(this.parseNoUnder, this.parseNumberExponent); |
|
} else throw this.error(new TomlError('Unexpected character, expected -, + or digit')); |
|
} |
|
parseNumberExponent() { |
|
if (isDigit(this.char)) this.consume(); |
|
else if (this.char === CHAR_LOWBAR) return this.call(this.parseNoUnder); |
|
else return this.returnNow(Float(this.state.buf)); |
|
} |
|
/* NUMBERS or DATETIMES */ parseNumberOrDateTime() { |
|
if (this.char === CHAR_0) { |
|
this.consume(); |
|
return this.next(this.parseNumberBaseOrDateTime); |
|
} else return this.goto(this.parseNumberOrDateTimeOnly); |
|
} |
|
parseNumberOrDateTimeOnly() { |
|
// note, if two zeros are in a row then it MUST be a date |
|
if (this.char === CHAR_LOWBAR) return this.call(this.parseNoUnder, this.parseNumberInteger); |
|
else if (isDigit(this.char)) { |
|
this.consume(); |
|
if (this.state.buf.length > 4) this.next(this.parseNumberInteger); |
|
} else if (this.char === CHAR_E || this.char === CHAR_e) { |
|
this.consume(); |
|
return this.next(this.parseNumberExponentSign); |
|
} else if (this.char === CHAR_PERIOD) { |
|
this.consume(); |
|
return this.call(this.parseNoUnder, this.parseNumberFloat); |
|
} else if (this.char === CHAR_HYPHEN) return this.goto(this.parseDateTime); |
|
else if (this.char === CHAR_COLON) return this.goto(this.parseOnlyTimeHour); |
|
else return this.returnNow(Integer(this.state.buf)); |
|
} |
|
parseDateTimeOnly() { |
|
if (this.state.buf.length < 4) { |
|
if (isDigit(this.char)) return this.consume(); |
|
else if (this.char === CHAR_COLON) return this.goto(this.parseOnlyTimeHour); |
|
else throw this.error(new TomlError('Expected digit while parsing year part of a date')); |
|
} else { |
|
if (this.char === CHAR_HYPHEN) return this.goto(this.parseDateTime); |
|
else throw this.error(new TomlError('Expected hyphen (-) while parsing year part of date')); |
|
} |
|
} |
|
parseNumberBaseOrDateTime() { |
|
if (this.char === CHAR_b) { |
|
this.consume(); |
|
return this.call(this.parseNoUnder, this.parseIntegerBin); |
|
} else if (this.char === CHAR_o) { |
|
this.consume(); |
|
return this.call(this.parseNoUnder, this.parseIntegerOct); |
|
} else if (this.char === CHAR_x) { |
|
this.consume(); |
|
return this.call(this.parseNoUnder, this.parseIntegerHex); |
|
} else if (this.char === CHAR_PERIOD) return this.goto(this.parseNumberInteger); |
|
else if (isDigit(this.char)) return this.goto(this.parseDateTimeOnly); |
|
else return this.returnNow(Integer(this.state.buf)); |
|
} |
|
parseIntegerHex() { |
|
if (isHexit(this.char)) this.consume(); |
|
else if (this.char === CHAR_LOWBAR) return this.call(this.parseNoUnder); |
|
else { |
|
const result = Integer(this.state.buf); |
|
/* istanbul ignore if */ if (result.isNaN()) throw this.error(new TomlError('Invalid number')); |
|
else return this.returnNow(result); |
|
} |
|
} |
|
parseIntegerOct() { |
|
if (isOctit(this.char)) this.consume(); |
|
else if (this.char === CHAR_LOWBAR) return this.call(this.parseNoUnder); |
|
else { |
|
const result = Integer(this.state.buf); |
|
/* istanbul ignore if */ if (result.isNaN()) throw this.error(new TomlError('Invalid number')); |
|
else return this.returnNow(result); |
|
} |
|
} |
|
parseIntegerBin() { |
|
if (isBit(this.char)) this.consume(); |
|
else if (this.char === CHAR_LOWBAR) return this.call(this.parseNoUnder); |
|
else { |
|
const result = Integer(this.state.buf); |
|
/* istanbul ignore if */ if (result.isNaN()) throw this.error(new TomlError('Invalid number')); |
|
else return this.returnNow(result); |
|
} |
|
} |
|
/* DATETIME */ parseDateTime() { |
|
// we enter here having just consumed the year and about to consume the hyphen |
|
if (this.state.buf.length < 4) throw this.error(new TomlError('Years less than 1000 must be zero padded to four characters')); |
|
this.state.result = this.state.buf; |
|
this.state.buf = ''; |
|
return this.next(this.parseDateMonth); |
|
} |
|
parseDateMonth() { |
|
if (this.char === CHAR_HYPHEN) { |
|
if (this.state.buf.length < 2) throw this.error(new TomlError('Months less than 10 must be zero padded to two characters')); |
|
this.state.result += '-' + this.state.buf; |
|
this.state.buf = ''; |
|
return this.next(this.parseDateDay); |
|
} else if (isDigit(this.char)) this.consume(); |
|
else throw this.error(new TomlError('Incomplete datetime')); |
|
} |
|
parseDateDay() { |
|
if (this.char === CHAR_T || this.char === CHAR_SP) { |
|
if (this.state.buf.length < 2) throw this.error(new TomlError('Days less than 10 must be zero padded to two characters')); |
|
this.state.result += '-' + this.state.buf; |
|
this.state.buf = ''; |
|
return this.next(this.parseStartTimeHour); |
|
} else if (this.atEndOfWord()) return this.return($gbrcb(this.state.result + '-' + this.state.buf)); |
|
else if (isDigit(this.char)) this.consume(); |
|
else throw this.error(new TomlError('Incomplete datetime')); |
|
} |
|
parseStartTimeHour() { |
|
if (this.atEndOfWord()) return this.returnNow($gbrcb(this.state.result)); |
|
else return this.goto(this.parseTimeHour); |
|
} |
|
parseTimeHour() { |
|
if (this.char === CHAR_COLON) { |
|
if (this.state.buf.length < 2) throw this.error(new TomlError('Hours less than 10 must be zero padded to two characters')); |
|
this.state.result += 'T' + this.state.buf; |
|
this.state.buf = ''; |
|
return this.next(this.parseTimeMin); |
|
} else if (isDigit(this.char)) this.consume(); |
|
else throw this.error(new TomlError('Incomplete datetime')); |
|
} |
|
parseTimeMin() { |
|
if (this.state.buf.length < 2 && isDigit(this.char)) this.consume(); |
|
else if (this.state.buf.length === 2 && this.char === CHAR_COLON) { |
|
this.state.result += ':' + this.state.buf; |
|
this.state.buf = ''; |
|
return this.next(this.parseTimeSec); |
|
} else throw this.error(new TomlError('Incomplete datetime')); |
|
} |
|
parseTimeSec() { |
|
if (isDigit(this.char)) { |
|
this.consume(); |
|
if (this.state.buf.length === 2) { |
|
this.state.result += ':' + this.state.buf; |
|
this.state.buf = ''; |
|
return this.next(this.parseTimeZoneOrFraction); |
|
} |
|
} else throw this.error(new TomlError('Incomplete datetime')); |
|
} |
|
parseOnlyTimeHour() { |
|
/* istanbul ignore else */ if (this.char === CHAR_COLON) { |
|
if (this.state.buf.length < 2) throw this.error(new TomlError('Hours less than 10 must be zero padded to two characters')); |
|
this.state.result = this.state.buf; |
|
this.state.buf = ''; |
|
return this.next(this.parseOnlyTimeMin); |
|
} else throw this.error(new TomlError('Incomplete time')); |
|
} |
|
parseOnlyTimeMin() { |
|
if (this.state.buf.length < 2 && isDigit(this.char)) this.consume(); |
|
else if (this.state.buf.length === 2 && this.char === CHAR_COLON) { |
|
this.state.result += ':' + this.state.buf; |
|
this.state.buf = ''; |
|
return this.next(this.parseOnlyTimeSec); |
|
} else throw this.error(new TomlError('Incomplete time')); |
|
} |
|
parseOnlyTimeSec() { |
|
if (isDigit(this.char)) { |
|
this.consume(); |
|
if (this.state.buf.length === 2) return this.next(this.parseOnlyTimeFractionMaybe); |
|
} else throw this.error(new TomlError('Incomplete time')); |
|
} |
|
parseOnlyTimeFractionMaybe() { |
|
this.state.result += ':' + this.state.buf; |
|
if (this.char === CHAR_PERIOD) { |
|
this.state.buf = ''; |
|
this.next(this.parseOnlyTimeFraction); |
|
} else return this.return($636jz(this.state.result)); |
|
} |
|
parseOnlyTimeFraction() { |
|
if (isDigit(this.char)) this.consume(); |
|
else if (this.atEndOfWord()) { |
|
if (this.state.buf.length === 0) throw this.error(new TomlError('Expected digit in milliseconds')); |
|
return this.returnNow($636jz(this.state.result + '.' + this.state.buf)); |
|
} else throw this.error(new TomlError('Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z')); |
|
} |
|
parseTimeZoneOrFraction() { |
|
if (this.char === CHAR_PERIOD) { |
|
this.consume(); |
|
this.next(this.parseDateTimeFraction); |
|
} else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) { |
|
this.consume(); |
|
this.next(this.parseTimeZoneHour); |
|
} else if (this.char === CHAR_Z) { |
|
this.consume(); |
|
return this.return($bS2MF(this.state.result + this.state.buf)); |
|
} else if (this.atEndOfWord()) return this.returnNow($9dYMx(this.state.result + this.state.buf)); |
|
else throw this.error(new TomlError('Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z')); |
|
} |
|
parseDateTimeFraction() { |
|
if (isDigit(this.char)) this.consume(); |
|
else if (this.state.buf.length === 1) throw this.error(new TomlError('Expected digit in milliseconds')); |
|
else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) { |
|
this.consume(); |
|
this.next(this.parseTimeZoneHour); |
|
} else if (this.char === CHAR_Z) { |
|
this.consume(); |
|
return this.return($bS2MF(this.state.result + this.state.buf)); |
|
} else if (this.atEndOfWord()) return this.returnNow($9dYMx(this.state.result + this.state.buf)); |
|
else throw this.error(new TomlError('Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z')); |
|
} |
|
parseTimeZoneHour() { |
|
if (isDigit(this.char)) { |
|
this.consume(); |
|
// FIXME: No more regexps |
|
if (/\d\d$/.test(this.state.buf)) return this.next(this.parseTimeZoneSep); |
|
} else throw this.error(new TomlError('Unexpected character in datetime, expected digit')); |
|
} |
|
parseTimeZoneSep() { |
|
if (this.char === CHAR_COLON) { |
|
this.consume(); |
|
this.next(this.parseTimeZoneMin); |
|
} else throw this.error(new TomlError('Unexpected character in datetime, expected colon')); |
|
} |
|
parseTimeZoneMin() { |
|
if (isDigit(this.char)) { |
|
this.consume(); |
|
if (/\d\d$/.test(this.state.buf)) return this.return($bS2MF(this.state.result + this.state.buf)); |
|
} else throw this.error(new TomlError('Unexpected character in datetime, expected digit')); |
|
} |
|
/* BOOLEAN */ parseBoolean() { |
|
/* istanbul ignore else */ if (this.char === CHAR_t) { |
|
this.consume(); |
|
return this.next(this.parseTrue_r); |
|
} else if (this.char === CHAR_f) { |
|
this.consume(); |
|
return this.next(this.parseFalse_a); |
|
} |
|
} |
|
parseTrue_r() { |
|
if (this.char === CHAR_r) { |
|
this.consume(); |
|
return this.next(this.parseTrue_u); |
|
} else throw this.error(new TomlError('Invalid boolean, expected true or false')); |
|
} |
|
parseTrue_u() { |
|
if (this.char === CHAR_u) { |
|
this.consume(); |
|
return this.next(this.parseTrue_e); |
|
} else throw this.error(new TomlError('Invalid boolean, expected true or false')); |
|
} |
|
parseTrue_e() { |
|
if (this.char === CHAR_e) return this.return(true); |
|
else throw this.error(new TomlError('Invalid boolean, expected true or false')); |
|
} |
|
parseFalse_a() { |
|
if (this.char === CHAR_a) { |
|
this.consume(); |
|
return this.next(this.parseFalse_l); |
|
} else throw this.error(new TomlError('Invalid boolean, expected true or false')); |
|
} |
|
parseFalse_l() { |
|
if (this.char === CHAR_l) { |
|
this.consume(); |
|
return this.next(this.parseFalse_s); |
|
} else throw this.error(new TomlError('Invalid boolean, expected true or false')); |
|
} |
|
parseFalse_s() { |
|
if (this.char === CHAR_s) { |
|
this.consume(); |
|
return this.next(this.parseFalse_e); |
|
} else throw this.error(new TomlError('Invalid boolean, expected true or false')); |
|
} |
|
parseFalse_e() { |
|
if (this.char === CHAR_e) return this.return(false); |
|
else throw this.error(new TomlError('Invalid boolean, expected true or false')); |
|
} |
|
/* INLINE LISTS */ parseInlineList() { |
|
if (this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M || this.char === CTRL_J) return null; |
|
else if (this.char === Parser.END) throw this.error(new TomlError('Unterminated inline array')); |
|
else if (this.char === CHAR_NUM) return this.call(this.parseComment); |
|
else if (this.char === CHAR_RSQB) return this.return(this.state.resultArr || InlineList()); |
|
else return this.callNow(this.parseValue, this.recordInlineListValue); |
|
} |
|
recordInlineListValue(value) { |
|
if (this.state.resultArr) { |
|
const listType = this.state.resultArr[_contentType]; |
|
const valueType = tomlType(value); |
|
if (listType !== valueType) throw this.error(new TomlError(`Inline lists must be a single type, not a mix of ${listType} and ${valueType}`)); |
|
} else this.state.resultArr = InlineList(tomlType(value)); |
|
if (isFloat(value) || isInteger(value)) // unbox now that we've verified they're ok |
|
this.state.resultArr.push(value.valueOf()); |
|
else this.state.resultArr.push(value); |
|
return this.goto(this.parseInlineListNext); |
|
} |
|
parseInlineListNext() { |
|
if (this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M || this.char === CTRL_J) return null; |
|
else if (this.char === CHAR_NUM) return this.call(this.parseComment); |
|
else if (this.char === CHAR_COMMA) return this.next(this.parseInlineList); |
|
else if (this.char === CHAR_RSQB) return this.goto(this.parseInlineList); |
|
else throw this.error(new TomlError('Invalid character, expected whitespace, comma (,) or close bracket (])')); |
|
} |
|
/* INLINE TABLE */ parseInlineTable() { |
|
if (this.char === CHAR_SP || this.char === CTRL_I) return null; |
|
else if (this.char === Parser.END || this.char === CHAR_NUM || this.char === CTRL_J || this.char === CTRL_M) throw this.error(new TomlError('Unterminated inline array')); |
|
else if (this.char === CHAR_RCUB) return this.return(this.state.resultTable || InlineTable()); |
|
else { |
|
if (!this.state.resultTable) this.state.resultTable = InlineTable(); |
|
return this.callNow(this.parseAssign, this.recordInlineTableValue); |
|
} |
|
} |
|
recordInlineTableValue(kv) { |
|
let target = this.state.resultTable; |
|
let finalKey = kv.key.pop(); |
|
for (let kw of kv.key){ |
|
if (hasKey(target, kw) && (!isTable(target[kw]) || target[kw][_declared])) throw this.error(new TomlError("Can't redefine existing key")); |
|
target = target[kw] = target[kw] || Table(); |
|
} |
|
if (hasKey(target, finalKey)) throw this.error(new TomlError("Can't redefine existing key")); |
|
if (isInteger(kv.value) || isFloat(kv.value)) target[finalKey] = kv.value.valueOf(); |
|
else target[finalKey] = kv.value; |
|
return this.goto(this.parseInlineTableNext); |
|
} |
|
parseInlineTableNext() { |
|
if (this.char === CHAR_SP || this.char === CTRL_I) return null; |
|
else if (this.char === Parser.END || this.char === CHAR_NUM || this.char === CTRL_J || this.char === CTRL_M) throw this.error(new TomlError('Unterminated inline array')); |
|
else if (this.char === CHAR_COMMA) return this.next(this.parseInlineTable); |
|
else if (this.char === CHAR_RCUB) return this.goto(this.parseInlineTable); |
|
else throw this.error(new TomlError('Invalid character, expected whitespace, comma (,) or close bracket (])')); |
|
} |
|
} |
|
return TOMLParser; |
|
} |
|
|
|
}); |
|
parcelRequire.register("8E52p", function(module, exports) { |
|
'use strict'; |
|
const $64b5f7964fcf57fb$var$ParserEND = 1114112; |
|
class $64b5f7964fcf57fb$var$ParserError extends Error { |
|
/* istanbul ignore next */ constructor(msg, filename, linenumber){ |
|
super('[ParserError] ' + msg, filename, linenumber); |
|
this.name = 'ParserError'; |
|
this.code = 'ParserError'; |
|
if (Error.captureStackTrace) Error.captureStackTrace(this, $64b5f7964fcf57fb$var$ParserError); |
|
} |
|
} |
|
class $64b5f7964fcf57fb$var$State { |
|
constructor(parser){ |
|
this.parser = parser; |
|
this.buf = ''; |
|
this.returned = null; |
|
this.result = null; |
|
this.resultTable = null; |
|
this.resultArr = null; |
|
} |
|
} |
|
class $64b5f7964fcf57fb$var$Parser { |
|
constructor(){ |
|
this.pos = 0; |
|
this.col = 0; |
|
this.line = 0; |
|
this.obj = { |
|
}; |
|
this.ctx = this.obj; |
|
this.stack = []; |
|
this._buf = ''; |
|
this.char = null; |
|
this.ii = 0; |
|
this.state = new $64b5f7964fcf57fb$var$State(this.parseStart); |
|
} |
|
parse(str) { |
|
/* istanbul ignore next */ if (str.length === 0 || str.length == null) return; |
|
this._buf = String(str); |
|
this.ii = -1; |
|
this.char = -1; |
|
let getNext; |
|
while(getNext === false || this.nextChar())getNext = this.runOne(); |
|
this._buf = null; |
|
} |
|
nextChar() { |
|
if (this.char === 10) { |
|
++this.line; |
|
this.col = -1; |
|
} |
|
++this.ii; |
|
this.char = this._buf.codePointAt(this.ii); |
|
++this.pos; |
|
++this.col; |
|
return this.haveBuffer(); |
|
} |
|
haveBuffer() { |
|
return this.ii < this._buf.length; |
|
} |
|
runOne() { |
|
return this.state.parser.call(this, this.state.returned); |
|
} |
|
finish() { |
|
this.char = $64b5f7964fcf57fb$var$ParserEND; |
|
let last; |
|
do { |
|
last = this.state.parser; |
|
this.runOne(); |
|
}while (this.state.parser !== last) |
|
this.ctx = null; |
|
this.state = null; |
|
this._buf = null; |
|
return this.obj; |
|
} |
|
next(fn) { |
|
/* istanbul ignore next */ if (typeof fn !== 'function') throw new $64b5f7964fcf57fb$var$ParserError('Tried to set state to non-existent state: ' + JSON.stringify(fn)); |
|
this.state.parser = fn; |
|
} |
|
goto(fn) { |
|
this.next(fn); |
|
return this.runOne(); |
|
} |
|
call(fn, returnWith) { |
|
if (returnWith) this.next(returnWith); |
|
this.stack.push(this.state); |
|
this.state = new $64b5f7964fcf57fb$var$State(fn); |
|
} |
|
callNow(fn, returnWith) { |
|
this.call(fn, returnWith); |
|
return this.runOne(); |
|
} |
|
return(value) { |
|
/* istanbul ignore next */ if (this.stack.length === 0) throw this.error(new $64b5f7964fcf57fb$var$ParserError('Stack underflow')); |
|
if (value === undefined) value = this.state.buf; |
|
this.state = this.stack.pop(); |
|
this.state.returned = value; |
|
} |
|
returnNow(value) { |
|
this.return(value); |
|
return this.runOne(); |
|
} |
|
consume() { |
|
/* istanbul ignore next */ if (this.char === $64b5f7964fcf57fb$var$ParserEND) throw this.error(new $64b5f7964fcf57fb$var$ParserError('Unexpected end-of-buffer')); |
|
this.state.buf += this._buf[this.ii]; |
|
} |
|
error(err) { |
|
err.line = this.line; |
|
err.col = this.col; |
|
err.pos = this.pos; |
|
return err; |
|
} |
|
/* istanbul ignore next */ parseStart() { |
|
throw new $64b5f7964fcf57fb$var$ParserError('Must declare a parseStart method'); |
|
} |
|
} |
|
$64b5f7964fcf57fb$var$Parser.END = $64b5f7964fcf57fb$var$ParserEND; |
|
$64b5f7964fcf57fb$var$Parser.Error = $64b5f7964fcf57fb$var$ParserError; |
|
module.exports = $64b5f7964fcf57fb$var$Parser; |
|
|
|
}); |
|
|
|
parcelRequire.register("bS2MF", function(module, exports) { |
|
'use strict'; |
|
module.exports = (value)=>{ |
|
const date = new Date(value); |
|
/* istanbul ignore if */ if (isNaN(date)) throw new TypeError('Invalid Datetime'); |
|
else return date; |
|
}; |
|
|
|
}); |
|
|
|
parcelRequire.register("9dYMx", function(module, exports) { |
|
'use strict'; |
|
|
|
var $1ThAX = parcelRequire("1ThAX"); |
|
class $6b7479f98c0b0f2e$var$FloatingDateTime extends Date { |
|
constructor(value){ |
|
super(value + 'Z'); |
|
this.isFloating = true; |
|
} |
|
toISOString() { |
|
const date = `${this.getUTCFullYear()}-${$1ThAX(2, this.getUTCMonth() + 1)}-${$1ThAX(2, this.getUTCDate())}`; |
|
const time = `${$1ThAX(2, this.getUTCHours())}:${$1ThAX(2, this.getUTCMinutes())}:${$1ThAX(2, this.getUTCSeconds())}.${$1ThAX(3, this.getUTCMilliseconds())}`; |
|
return `${date}T${time}`; |
|
} |
|
} |
|
module.exports = (value)=>{ |
|
const date = new $6b7479f98c0b0f2e$var$FloatingDateTime(value); |
|
/* istanbul ignore if */ if (isNaN(date)) throw new TypeError('Invalid Datetime'); |
|
else return date; |
|
}; |
|
|
|
}); |
|
parcelRequire.register("1ThAX", function(module, exports) { |
|
'use strict'; |
|
module.exports = (d, num)=>{ |
|
num = String(num); |
|
while(num.length < d)num = '0' + num; |
|
return num; |
|
}; |
|
|
|
}); |
|
|
|
|
|
parcelRequire.register("gbrcb", function(module, exports) { |
|
'use strict'; |
|
|
|
var $1ThAX = parcelRequire("1ThAX"); |
|
const $bc82c4de3669a4d8$var$DateTime = $parcel$global.Date; |
|
class $bc82c4de3669a4d8$var$Date extends $bc82c4de3669a4d8$var$DateTime { |
|
constructor(value){ |
|
super(value); |
|
this.isDate = true; |
|
} |
|
toISOString() { |
|
return `${this.getUTCFullYear()}-${$1ThAX(2, this.getUTCMonth() + 1)}-${$1ThAX(2, this.getUTCDate())}`; |
|
} |
|
} |
|
module.exports = (value)=>{ |
|
const date = new $bc82c4de3669a4d8$var$Date(value); |
|
/* istanbul ignore if */ if (isNaN(date)) throw new TypeError('Invalid Datetime'); |
|
else return date; |
|
}; |
|
|
|
}); |
|
|
|
parcelRequire.register("636jz", function(module, exports) { |
|
'use strict'; |
|
|
|
var $1ThAX = parcelRequire("1ThAX"); |
|
class $4677ebdc0d7530bb$var$Time extends Date { |
|
constructor(value){ |
|
super(`0000-01-01T${value}Z`); |
|
this.isTime = true; |
|
} |
|
toISOString() { |
|
return `${$1ThAX(2, this.getUTCHours())}:${$1ThAX(2, this.getUTCMinutes())}:${$1ThAX(2, this.getUTCSeconds())}.${$1ThAX(3, this.getUTCMilliseconds())}`; |
|
} |
|
} |
|
module.exports = (value)=>{ |
|
const date = new $4677ebdc0d7530bb$var$Time(value); |
|
/* istanbul ignore if */ if (isNaN(date)) throw new TypeError('Invalid Datetime'); |
|
else return date; |
|
}; |
|
|
|
}); |
|
|
|
|
|
parcelRequire.register("ciuZ9", function(module, exports) { |
|
'use strict'; |
|
module.exports = $8f3f337e029ee933$var$prettyError; |
|
function $8f3f337e029ee933$var$prettyError(err, buf) { |
|
/* istanbul ignore if */ if (err.pos == null || err.line == null) return err; |
|
let msg = err.message; |
|
msg += ` at row ${err.line + 1}, col ${err.col + 1}, pos ${err.pos}:\n`; |
|
/* istanbul ignore else */ if (buf && buf.split) { |
|
const lines = buf.split(/\n/); |
|
const lineNumWidth = String(Math.min(lines.length, err.line + 3)).length; |
|
let linePadding = ' '; |
|
while(linePadding.length < lineNumWidth)linePadding += ' '; |
|
for(let ii = Math.max(0, err.line - 1); ii < Math.min(lines.length, err.line + 2); ++ii){ |
|
let lineNum = String(ii + 1); |
|
if (lineNum.length < lineNumWidth) lineNum = ' ' + lineNum; |
|
if (err.line === ii) { |
|
msg += lineNum + '> ' + lines[ii] + '\n'; |
|
msg += linePadding + ' '; |
|
for(let hh = 0; hh < err.col; ++hh)msg += ' '; |
|
msg += '^\n'; |
|
} else msg += lineNum + ': ' + lines[ii] + '\n'; |
|
} |
|
} |
|
err.message = msg + '\n'; |
|
return err; |
|
} |
|
|
|
}); |
|
|
|
|
|
parcelRequire.register("9s5mZ", function(module, exports) { |
|
'use strict'; |
|
module.exports = $6e1ae4ed5b62d1d9$var$parseAsync; |
|
|
|
var $1Sf6D = parcelRequire("1Sf6D"); |
|
|
|
var $ciuZ9 = parcelRequire("ciuZ9"); |
|
function $6e1ae4ed5b62d1d9$var$parseAsync(str, opts) { |
|
if (!opts) opts = { |
|
}; |
|
const index1 = 0; |
|
const blocksize1 = opts.blocksize || 40960; |
|
const parser = new $1Sf6D(); |
|
function parseAsyncNext(index, blocksize, resolve, reject) { |
|
if (index >= str.length) { |
|
try { |
|
return resolve(parser.finish()); |
|
} catch (err) { |
|
return reject($ciuZ9(err, str)); |
|
} |
|
} |
|
try { |
|
parser.parse(str.slice(index, index + blocksize)); |
|
setImmediate(parseAsyncNext, index + blocksize, blocksize, resolve, reject); |
|
} catch (err) { |
|
reject($ciuZ9(err, str)); |
|
} |
|
} |
|
return new Promise((resolve, reject)=>{ |
|
setImmediate(parseAsyncNext, index1, blocksize1, resolve, reject); |
|
}); |
|
} |
|
|
|
}); |
|
|
|
parcelRequire.register("kV1zV", function(module, exports) { |
|
'use strict'; |
|
module.exports = $f3aa5afcf94fb65f$var$parseStream; |
|
|
|
|
|
var $1Sf6D = parcelRequire("1Sf6D"); |
|
function $f3aa5afcf94fb65f$var$parseStream(stm) { |
|
if (stm) return $f3aa5afcf94fb65f$var$parseReadable(stm); |
|
else return $f3aa5afcf94fb65f$var$parseTransform(stm); |
|
} |
|
function $f3aa5afcf94fb65f$var$parseReadable(stm) { |
|
const parser = new $1Sf6D(); |
|
stm.setEncoding('utf8'); |
|
return new Promise((resolve, reject)=>{ |
|
let readable; |
|
let ended = false; |
|
let errored = false; |
|
function finish() { |
|
ended = true; |
|
if (readable) return; |
|
try { |
|
resolve(parser.finish()); |
|
} catch (err) { |
|
reject(err); |
|
} |
|
} |
|
function error(err) { |
|
errored = true; |
|
reject(err); |
|
} |
|
stm.once('end', finish); |
|
stm.once('error', error); |
|
readNext(); |
|
function readNext() { |
|
readable = true; |
|
let data; |
|
while((data = stm.read()) !== null)try { |
|
parser.parse(data); |
|
} catch (err) { |
|
return error(err); |
|
} |
|
readable = false; |
|
/* istanbul ignore if */ if (ended) return finish(); |
|
/* istanbul ignore if */ if (errored) return; |
|
stm.once('readable', readNext); |
|
} |
|
}); |
|
} |
|
function $f3aa5afcf94fb65f$var$parseTransform() { |
|
const parser = new $1Sf6D(); |
|
return new $8C1kk$stream.Transform({ |
|
objectMode: true, |
|
transform (chunk, encoding, cb) { |
|
try { |
|
parser.parse(chunk.toString(encoding)); |
|
} catch (err) { |
|
this.emit('error', err); |
|
} |
|
cb(); |
|
}, |
|
flush (cb) { |
|
try { |
|
this.push(parser.finish()); |
|
} catch (err) { |
|
this.emit('error', err); |
|
} |
|
cb(); |
|
} |
|
}); |
|
} |
|
|
|
}); |
|
|
|
|
|
parcelRequire.register("224JI", function(module, exports) { |
|
'use strict'; |
|
module.exports = $17af713ce388fcb8$var$stringify; |
|
module.exports.value = $17af713ce388fcb8$var$stringifyInline; |
|
function $17af713ce388fcb8$var$stringify(obj) { |
|
if (obj === null) throw $17af713ce388fcb8$var$typeError('null'); |
|
if (obj === void 0) throw $17af713ce388fcb8$var$typeError('undefined'); |
|
if (typeof obj !== 'object') throw $17af713ce388fcb8$var$typeError(typeof obj); |
|
if (typeof obj.toJSON === 'function') obj = obj.toJSON(); |
|
if (obj == null) return null; |
|
const type = $17af713ce388fcb8$var$tomlType(obj); |
|
if (type !== 'table') throw $17af713ce388fcb8$var$typeError(type); |
|
return $17af713ce388fcb8$var$stringifyObject('', '', obj); |
|
} |
|
function $17af713ce388fcb8$var$typeError(type) { |
|
return new Error('Can only stringify objects, not ' + type); |
|
} |
|
function $17af713ce388fcb8$var$arrayOneTypeError() { |
|
return new Error("Array values can't have mixed types"); |
|
} |
|
function $17af713ce388fcb8$var$getInlineKeys(obj) { |
|
return Object.keys(obj).filter((key)=>$17af713ce388fcb8$var$isInline(obj[key]) |
|
); |
|
} |
|
function $17af713ce388fcb8$var$getComplexKeys(obj) { |
|
return Object.keys(obj).filter((key)=>!$17af713ce388fcb8$var$isInline(obj[key]) |
|
); |
|
} |
|
function $17af713ce388fcb8$var$toJSON(obj) { |
|
let nobj = Array.isArray(obj) ? [] : Object.prototype.hasOwnProperty.call(obj, '__proto__') ? { |
|
['__proto__']: undefined |
|
} : { |
|
}; |
|
for (let prop of Object.keys(obj))if (obj[prop] && typeof obj[prop].toJSON === 'function' && !('toISOString' in obj[prop])) nobj[prop] = obj[prop].toJSON(); |
|
else nobj[prop] = obj[prop]; |
|
return nobj; |
|
} |
|
function $17af713ce388fcb8$var$stringifyObject(prefix, indent, obj) { |
|
obj = $17af713ce388fcb8$var$toJSON(obj); |
|
var inlineKeys; |
|
var complexKeys; |
|
inlineKeys = $17af713ce388fcb8$var$getInlineKeys(obj); |
|
complexKeys = $17af713ce388fcb8$var$getComplexKeys(obj); |
|
var result = []; |
|
var inlineIndent = indent || ''; |
|
inlineKeys.forEach((key)=>{ |
|
var type = $17af713ce388fcb8$var$tomlType(obj[key]); |
|
if (type !== 'undefined' && type !== 'null') result.push(inlineIndent + $17af713ce388fcb8$var$stringifyKey(key) + ' = ' + $17af713ce388fcb8$var$stringifyAnyInline(obj[key], true)); |
|
}); |
|
if (result.length > 0) result.push(''); |
|
var complexIndent = prefix && inlineKeys.length > 0 ? indent + ' ' : ''; |
|
complexKeys.forEach((key)=>{ |
|
result.push($17af713ce388fcb8$var$stringifyComplex(prefix, complexIndent, key, obj[key])); |
|
}); |
|
return result.join('\n'); |
|
} |
|
function $17af713ce388fcb8$var$isInline(value) { |
|
switch($17af713ce388fcb8$var$tomlType(value)){ |
|
case 'undefined': |
|
case 'null': |
|
case 'integer': |
|
case 'nan': |
|
case 'float': |
|
case 'boolean': |
|
case 'string': |
|
case 'datetime': |
|
return true; |
|
case 'array': |
|
return value.length === 0 || $17af713ce388fcb8$var$tomlType(value[0]) !== 'table'; |
|
case 'table': |
|
return Object.keys(value).length === 0; |
|
/* istanbul ignore next */ default: |
|
return false; |
|
} |
|
} |
|
function $17af713ce388fcb8$var$tomlType(value) { |
|
if (value === undefined) return 'undefined'; |
|
else if (value === null) return 'null'; |
|
else if (typeof value === 'bigint' || Number.isInteger(value) && !Object.is(value, -0)) return 'integer'; |
|
else if (typeof value === 'number') return 'float'; |
|
else if (typeof value === 'boolean') return 'boolean'; |
|
else if (typeof value === 'string') return 'string'; |
|
else if ('toISOString' in value) return isNaN(value) ? 'undefined' : 'datetime'; |
|
else if (Array.isArray(value)) return 'array'; |
|
else return 'table'; |
|
} |
|
function $17af713ce388fcb8$var$stringifyKey(key) { |
|
var keyStr = String(key); |
|
if (/^[-A-Za-z0-9_]+$/.test(keyStr)) return keyStr; |
|
else return $17af713ce388fcb8$var$stringifyBasicString(keyStr); |
|
} |
|
function $17af713ce388fcb8$var$stringifyBasicString(str) { |
|
return '"' + $17af713ce388fcb8$var$escapeString(str).replace(/"/g, '\\"') + '"'; |
|
} |
|
function $17af713ce388fcb8$var$stringifyLiteralString(str) { |
|
return "'" + str + "'"; |
|
} |
|
function $17af713ce388fcb8$var$numpad(num, str) { |
|
while(str.length < num)str = '0' + str; |
|
return str; |
|
} |
|
function $17af713ce388fcb8$var$escapeString(str) { |
|
return str.replace(/\\/g, '\\\\').replace(/[\b]/g, '\\b').replace(/\t/g, '\\t').replace(/\n/g, '\\n').replace(/\f/g, '\\f').replace(/\r/g, '\\r')/* eslint-disable no-control-regex */ .replace(/([\u0000-\u001f\u007f])/, (c)=>'\\u' + $17af713ce388fcb8$var$numpad(4, c.codePointAt(0).toString(16)) |
|
); |
|
/* eslint-enable no-control-regex */ } |
|
function $17af713ce388fcb8$var$stringifyMultilineString(str1) { |
|
let escaped = str1.split(/\n/).map((str)=>{ |
|
return $17af713ce388fcb8$var$escapeString(str).replace(/"(?="")/g, '\\"'); |
|
}).join('\n'); |
|
if (escaped.slice(-1) === '"') escaped += '\\\n'; |
|
return '"""\n' + escaped + '"""'; |
|
} |
|
function $17af713ce388fcb8$var$stringifyAnyInline(value, multilineOk) { |
|
let type = $17af713ce388fcb8$var$tomlType(value); |
|
if (type === 'string') { |
|
if (multilineOk && /\n/.test(value)) type = 'string-multiline'; |
|
else if (!/[\b\t\n\f\r']/.test(value) && /"/.test(value)) type = 'string-literal'; |
|
} |
|
return $17af713ce388fcb8$var$stringifyInline(value, type); |
|
} |
|
function $17af713ce388fcb8$var$stringifyInline(value, type) { |
|
/* istanbul ignore if */ if (!type) type = $17af713ce388fcb8$var$tomlType(value); |
|
switch(type){ |
|
case 'string-multiline': |
|
return $17af713ce388fcb8$var$stringifyMultilineString(value); |
|
case 'string': |
|
return $17af713ce388fcb8$var$stringifyBasicString(value); |
|
case 'string-literal': |
|
return $17af713ce388fcb8$var$stringifyLiteralString(value); |
|
case 'integer': |
|
return $17af713ce388fcb8$var$stringifyInteger(value); |
|
case 'float': |
|
return $17af713ce388fcb8$var$stringifyFloat(value); |
|
case 'boolean': |
|
return $17af713ce388fcb8$var$stringifyBoolean(value); |
|
case 'datetime': |
|
return $17af713ce388fcb8$var$stringifyDatetime(value); |
|
case 'array': |
|
return $17af713ce388fcb8$var$stringifyInlineArray(value.filter((_)=>$17af713ce388fcb8$var$tomlType(_) !== 'null' && $17af713ce388fcb8$var$tomlType(_) !== 'undefined' && $17af713ce388fcb8$var$tomlType(_) !== 'nan' |
|
)); |
|
case 'table': |
|
return $17af713ce388fcb8$var$stringifyInlineTable(value); |
|
/* istanbul ignore next */ default: |
|
throw $17af713ce388fcb8$var$typeError(type); |
|
} |
|
} |
|
function $17af713ce388fcb8$var$stringifyInteger(value) { |
|
/* eslint-disable security/detect-unsafe-regex */ return String(value).replace(/\B(?=(\d{3})+(?!\d))/g, '_'); |
|
} |
|
function $17af713ce388fcb8$var$stringifyFloat(value) { |
|
if (value === Infinity) return 'inf'; |
|
else if (value === -Infinity) return '-inf'; |
|
else if (Object.is(value, NaN)) return 'nan'; |
|
else if (Object.is(value, -0)) return '-0.0'; |
|
var chunks = String(value).split('.'); |
|
var int = chunks[0]; |
|
var dec = chunks[1] || 0; |
|
return $17af713ce388fcb8$var$stringifyInteger(int) + '.' + dec; |
|
} |
|
function $17af713ce388fcb8$var$stringifyBoolean(value) { |
|
return String(value); |
|
} |
|
function $17af713ce388fcb8$var$stringifyDatetime(value) { |
|
return value.toISOString(); |
|
} |
|
function $17af713ce388fcb8$var$isNumber(type) { |
|
return type === 'float' || type === 'integer'; |
|
} |
|
function $17af713ce388fcb8$var$arrayType(values) { |
|
var contentType = $17af713ce388fcb8$var$tomlType(values[0]); |
|
if (values.every((_)=>$17af713ce388fcb8$var$tomlType(_) === contentType |
|
)) return contentType; |
|
// mixed integer/float, emit as floats |
|
if (values.every((_)=>$17af713ce388fcb8$var$isNumber($17af713ce388fcb8$var$tomlType(_)) |
|
)) return 'float'; |
|
return 'mixed'; |
|
} |
|
function $17af713ce388fcb8$var$validateArray(values) { |
|
const type = $17af713ce388fcb8$var$arrayType(values); |
|
if (type === 'mixed') throw $17af713ce388fcb8$var$arrayOneTypeError(); |
|
return type; |
|
} |
|
function $17af713ce388fcb8$var$stringifyInlineArray(values) { |
|
values = $17af713ce388fcb8$var$toJSON(values); |
|
const type = $17af713ce388fcb8$var$validateArray(values); |
|
var result = '['; |
|
var stringified = values.map((_)=>$17af713ce388fcb8$var$stringifyInline(_, type) |
|
); |
|
if (stringified.join(', ').length > 60 || /\n/.test(stringified)) result += '\n ' + stringified.join(',\n ') + '\n'; |
|
else result += ' ' + stringified.join(', ') + (stringified.length > 0 ? ' ' : ''); |
|
return result + ']'; |
|
} |
|
function $17af713ce388fcb8$var$stringifyInlineTable(value) { |
|
value = $17af713ce388fcb8$var$toJSON(value); |
|
var result = []; |
|
Object.keys(value).forEach((key)=>{ |
|
result.push($17af713ce388fcb8$var$stringifyKey(key) + ' = ' + $17af713ce388fcb8$var$stringifyAnyInline(value[key], false)); |
|
}); |
|
return '{ ' + result.join(', ') + (result.length > 0 ? ' ' : '') + '}'; |
|
} |
|
function $17af713ce388fcb8$var$stringifyComplex(prefix, indent, key, value) { |
|
var valueType = $17af713ce388fcb8$var$tomlType(value); |
|
/* istanbul ignore else */ if (valueType === 'array') return $17af713ce388fcb8$var$stringifyArrayOfTables(prefix, indent, key, value); |
|
else if (valueType === 'table') return $17af713ce388fcb8$var$stringifyComplexTable(prefix, indent, key, value); |
|
else throw $17af713ce388fcb8$var$typeError(valueType); |
|
} |
|
function $17af713ce388fcb8$var$stringifyArrayOfTables(prefix, indent, key, values) { |
|
values = $17af713ce388fcb8$var$toJSON(values); |
|
$17af713ce388fcb8$var$validateArray(values); |
|
var firstValueType = $17af713ce388fcb8$var$tomlType(values[0]); |
|
/* istanbul ignore if */ if (firstValueType !== 'table') throw $17af713ce388fcb8$var$typeError(firstValueType); |
|
var fullKey = prefix + $17af713ce388fcb8$var$stringifyKey(key); |
|
var result = ''; |
|
values.forEach((table)=>{ |
|
if (result.length > 0) result += '\n'; |
|
result += indent + '[[' + fullKey + ']]\n'; |
|
result += $17af713ce388fcb8$var$stringifyObject(fullKey + '.', indent, table); |
|
}); |
|
return result; |
|
} |
|
function $17af713ce388fcb8$var$stringifyComplexTable(prefix, indent, key, value) { |
|
var fullKey = prefix + $17af713ce388fcb8$var$stringifyKey(key); |
|
var result = ''; |
|
if ($17af713ce388fcb8$var$getInlineKeys(value).length > 0) result += indent + '[' + fullKey + ']\n'; |
|
return result + $17af713ce388fcb8$var$stringifyObject(fullKey + '.', indent, value); |
|
} |
|
|
|
}); |
|
|
|
parcelRequire.register("lADnf", function(module, exports) { |
|
'use strict'; |
|
module.exports = function(Yallist) { |
|
Yallist.prototype[Symbol.iterator] = function*() { |
|
for(let walker = this.head; walker; walker = walker.next)yield walker.value; |
|
}; |
|
}; |
|
|
|
}); |
|
|
|
|
|
$parcel$export(module.exports, "countLines", () => $fddc9169ba2fd655$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "generateBuildMetrics", () => $15d4bc8b6fca8c7e$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "generateCertificate", () => $c6cbdbdbaf0fafc1$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "getCertificate", () => $186980c178984fd2$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "getRootDir", () => $275c1a71c92a4142$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "isDirectoryInside", () => $ea105385370dfccd$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "isURL", () => $f7d48e99e9c9e3b2$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "objectHash", () => $295998acc3b31ee9$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "prettifyTime", () => $ec068ba9e84f8eea$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "prettyDiagnostic", () => $f02d6a9d30f55938$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "PromiseQueue", () => $b0fd219fea43bcac$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "validateSchema", () => $4ca1027d34905147$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "TapStream", () => $3f2d35ad38f40faa$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "urlJoin", () => $dfabc3743c08d51c$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "relativeUrl", () => $b18990c6c3ea36b3$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "createDependencyLocation", () => $43b0dce5dd282650$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "debounce", () => $1ba22b2a95920d8e$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "throttle", () => $e499d3e618e93ebd$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "openInBrowser", () => $f064b622a304e96c$export$2e2bcd8739ae039); |
|
$parcel$export(module.exports, "findAlternativeNodeModules", () => $6aebdac47db0459e$export$6643be4f4e63e994); |
|
$parcel$export(module.exports, "findAlternativeFiles", () => $6aebdac47db0459e$export$4eeb1b3271a29661); |
|
$parcel$export(module.exports, "blobToBuffer", () => $a3de5fd908122828$export$e234f0a8b913b7b9); |
|
$parcel$export(module.exports, "blobToString", () => $a3de5fd908122828$export$c6adc95df13c8b9e); |
|
$parcel$export(module.exports, "unique", () => $9631335a11debdd4$export$7a5d5c156e7dc406); |
|
$parcel$export(module.exports, "objectSortedEntries", () => $9631335a11debdd4$export$61559eb31990eff6); |
|
$parcel$export(module.exports, "objectSortedEntriesDeep", () => $9631335a11debdd4$export$1a9b883158ac407c); |
|
$parcel$export(module.exports, "setDifference", () => $9631335a11debdd4$export$8bd517cc5b3722f7); |
|
$parcel$export(module.exports, "setIntersect", () => $9631335a11debdd4$export$9404cfefeb010e68); |
|
$parcel$export(module.exports, "setUnion", () => $9631335a11debdd4$export$667066422fa0af46); |
|
$parcel$export(module.exports, "resolveConfig", () => $10671d0be444e08b$export$7eca4ea16d4c8343); |
|
$parcel$export(module.exports, "resolveConfigSync", () => $10671d0be444e08b$export$d175e66e9fcd7b75); |
|
$parcel$export(module.exports, "loadConfig", () => $10671d0be444e08b$export$c1a4367d4847eb06); |
|
$parcel$export(module.exports, "DefaultMap", () => $5783bf7916ff59db$export$674cd7dcb504ac5c); |
|
$parcel$export(module.exports, "DefaultWeakMap", () => $5783bf7916ff59db$export$4924f7ffab2ae440); |
|
$parcel$export(module.exports, "makeDeferredWithPromise", () => $75952a43539cb60f$export$93f345b3f0dd27e7); |
|
$parcel$export(module.exports, "isGlob", () => $e8d0e504a4244d84$export$f3a2344a73dbdd42); |
|
$parcel$export(module.exports, "isGlobMatch", () => $e8d0e504a4244d84$export$16e6d319a883f04e); |
|
$parcel$export(module.exports, "globSync", () => $e8d0e504a4244d84$export$42275ba87174c828); |
|
$parcel$export(module.exports, "glob", () => $e8d0e504a4244d84$export$442f1a04865e4790); |
|
$parcel$export(module.exports, "globToRegex", () => $e8d0e504a4244d84$export$c0436a5422df81e4); |
|
$parcel$export(module.exports, "hashStream", () => $4b14026b40817fca$export$8a9ede1a78d6a1fe); |
|
$parcel$export(module.exports, "hashObject", () => $4b14026b40817fca$export$3477f9615e12f61d); |
|
$parcel$export(module.exports, "hashFile", () => $4b14026b40817fca$export$42462553d605d8cd); |
|
$parcel$export(module.exports, "SharedBuffer", () => $1c93db5abaa33eaa$export$8b1c306fed4227bf); |
|
$parcel$export(module.exports, "fuzzySearch", () => $4ca1027d34905147$export$2115c2c0a84eef61); |
|
$parcel$export(module.exports, "createHTTPServer", () => $0e887a49fdd81cad$export$3b1983e9896f988b); |
|
$parcel$export(module.exports, "normalizePath", () => $3dff16cfd200ff25$export$6af368f973c74c5); |
|
$parcel$export(module.exports, "normalizeSeparators", () => $3dff16cfd200ff25$export$16778b798ae8e49d); |
|
$parcel$export(module.exports, "relativePath", () => $3dff16cfd200ff25$export$7413eea5ad243d4); |
|
$parcel$export(module.exports, "replaceURLReferences", () => $bc66accb63b05e9a$export$d0d0105f44defc19); |
|
$parcel$export(module.exports, "replaceInlineReferences", () => $bc66accb63b05e9a$export$f074a8f9bef628fd); |
|
$parcel$export(module.exports, "measureStreamLength", () => $29bb96d8a6524ff0$export$457f03b1bf37ec1a); |
|
$parcel$export(module.exports, "readableFromStringOrBuffer", () => $29bb96d8a6524ff0$export$dc30d0b81ccad9c7); |
|
$parcel$export(module.exports, "bufferStream", () => $29bb96d8a6524ff0$export$f109d1c79a5ae5a1); |
|
$parcel$export(module.exports, "blobToStream", () => $29bb96d8a6524ff0$export$5ba0b0e7e2e9ae7a); |
|
$parcel$export(module.exports, "streamFromPromise", () => $29bb96d8a6524ff0$export$7ebca75e1135fcd6); |
|
$parcel$export(module.exports, "fallbackStream", () => $29bb96d8a6524ff0$export$68f6769cfac79897); |
|
$parcel$export(module.exports, "relativeBundlePath", () => $76ed5e95485fb544$export$402b5a120b1183b3); |
|
$parcel$export(module.exports, "ansiHtml", () => $7ea2b0152b726098$export$565d0ff71645da31); |
|
$parcel$export(module.exports, "escapeHTML", () => $557d7b477cbdc368$export$5dd27816c66fb702); |
|
$parcel$export(module.exports, "SOURCEMAP_RE", () => $46fc74961fdcfe31$export$db8833b274702782); |
|
$parcel$export(module.exports, "SOURCEMAP_EXTENSIONS", () => $46fc74961fdcfe31$export$4b206fdd01e58041); |
|
$parcel$export(module.exports, "matchSourceMappingURL", () => $46fc74961fdcfe31$export$ff36203a2e5cc203); |
|
$parcel$export(module.exports, "loadSourceMapUrl", () => $46fc74961fdcfe31$export$527a92fa675f5e93); |
|
$parcel$export(module.exports, "loadSourceMap", () => $46fc74961fdcfe31$export$c500fecaca54de65); |
|
$parcel$export(module.exports, "remapSourceLocation", () => $46fc74961fdcfe31$export$2fed780245c466c1); |
|
function $fddc9169ba2fd655$export$2e2bcd8739ae039(string, startIndex = 0) { |
|
let lines = 1; |
|
for(let i = startIndex; i < string.length; i++)if (string.charAt(i) === '\n') lines++; |
|
return lines; |
|
} |
|
|
|
|
|
|
|
var $812806c6461f2963$exports = {}; |
|
'use strict'; |
|
function $812806c6461f2963$var$nullthrows(x, message) { |
|
if (x != null) return x; |
|
var error = new Error(message !== undefined ? message : 'Got unexpected ' + x); |
|
error.framesToPop = 1; // Skip nullthrows's own stack frame. |
|
throw error; |
|
} |
|
$812806c6461f2963$exports = $812806c6461f2963$var$nullthrows; |
|
$812806c6461f2963$exports.default = $812806c6461f2963$var$nullthrows; |
|
Object.defineProperty($812806c6461f2963$exports, '__esModule', { |
|
value: true |
|
}); |
|
|
|
|
|
|
|
|
|
async function $15d4bc8b6fca8c7e$var$getSourcemapSizes(filePath, fs, projectRoot) { |
|
let bundleContents = await fs.readFile(filePath, 'utf-8'); |
|
let mapUrlData = await $46fc74961fdcfe31$export$527a92fa675f5e93(fs, filePath, bundleContents); |
|
if (!mapUrlData) return null; |
|
let rawMap = mapUrlData.map; |
|
let sourceMap = new ($parcel$interopDefault($8C1kk$parcelsourcemap))(projectRoot); |
|
sourceMap.addVLQMap(rawMap); |
|
let parsedMapData = sourceMap.getMap(); |
|
if (parsedMapData.mappings.length > 2) { |
|
let sources = parsedMapData.sources.map((s)=>($parcel$interopDefault($8C1kk$path)).normalize(($parcel$interopDefault($8C1kk$path)).join(projectRoot, s)) |
|
); |
|
let currLine = 1; |
|
let currColumn = 0; |
|
let currMappingIndex = 0; |
|
let currMapping = parsedMapData.mappings[currMappingIndex]; |
|
let nextMapping = parsedMapData.mappings[currMappingIndex + 1]; |
|
let sourceSizes = new Array(sources.length).fill(0); |
|
let unknownOrigin = 0; |
|
for(let i = 0; i < bundleContents.length; i++){ |
|
let character = bundleContents[i]; |
|
while(nextMapping && nextMapping.generated.line === currLine && nextMapping.generated.column <= currColumn){ |
|
currMappingIndex++; |
|
currMapping = parsedMapData.mappings[currMappingIndex]; |
|
nextMapping = parsedMapData.mappings[currMappingIndex + 1]; |
|
} |
|
let currentSource = currMapping.source; |
|
let charSize = Buffer.byteLength(character, 'utf8'); |
|
if (currentSource != null && currMapping.generated.line === currLine && currMapping.generated.column <= currColumn) sourceSizes[currentSource] += charSize; |
|
else unknownOrigin += charSize; |
|
if (character === '\n') { |
|
currColumn = 0; |
|
currLine++; |
|
} else currColumn++; |
|
} |
|
let sizeMap = new Map(); |
|
for(let i1 = 0; i1 < sourceSizes.length; i1++)sizeMap.set(sources[i1], sourceSizes[i1]); |
|
sizeMap.set('', unknownOrigin); |
|
return sizeMap; |
|
} |
|
} |
|
async function $15d4bc8b6fca8c7e$var$createBundleStats(bundle, fs, projectRoot) { |
|
let filePath1 = bundle.filePath; |
|
let sourcemapSizes = await $15d4bc8b6fca8c7e$var$getSourcemapSizes(filePath1, fs, projectRoot); |
|
let assets = new Map(); |
|
bundle.traverseAssets((asset)=>{ |
|
let filePath = ($parcel$interopDefault($8C1kk$path)).normalize(asset.filePath); |
|
assets.set(filePath, { |
|
filePath: filePath, |
|
size: asset.stats.size, |
|
originalSize: asset.stats.size, |
|
time: asset.stats.time |
|
}); |
|
}); |
|
let assetsReport = []; |
|
if (sourcemapSizes && sourcemapSizes.size) assetsReport = Array.from(sourcemapSizes.keys()).map((filePath)=>{ |
|
let foundSize = sourcemapSizes.get(filePath) || 0; |
|
let stats = assets.get(filePath) || { |
|
filePath: filePath, |
|
size: foundSize, |
|
originalSize: foundSize, |
|
time: 0 |
|
}; |
|
return { |
|
...stats, |
|
size: foundSize |
|
}; |
|
}); |
|
else assetsReport = Array.from(assets.values()); |
|
return { |
|
filePath: (/*@__PURE__*/$parcel$interopDefault($812806c6461f2963$exports))(bundle.filePath), |
|
size: bundle.stats.size, |
|
time: bundle.stats.time, |
|
assets: assetsReport.sort((a, b)=>b.size - a.size |
|
) |
|
}; |
|
} |
|
async function $15d4bc8b6fca8c7e$export$2e2bcd8739ae039(bundles, fs, projectRoot) { |
|
bundles.sort((a, b)=>b.stats.size - a.stats.size |
|
).filter((b)=>!!b.filePath |
|
); |
|
return { |
|
bundles: (await Promise.all(bundles.map((b)=>$15d4bc8b6fca8c7e$var$createBundleStats(b, fs, projectRoot) |
|
))).filter((e)=>!!e |
|
) |
|
}; |
|
} |
|
|
|
|
|
var $99e85628b30fe009$exports = {}; |
|
|
|
/** |
|
* Node.js module for Forge. |
|
* |
|
* @author Dave Longley |
|
* |
|
* Copyright 2011-2016 Digital Bazaar, Inc. |
|
*/ $99e85628b30fe009$exports = (parcelRequire("iGlOy")); |
|
var $ca9d5cba0afae339$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
var $871289bd32ea5f15$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
var $4143f576ffbec226$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
var $53abc20733f4b0dc$exports = {}; |
|
/** |
|
* Base-N/Base-X encoding/decoding functions. |
|
* |
|
* Original implementation from base-x: |
|
* https://github.com/cryptocoinjs/base-x |
|
* |
|
* Which is MIT licensed: |
|
* |
|
* The MIT License (MIT) |
|
* |
|
* Copyright base-x contributors (c) 2016 |
|
* |
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
* of this software and associated documentation files (the "Software"), to deal |
|
* in the Software without restriction, including without limitation the rights |
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
* copies of the Software, and to permit persons to whom the Software is |
|
* furnished to do so, subject to the following conditions: |
|
* |
|
* The above copyright notice and this permission notice shall be included in |
|
* all copies or substantial portions of the Software. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
* DEALINGS IN THE SOFTWARE. |
|
*/ var $53abc20733f4b0dc$var$api = { |
|
}; |
|
$53abc20733f4b0dc$exports = $53abc20733f4b0dc$var$api; |
|
// baseN alphabet indexes |
|
var $53abc20733f4b0dc$var$_reverseAlphabets = { |
|
}; |
|
/** |
|
* BaseN-encodes a Uint8Array using the given alphabet. |
|
* |
|
* @param input the Uint8Array to encode. |
|
* @param maxline the maximum number of encoded characters per line to use, |
|
* defaults to none. |
|
* |
|
* @return the baseN-encoded output string. |
|
*/ $53abc20733f4b0dc$var$api.encode = function(input, alphabet, maxline) { |
|
if (typeof alphabet !== 'string') throw new TypeError('"alphabet" must be a string.'); |
|
if (maxline !== undefined && typeof maxline !== 'number') throw new TypeError('"maxline" must be a number.'); |
|
var output = ''; |
|
if (!(input instanceof Uint8Array)) // assume forge byte buffer |
|
output = $53abc20733f4b0dc$var$_encodeWithByteBuffer(input, alphabet); |
|
else { |
|
var i = 0; |
|
var base = alphabet.length; |
|
var first = alphabet.charAt(0); |
|
var digits = [ |
|
0 |
|
]; |
|
for(i = 0; i < input.length; ++i){ |
|
for(var j = 0, carry = input[i]; j < digits.length; ++j){ |
|
carry += digits[j] << 8; |
|
digits[j] = carry % base; |
|
carry = carry / base | 0; |
|
} |
|
while(carry > 0){ |
|
digits.push(carry % base); |
|
carry = carry / base | 0; |
|
} |
|
} |
|
// deal with leading zeros |
|
for(i = 0; input[i] === 0 && i < input.length - 1; ++i)output += first; |
|
// convert digits to a string |
|
for(i = digits.length - 1; i >= 0; --i)output += alphabet[digits[i]]; |
|
} |
|
if (maxline) { |
|
var regex = new RegExp('.{1,' + maxline + '}', 'g'); |
|
output = output.match(regex).join('\r\n'); |
|
} |
|
return output; |
|
}; |
|
/** |
|
* Decodes a baseN-encoded (using the given alphabet) string to a |
|
* Uint8Array. |
|
* |
|
* @param input the baseN-encoded input string. |
|
* |
|
* @return the Uint8Array. |
|
*/ $53abc20733f4b0dc$var$api.decode = function(input, alphabet) { |
|
if (typeof input !== 'string') throw new TypeError('"input" must be a string.'); |
|
if (typeof alphabet !== 'string') throw new TypeError('"alphabet" must be a string.'); |
|
var table = $53abc20733f4b0dc$var$_reverseAlphabets[alphabet]; |
|
if (!table) { |
|
// compute reverse alphabet |
|
table = $53abc20733f4b0dc$var$_reverseAlphabets[alphabet] = []; |
|
for(var i = 0; i < alphabet.length; ++i)table[alphabet.charCodeAt(i)] = i; |
|
} |
|
// remove whitespace characters |
|
input = input.replace(/\s/g, ''); |
|
var base = alphabet.length; |
|
var first = alphabet.charAt(0); |
|
var bytes = [ |
|
0 |
|
]; |
|
for(var i = 0; i < input.length; i++){ |
|
var value = table[input.charCodeAt(i)]; |
|
if (value === undefined) return; |
|
for(var j = 0, carry = value; j < bytes.length; ++j){ |
|
carry += bytes[j] * base; |
|
bytes[j] = carry & 255; |
|
carry >>= 8; |
|
} |
|
while(carry > 0){ |
|
bytes.push(carry & 255); |
|
carry >>= 8; |
|
} |
|
} |
|
// deal with leading zeros |
|
for(var k = 0; input[k] === first && k < input.length - 1; ++k)bytes.push(0); |
|
if (typeof Buffer !== 'undefined') return Buffer.from(bytes.reverse()); |
|
return new Uint8Array(bytes.reverse()); |
|
}; |
|
function $53abc20733f4b0dc$var$_encodeWithByteBuffer(input, alphabet) { |
|
var i = 0; |
|
var base = alphabet.length; |
|
var first = alphabet.charAt(0); |
|
var digits = [ |
|
0 |
|
]; |
|
for(i = 0; i < input.length(); ++i){ |
|
for(var j = 0, carry = input.at(i); j < digits.length; ++j){ |
|
carry += digits[j] << 8; |
|
digits[j] = carry % base; |
|
carry = carry / base | 0; |
|
} |
|
while(carry > 0){ |
|
digits.push(carry % base); |
|
carry = carry / base | 0; |
|
} |
|
} |
|
var output = ''; |
|
// deal with leading zeros |
|
for(i = 0; input.at(i) === 0 && i < input.length() - 1; ++i)output += first; |
|
// convert digits to a string |
|
for(i = digits.length - 1; i >= 0; --i)output += alphabet[digits[i]]; |
|
return output; |
|
} |
|
|
|
|
|
/* Utilities API */ var $4143f576ffbec226$var$util = $4143f576ffbec226$exports = $iGlOy.util = $iGlOy.util || { |
|
}; |
|
// define setImmediate and nextTick |
|
(function() { |
|
// use native nextTick (unless we're in webpack) |
|
// webpack (or better node-libs-browser polyfill) sets process.browser. |
|
// this way we can detect webpack properly |
|
if (typeof process !== 'undefined' && process.nextTick && !process.browser) { |
|
$4143f576ffbec226$var$util.nextTick = process.nextTick; |
|
if (typeof setImmediate === 'function') $4143f576ffbec226$var$util.setImmediate = setImmediate; |
|
else // polyfill setImmediate with nextTick, older versions of node |
|
// (those w/o setImmediate) won't totally starve IO |
|
$4143f576ffbec226$var$util.setImmediate = $4143f576ffbec226$var$util.nextTick; |
|
return; |
|
} |
|
// polyfill nextTick with native setImmediate |
|
if (typeof setImmediate === 'function') { |
|
$4143f576ffbec226$var$util.setImmediate = function() { |
|
return setImmediate.apply(undefined, arguments); |
|
}; |
|
$4143f576ffbec226$var$util.nextTick = function(callback) { |
|
return setImmediate(callback); |
|
}; |
|
return; |
|
} |
|
/* Note: A polyfill upgrade pattern is used here to allow combining |
|
polyfills. For example, MutationObserver is fast, but blocks UI updates, |
|
so it needs to allow UI updates periodically, so it falls back on |
|
postMessage or setTimeout. */ // polyfill with setTimeout |
|
$4143f576ffbec226$var$util.setImmediate = function(callback) { |
|
setTimeout(callback, 0); |
|
}; |
|
// upgrade polyfill to use postMessage |
|
if (typeof window !== 'undefined' && typeof window.postMessage === 'function') { |
|
var msg = 'forge.setImmediate'; |
|
var callbacks = []; |
|
$4143f576ffbec226$var$util.setImmediate = function(callback) { |
|
callbacks.push(callback); |
|
// only send message when one hasn't been sent in |
|
// the current turn of the event loop |
|
if (callbacks.length === 1) window.postMessage(msg, '*'); |
|
}; |
|
function handler(event) { |
|
if (event.source === window && event.data === msg) { |
|
event.stopPropagation(); |
|
var copy = callbacks.slice(); |
|
callbacks.length = 0; |
|
copy.forEach(function(callback) { |
|
callback(); |
|
}); |
|
} |
|
} |
|
window.addEventListener('message', handler, true); |
|
} |
|
// upgrade polyfill to use MutationObserver |
|
if (typeof MutationObserver !== 'undefined') { |
|
// polyfill with MutationObserver |
|
var now = Date.now(); |
|
var attr = true; |
|
var div = document.createElement('div'); |
|
var callbacks = []; |
|
new MutationObserver(function() { |
|
var copy = callbacks.slice(); |
|
callbacks.length = 0; |
|
copy.forEach(function(callback) { |
|
callback(); |
|
}); |
|
}).observe(div, { |
|
attributes: true |
|
}); |
|
var oldSetImmediate = $4143f576ffbec226$var$util.setImmediate; |
|
$4143f576ffbec226$var$util.setImmediate = function(callback) { |
|
if (Date.now() - now > 15) { |
|
now = Date.now(); |
|
oldSetImmediate(callback); |
|
} else { |
|
callbacks.push(callback); |
|
// only trigger observer when it hasn't been triggered in |
|
// the current turn of the event loop |
|
if (callbacks.length === 1) div.setAttribute('a', attr = !attr); |
|
} |
|
}; |
|
} |
|
$4143f576ffbec226$var$util.nextTick = $4143f576ffbec226$var$util.setImmediate; |
|
})(); |
|
// check if running under Node.js |
|
$4143f576ffbec226$var$util.isNodejs = typeof process !== 'undefined' && process.versions && process.versions.node; |
|
// 'self' will also work in Web Workers (instance of WorkerGlobalScope) while |
|
// it will point to `window` in the main thread. |
|
// To remain compatible with older browsers, we fall back to 'window' if 'self' |
|
// is not available. |
|
$4143f576ffbec226$var$util.globalScope = (function() { |
|
if ($4143f576ffbec226$var$util.isNodejs) return $parcel$global; |
|
return typeof self === 'undefined' ? window : self; |
|
})(); |
|
// define isArray |
|
$4143f576ffbec226$var$util.isArray = Array.isArray || function(x) { |
|
return Object.prototype.toString.call(x) === '[object Array]'; |
|
}; |
|
// define isArrayBuffer |
|
$4143f576ffbec226$var$util.isArrayBuffer = function(x) { |
|
return typeof ArrayBuffer !== 'undefined' && x instanceof ArrayBuffer; |
|
}; |
|
// define isArrayBufferView |
|
$4143f576ffbec226$var$util.isArrayBufferView = function(x) { |
|
return x && $4143f576ffbec226$var$util.isArrayBuffer(x.buffer) && x.byteLength !== undefined; |
|
}; |
|
/** |
|
* Ensure a bits param is 8, 16, 24, or 32. Used to validate input for |
|
* algorithms where bit manipulation, JavaScript limitations, and/or algorithm |
|
* design only allow for byte operations of a limited size. |
|
* |
|
* @param n number of bits. |
|
* |
|
* Throw Error if n invalid. |
|
*/ function $4143f576ffbec226$var$_checkBitsParam(n) { |
|
if (!(n === 8 || n === 16 || n === 24 || n === 32)) throw new Error('Only 8, 16, 24, or 32 bits supported: ' + n); |
|
} |
|
// TODO: set ByteBuffer to best available backing |
|
$4143f576ffbec226$var$util.ByteBuffer = $4143f576ffbec226$var$ByteStringBuffer; |
|
/** Buffer w/BinaryString backing */ /** |
|
* Constructor for a binary string backed byte buffer. |
|
* |
|
* @param [b] the bytes to wrap (either encoded as string, one byte per |
|
* character, or as an ArrayBuffer or Typed Array). |
|
*/ function $4143f576ffbec226$var$ByteStringBuffer(b) { |
|
// TODO: update to match DataBuffer API |
|
// the data in this buffer |
|
this.data = ''; |
|
// the pointer for reading from this buffer |
|
this.read = 0; |
|
if (typeof b === 'string') this.data = b; |
|
else if ($4143f576ffbec226$var$util.isArrayBuffer(b) || $4143f576ffbec226$var$util.isArrayBufferView(b)) { |
|
if (typeof Buffer !== 'undefined' && b instanceof Buffer) this.data = b.toString('binary'); |
|
else { |
|
// convert native buffer to forge buffer |
|
// FIXME: support native buffers internally instead |
|
var arr = new Uint8Array(b); |
|
try { |
|
this.data = String.fromCharCode.apply(null, arr); |
|
} catch (e) { |
|
for(var i = 0; i < arr.length; ++i)this.putByte(arr[i]); |
|
} |
|
} |
|
} else if (b instanceof $4143f576ffbec226$var$ByteStringBuffer || typeof b === 'object' && typeof b.data === 'string' && typeof b.read === 'number') { |
|
// copy existing buffer |
|
this.data = b.data; |
|
this.read = b.read; |
|
} |
|
// used for v8 optimization |
|
this._constructedStringLength = 0; |
|
} |
|
$4143f576ffbec226$var$util.ByteStringBuffer = $4143f576ffbec226$var$ByteStringBuffer; |
|
/* Note: This is an optimization for V8-based browsers. When V8 concatenates |
|
a string, the strings are only joined logically using a "cons string" or |
|
"constructed/concatenated string". These containers keep references to one |
|
another and can result in very large memory usage. For example, if a 2MB |
|
string is constructed by concatenating 4 bytes together at a time, the |
|
memory usage will be ~44MB; so ~22x increase. The strings are only joined |
|
together when an operation requiring their joining takes place, such as |
|
substr(). This function is called when adding data to this buffer to ensure |
|
these types of strings are periodically joined to reduce the memory |
|
footprint. */ var $4143f576ffbec226$var$_MAX_CONSTRUCTED_STRING_LENGTH = 4096; |
|
$4143f576ffbec226$var$util.ByteStringBuffer.prototype._optimizeConstructedString = function(x) { |
|
this._constructedStringLength += x; |
|
if (this._constructedStringLength > $4143f576ffbec226$var$_MAX_CONSTRUCTED_STRING_LENGTH) { |
|
// this substr() should cause the constructed string to join |
|
this.data.substr(0, 1); |
|
this._constructedStringLength = 0; |
|
} |
|
}; |
|
/** |
|
* Gets the number of bytes in this buffer. |
|
* |
|
* @return the number of bytes in this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.length = function() { |
|
return this.data.length - this.read; |
|
}; |
|
/** |
|
* Gets whether or not this buffer is empty. |
|
* |
|
* @return true if this buffer is empty, false if not. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.isEmpty = function() { |
|
return this.length() <= 0; |
|
}; |
|
/** |
|
* Puts a byte in this buffer. |
|
* |
|
* @param b the byte to put. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putByte = function(b) { |
|
return this.putBytes(String.fromCharCode(b)); |
|
}; |
|
/** |
|
* Puts a byte in this buffer N times. |
|
* |
|
* @param b the byte to put. |
|
* @param n the number of bytes of value b to put. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.fillWithByte = function(b, n) { |
|
b = String.fromCharCode(b); |
|
var d = this.data; |
|
while(n > 0){ |
|
if (n & 1) d += b; |
|
n >>>= 1; |
|
if (n > 0) b += b; |
|
} |
|
this.data = d; |
|
this._optimizeConstructedString(n); |
|
return this; |
|
}; |
|
/** |
|
* Puts bytes in this buffer. |
|
* |
|
* @param bytes the bytes (as a binary encoded string) to put. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putBytes = function(bytes) { |
|
this.data += bytes; |
|
this._optimizeConstructedString(bytes.length); |
|
return this; |
|
}; |
|
/** |
|
* Puts a UTF-16 encoded string into this buffer. |
|
* |
|
* @param str the string to put. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putString = function(str) { |
|
return this.putBytes($4143f576ffbec226$var$util.encodeUtf8(str)); |
|
}; |
|
/** |
|
* Puts a 16-bit integer in this buffer in big-endian order. |
|
* |
|
* @param i the 16-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putInt16 = function(i) { |
|
return this.putBytes(String.fromCharCode(i >> 8 & 255) + String.fromCharCode(i & 255)); |
|
}; |
|
/** |
|
* Puts a 24-bit integer in this buffer in big-endian order. |
|
* |
|
* @param i the 24-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putInt24 = function(i) { |
|
return this.putBytes(String.fromCharCode(i >> 16 & 255) + String.fromCharCode(i >> 8 & 255) + String.fromCharCode(i & 255)); |
|
}; |
|
/** |
|
* Puts a 32-bit integer in this buffer in big-endian order. |
|
* |
|
* @param i the 32-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putInt32 = function(i) { |
|
return this.putBytes(String.fromCharCode(i >> 24 & 255) + String.fromCharCode(i >> 16 & 255) + String.fromCharCode(i >> 8 & 255) + String.fromCharCode(i & 255)); |
|
}; |
|
/** |
|
* Puts a 16-bit integer in this buffer in little-endian order. |
|
* |
|
* @param i the 16-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putInt16Le = function(i) { |
|
return this.putBytes(String.fromCharCode(i & 255) + String.fromCharCode(i >> 8 & 255)); |
|
}; |
|
/** |
|
* Puts a 24-bit integer in this buffer in little-endian order. |
|
* |
|
* @param i the 24-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putInt24Le = function(i) { |
|
return this.putBytes(String.fromCharCode(i & 255) + String.fromCharCode(i >> 8 & 255) + String.fromCharCode(i >> 16 & 255)); |
|
}; |
|
/** |
|
* Puts a 32-bit integer in this buffer in little-endian order. |
|
* |
|
* @param i the 32-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putInt32Le = function(i) { |
|
return this.putBytes(String.fromCharCode(i & 255) + String.fromCharCode(i >> 8 & 255) + String.fromCharCode(i >> 16 & 255) + String.fromCharCode(i >> 24 & 255)); |
|
}; |
|
/** |
|
* Puts an n-bit integer in this buffer in big-endian order. |
|
* |
|
* @param i the n-bit integer. |
|
* @param n the number of bits in the integer (8, 16, 24, or 32). |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putInt = function(i, n) { |
|
$4143f576ffbec226$var$_checkBitsParam(n); |
|
var bytes = ''; |
|
do { |
|
n -= 8; |
|
bytes += String.fromCharCode(i >> n & 255); |
|
}while (n > 0) |
|
return this.putBytes(bytes); |
|
}; |
|
/** |
|
* Puts a signed n-bit integer in this buffer in big-endian order. Two's |
|
* complement representation is used. |
|
* |
|
* @param i the n-bit integer. |
|
* @param n the number of bits in the integer (8, 16, 24, or 32). |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putSignedInt = function(i, n) { |
|
// putInt checks n |
|
if (i < 0) i += 2 << n - 1; |
|
return this.putInt(i, n); |
|
}; |
|
/** |
|
* Puts the given buffer into this buffer. |
|
* |
|
* @param buffer the buffer to put into this one. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.putBuffer = function(buffer) { |
|
return this.putBytes(buffer.getBytes()); |
|
}; |
|
/** |
|
* Gets a byte from this buffer and advances the read pointer by 1. |
|
* |
|
* @return the byte. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getByte = function() { |
|
return this.data.charCodeAt(this.read++); |
|
}; |
|
/** |
|
* Gets a uint16 from this buffer in big-endian order and advances the read |
|
* pointer by 2. |
|
* |
|
* @return the uint16. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getInt16 = function() { |
|
var rval = this.data.charCodeAt(this.read) << 8 ^ this.data.charCodeAt(this.read + 1); |
|
this.read += 2; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint24 from this buffer in big-endian order and advances the read |
|
* pointer by 3. |
|
* |
|
* @return the uint24. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getInt24 = function() { |
|
var rval = this.data.charCodeAt(this.read) << 16 ^ this.data.charCodeAt(this.read + 1) << 8 ^ this.data.charCodeAt(this.read + 2); |
|
this.read += 3; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint32 from this buffer in big-endian order and advances the read |
|
* pointer by 4. |
|
* |
|
* @return the word. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getInt32 = function() { |
|
var rval = this.data.charCodeAt(this.read) << 24 ^ this.data.charCodeAt(this.read + 1) << 16 ^ this.data.charCodeAt(this.read + 2) << 8 ^ this.data.charCodeAt(this.read + 3); |
|
this.read += 4; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint16 from this buffer in little-endian order and advances the read |
|
* pointer by 2. |
|
* |
|
* @return the uint16. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getInt16Le = function() { |
|
var rval = this.data.charCodeAt(this.read) ^ this.data.charCodeAt(this.read + 1) << 8; |
|
this.read += 2; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint24 from this buffer in little-endian order and advances the read |
|
* pointer by 3. |
|
* |
|
* @return the uint24. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getInt24Le = function() { |
|
var rval = this.data.charCodeAt(this.read) ^ this.data.charCodeAt(this.read + 1) << 8 ^ this.data.charCodeAt(this.read + 2) << 16; |
|
this.read += 3; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint32 from this buffer in little-endian order and advances the read |
|
* pointer by 4. |
|
* |
|
* @return the word. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getInt32Le = function() { |
|
var rval = this.data.charCodeAt(this.read) ^ this.data.charCodeAt(this.read + 1) << 8 ^ this.data.charCodeAt(this.read + 2) << 16 ^ this.data.charCodeAt(this.read + 3) << 24; |
|
this.read += 4; |
|
return rval; |
|
}; |
|
/** |
|
* Gets an n-bit integer from this buffer in big-endian order and advances the |
|
* read pointer by ceil(n/8). |
|
* |
|
* @param n the number of bits in the integer (8, 16, 24, or 32). |
|
* |
|
* @return the integer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getInt = function(n) { |
|
$4143f576ffbec226$var$_checkBitsParam(n); |
|
var rval = 0; |
|
do { |
|
// TODO: Use (rval * 0x100) if adding support for 33 to 53 bits. |
|
rval = (rval << 8) + this.data.charCodeAt(this.read++); |
|
n -= 8; |
|
}while (n > 0) |
|
return rval; |
|
}; |
|
/** |
|
* Gets a signed n-bit integer from this buffer in big-endian order, using |
|
* two's complement, and advances the read pointer by n/8. |
|
* |
|
* @param n the number of bits in the integer (8, 16, 24, or 32). |
|
* |
|
* @return the integer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getSignedInt = function(n) { |
|
// getInt checks n |
|
var x = this.getInt(n); |
|
var max = 2 << n - 2; |
|
if (x >= max) x -= max << 1; |
|
return x; |
|
}; |
|
/** |
|
* Reads bytes out as a binary encoded string and clears them from the |
|
* buffer. Note that the resulting string is binary encoded (in node.js this |
|
* encoding is referred to as `binary`, it is *not* `utf8`). |
|
* |
|
* @param count the number of bytes to read, undefined or null for all. |
|
* |
|
* @return a binary encoded string of bytes. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.getBytes = function(count) { |
|
var rval; |
|
if (count) { |
|
// read count bytes |
|
count = Math.min(this.length(), count); |
|
rval = this.data.slice(this.read, this.read + count); |
|
this.read += count; |
|
} else if (count === 0) rval = ''; |
|
else { |
|
// read all bytes, optimize to only copy when needed |
|
rval = this.read === 0 ? this.data : this.data.slice(this.read); |
|
this.clear(); |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Gets a binary encoded string of the bytes from this buffer without |
|
* modifying the read pointer. |
|
* |
|
* @param count the number of bytes to get, omit to get all. |
|
* |
|
* @return a string full of binary encoded characters. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.bytes = function(count) { |
|
return typeof count === 'undefined' ? this.data.slice(this.read) : this.data.slice(this.read, this.read + count); |
|
}; |
|
/** |
|
* Gets a byte at the given index without modifying the read pointer. |
|
* |
|
* @param i the byte index. |
|
* |
|
* @return the byte. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.at = function(i) { |
|
return this.data.charCodeAt(this.read + i); |
|
}; |
|
/** |
|
* Puts a byte at the given index without modifying the read pointer. |
|
* |
|
* @param i the byte index. |
|
* @param b the byte to put. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.setAt = function(i, b) { |
|
this.data = this.data.substr(0, this.read + i) + String.fromCharCode(b) + this.data.substr(this.read + i + 1); |
|
return this; |
|
}; |
|
/** |
|
* Gets the last byte without modifying the read pointer. |
|
* |
|
* @return the last byte. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.last = function() { |
|
return this.data.charCodeAt(this.data.length - 1); |
|
}; |
|
/** |
|
* Creates a copy of this buffer. |
|
* |
|
* @return the copy. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.copy = function() { |
|
var c = $4143f576ffbec226$var$util.createBuffer(this.data); |
|
c.read = this.read; |
|
return c; |
|
}; |
|
/** |
|
* Compacts this buffer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.compact = function() { |
|
if (this.read > 0) { |
|
this.data = this.data.slice(this.read); |
|
this.read = 0; |
|
} |
|
return this; |
|
}; |
|
/** |
|
* Clears this buffer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.clear = function() { |
|
this.data = ''; |
|
this.read = 0; |
|
return this; |
|
}; |
|
/** |
|
* Shortens this buffer by triming bytes off of the end of this buffer. |
|
* |
|
* @param count the number of bytes to trim off. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.truncate = function(count) { |
|
var len = Math.max(0, this.length() - count); |
|
this.data = this.data.substr(this.read, len); |
|
this.read = 0; |
|
return this; |
|
}; |
|
/** |
|
* Converts this buffer to a hexadecimal string. |
|
* |
|
* @return a hexadecimal string. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.toHex = function() { |
|
var rval = ''; |
|
for(var i = this.read; i < this.data.length; ++i){ |
|
var b = this.data.charCodeAt(i); |
|
if (b < 16) rval += '0'; |
|
rval += b.toString(16); |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Converts this buffer to a UTF-16 string (standard JavaScript string). |
|
* |
|
* @return a UTF-16 string. |
|
*/ $4143f576ffbec226$var$util.ByteStringBuffer.prototype.toString = function() { |
|
return $4143f576ffbec226$var$util.decodeUtf8(this.bytes()); |
|
}; |
|
/** End Buffer w/BinaryString backing */ /** Buffer w/UInt8Array backing */ /** |
|
* FIXME: Experimental. Do not use yet. |
|
* |
|
* Constructor for an ArrayBuffer-backed byte buffer. |
|
* |
|
* The buffer may be constructed from a string, an ArrayBuffer, DataView, or a |
|
* TypedArray. |
|
* |
|
* If a string is given, its encoding should be provided as an option, |
|
* otherwise it will default to 'binary'. A 'binary' string is encoded such |
|
* that each character is one byte in length and size. |
|
* |
|
* If an ArrayBuffer, DataView, or TypedArray is given, it will be used |
|
* *directly* without any copying. Note that, if a write to the buffer requires |
|
* more space, the buffer will allocate a new backing ArrayBuffer to |
|
* accommodate. The starting read and write offsets for the buffer may be |
|
* given as options. |
|
* |
|
* @param [b] the initial bytes for this buffer. |
|
* @param options the options to use: |
|
* [readOffset] the starting read offset to use (default: 0). |
|
* [writeOffset] the starting write offset to use (default: the |
|
* length of the first parameter). |
|
* [growSize] the minimum amount, in bytes, to grow the buffer by to |
|
* accommodate writes (default: 1024). |
|
* [encoding] the encoding ('binary', 'utf8', 'utf16', 'hex') for the |
|
* first parameter, if it is a string (default: 'binary'). |
|
*/ function $4143f576ffbec226$var$DataBuffer(b, options) { |
|
// default options |
|
options = options || { |
|
}; |
|
// pointers for read from/write to buffer |
|
this.read = options.readOffset || 0; |
|
this.growSize = options.growSize || 1024; |
|
var isArrayBuffer = $4143f576ffbec226$var$util.isArrayBuffer(b); |
|
var isArrayBufferView = $4143f576ffbec226$var$util.isArrayBufferView(b); |
|
if (isArrayBuffer || isArrayBufferView) { |
|
// use ArrayBuffer directly |
|
if (isArrayBuffer) this.data = new DataView(b); |
|
else // TODO: adjust read/write offset based on the type of view |
|
// or specify that this must be done in the options ... that the |
|
// offsets are byte-based |
|
this.data = new DataView(b.buffer, b.byteOffset, b.byteLength); |
|
this.write = 'writeOffset' in options ? options.writeOffset : this.data.byteLength; |
|
return; |
|
} |
|
// initialize to empty array buffer and add any given bytes using putBytes |
|
this.data = new DataView(new ArrayBuffer(0)); |
|
this.write = 0; |
|
if (b !== null && b !== undefined) this.putBytes(b); |
|
if ('writeOffset' in options) this.write = options.writeOffset; |
|
} |
|
$4143f576ffbec226$var$util.DataBuffer = $4143f576ffbec226$var$DataBuffer; |
|
/** |
|
* Gets the number of bytes in this buffer. |
|
* |
|
* @return the number of bytes in this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.length = function() { |
|
return this.write - this.read; |
|
}; |
|
/** |
|
* Gets whether or not this buffer is empty. |
|
* |
|
* @return true if this buffer is empty, false if not. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.isEmpty = function() { |
|
return this.length() <= 0; |
|
}; |
|
/** |
|
* Ensures this buffer has enough empty space to accommodate the given number |
|
* of bytes. An optional parameter may be given that indicates a minimum |
|
* amount to grow the buffer if necessary. If the parameter is not given, |
|
* the buffer will be grown by some previously-specified default amount |
|
* or heuristic. |
|
* |
|
* @param amount the number of bytes to accommodate. |
|
* @param [growSize] the minimum amount, in bytes, to grow the buffer by if |
|
* necessary. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.accommodate = function(amount, growSize) { |
|
if (this.length() >= amount) return this; |
|
growSize = Math.max(growSize || this.growSize, amount); |
|
// grow buffer |
|
var src = new Uint8Array(this.data.buffer, this.data.byteOffset, this.data.byteLength); |
|
var dst = new Uint8Array(this.length() + growSize); |
|
dst.set(src); |
|
this.data = new DataView(dst.buffer); |
|
return this; |
|
}; |
|
/** |
|
* Puts a byte in this buffer. |
|
* |
|
* @param b the byte to put. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putByte = function(b) { |
|
this.accommodate(1); |
|
this.data.setUint8(this.write++, b); |
|
return this; |
|
}; |
|
/** |
|
* Puts a byte in this buffer N times. |
|
* |
|
* @param b the byte to put. |
|
* @param n the number of bytes of value b to put. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.fillWithByte = function(b, n) { |
|
this.accommodate(n); |
|
for(var i = 0; i < n; ++i)this.data.setUint8(b); |
|
return this; |
|
}; |
|
/** |
|
* Puts bytes in this buffer. The bytes may be given as a string, an |
|
* ArrayBuffer, a DataView, or a TypedArray. |
|
* |
|
* @param bytes the bytes to put. |
|
* @param [encoding] the encoding for the first parameter ('binary', 'utf8', |
|
* 'utf16', 'hex'), if it is a string (default: 'binary'). |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putBytes = function(bytes, encoding) { |
|
if ($4143f576ffbec226$var$util.isArrayBufferView(bytes)) { |
|
var src = new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength); |
|
var len = src.byteLength - src.byteOffset; |
|
this.accommodate(len); |
|
var dst = new Uint8Array(this.data.buffer, this.write); |
|
dst.set(src); |
|
this.write += len; |
|
return this; |
|
} |
|
if ($4143f576ffbec226$var$util.isArrayBuffer(bytes)) { |
|
var src = new Uint8Array(bytes); |
|
this.accommodate(src.byteLength); |
|
var dst = new Uint8Array(this.data.buffer); |
|
dst.set(src, this.write); |
|
this.write += src.byteLength; |
|
return this; |
|
} |
|
// bytes is a util.DataBuffer or equivalent |
|
if (bytes instanceof $4143f576ffbec226$var$util.DataBuffer || typeof bytes === 'object' && typeof bytes.read === 'number' && typeof bytes.write === 'number' && $4143f576ffbec226$var$util.isArrayBufferView(bytes.data)) { |
|
var src = new Uint8Array(bytes.data.byteLength, bytes.read, bytes.length()); |
|
this.accommodate(src.byteLength); |
|
var dst = new Uint8Array(bytes.data.byteLength, this.write); |
|
dst.set(src); |
|
this.write += src.byteLength; |
|
return this; |
|
} |
|
if (bytes instanceof $4143f576ffbec226$var$util.ByteStringBuffer) { |
|
// copy binary string and process as the same as a string parameter below |
|
bytes = bytes.data; |
|
encoding = 'binary'; |
|
} |
|
// string conversion |
|
encoding = encoding || 'binary'; |
|
if (typeof bytes === 'string') { |
|
var view; |
|
// decode from string |
|
if (encoding === 'hex') { |
|
this.accommodate(Math.ceil(bytes.length / 2)); |
|
view = new Uint8Array(this.data.buffer, this.write); |
|
this.write += $4143f576ffbec226$var$util.binary.hex.decode(bytes, view, this.write); |
|
return this; |
|
} |
|
if (encoding === 'base64') { |
|
this.accommodate(Math.ceil(bytes.length / 4) * 3); |
|
view = new Uint8Array(this.data.buffer, this.write); |
|
this.write += $4143f576ffbec226$var$util.binary.base64.decode(bytes, view, this.write); |
|
return this; |
|
} |
|
// encode text as UTF-8 bytes |
|
if (encoding === 'utf8') { |
|
// encode as UTF-8 then decode string as raw binary |
|
bytes = $4143f576ffbec226$var$util.encodeUtf8(bytes); |
|
encoding = 'binary'; |
|
} |
|
// decode string as raw binary |
|
if (encoding === 'binary' || encoding === 'raw') { |
|
// one byte per character |
|
this.accommodate(bytes.length); |
|
view = new Uint8Array(this.data.buffer, this.write); |
|
this.write += $4143f576ffbec226$var$util.binary.raw.decode(view); |
|
return this; |
|
} |
|
// encode text as UTF-16 bytes |
|
if (encoding === 'utf16') { |
|
// two bytes per character |
|
this.accommodate(bytes.length * 2); |
|
view = new Uint16Array(this.data.buffer, this.write); |
|
this.write += $4143f576ffbec226$var$util.text.utf16.encode(view); |
|
return this; |
|
} |
|
throw new Error('Invalid encoding: ' + encoding); |
|
} |
|
throw Error('Invalid parameter: ' + bytes); |
|
}; |
|
/** |
|
* Puts the given buffer into this buffer. |
|
* |
|
* @param buffer the buffer to put into this one. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putBuffer = function(buffer) { |
|
this.putBytes(buffer); |
|
buffer.clear(); |
|
return this; |
|
}; |
|
/** |
|
* Puts a string into this buffer. |
|
* |
|
* @param str the string to put. |
|
* @param [encoding] the encoding for the string (default: 'utf16'). |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putString = function(str) { |
|
return this.putBytes(str, 'utf16'); |
|
}; |
|
/** |
|
* Puts a 16-bit integer in this buffer in big-endian order. |
|
* |
|
* @param i the 16-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putInt16 = function(i) { |
|
this.accommodate(2); |
|
this.data.setInt16(this.write, i); |
|
this.write += 2; |
|
return this; |
|
}; |
|
/** |
|
* Puts a 24-bit integer in this buffer in big-endian order. |
|
* |
|
* @param i the 24-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putInt24 = function(i) { |
|
this.accommodate(3); |
|
this.data.setInt16(this.write, i >> 8 & 65535); |
|
this.data.setInt8(this.write, i >> 16 & 255); |
|
this.write += 3; |
|
return this; |
|
}; |
|
/** |
|
* Puts a 32-bit integer in this buffer in big-endian order. |
|
* |
|
* @param i the 32-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putInt32 = function(i) { |
|
this.accommodate(4); |
|
this.data.setInt32(this.write, i); |
|
this.write += 4; |
|
return this; |
|
}; |
|
/** |
|
* Puts a 16-bit integer in this buffer in little-endian order. |
|
* |
|
* @param i the 16-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putInt16Le = function(i) { |
|
this.accommodate(2); |
|
this.data.setInt16(this.write, i, true); |
|
this.write += 2; |
|
return this; |
|
}; |
|
/** |
|
* Puts a 24-bit integer in this buffer in little-endian order. |
|
* |
|
* @param i the 24-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putInt24Le = function(i) { |
|
this.accommodate(3); |
|
this.data.setInt8(this.write, i >> 16 & 255); |
|
this.data.setInt16(this.write, i >> 8 & 65535, true); |
|
this.write += 3; |
|
return this; |
|
}; |
|
/** |
|
* Puts a 32-bit integer in this buffer in little-endian order. |
|
* |
|
* @param i the 32-bit integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putInt32Le = function(i) { |
|
this.accommodate(4); |
|
this.data.setInt32(this.write, i, true); |
|
this.write += 4; |
|
return this; |
|
}; |
|
/** |
|
* Puts an n-bit integer in this buffer in big-endian order. |
|
* |
|
* @param i the n-bit integer. |
|
* @param n the number of bits in the integer (8, 16, 24, or 32). |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putInt = function(i, n) { |
|
$4143f576ffbec226$var$_checkBitsParam(n); |
|
this.accommodate(n / 8); |
|
do { |
|
n -= 8; |
|
this.data.setInt8(this.write++, i >> n & 255); |
|
}while (n > 0) |
|
return this; |
|
}; |
|
/** |
|
* Puts a signed n-bit integer in this buffer in big-endian order. Two's |
|
* complement representation is used. |
|
* |
|
* @param i the n-bit integer. |
|
* @param n the number of bits in the integer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.putSignedInt = function(i, n) { |
|
$4143f576ffbec226$var$_checkBitsParam(n); |
|
this.accommodate(n / 8); |
|
if (i < 0) i += 2 << n - 1; |
|
return this.putInt(i, n); |
|
}; |
|
/** |
|
* Gets a byte from this buffer and advances the read pointer by 1. |
|
* |
|
* @return the byte. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getByte = function() { |
|
return this.data.getInt8(this.read++); |
|
}; |
|
/** |
|
* Gets a uint16 from this buffer in big-endian order and advances the read |
|
* pointer by 2. |
|
* |
|
* @return the uint16. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getInt16 = function() { |
|
var rval = this.data.getInt16(this.read); |
|
this.read += 2; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint24 from this buffer in big-endian order and advances the read |
|
* pointer by 3. |
|
* |
|
* @return the uint24. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getInt24 = function() { |
|
var rval = this.data.getInt16(this.read) << 8 ^ this.data.getInt8(this.read + 2); |
|
this.read += 3; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint32 from this buffer in big-endian order and advances the read |
|
* pointer by 4. |
|
* |
|
* @return the word. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getInt32 = function() { |
|
var rval = this.data.getInt32(this.read); |
|
this.read += 4; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint16 from this buffer in little-endian order and advances the read |
|
* pointer by 2. |
|
* |
|
* @return the uint16. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getInt16Le = function() { |
|
var rval = this.data.getInt16(this.read, true); |
|
this.read += 2; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint24 from this buffer in little-endian order and advances the read |
|
* pointer by 3. |
|
* |
|
* @return the uint24. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getInt24Le = function() { |
|
var rval = this.data.getInt8(this.read) ^ this.data.getInt16(this.read + 1, true) << 8; |
|
this.read += 3; |
|
return rval; |
|
}; |
|
/** |
|
* Gets a uint32 from this buffer in little-endian order and advances the read |
|
* pointer by 4. |
|
* |
|
* @return the word. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getInt32Le = function() { |
|
var rval = this.data.getInt32(this.read, true); |
|
this.read += 4; |
|
return rval; |
|
}; |
|
/** |
|
* Gets an n-bit integer from this buffer in big-endian order and advances the |
|
* read pointer by n/8. |
|
* |
|
* @param n the number of bits in the integer (8, 16, 24, or 32). |
|
* |
|
* @return the integer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getInt = function(n) { |
|
$4143f576ffbec226$var$_checkBitsParam(n); |
|
var rval = 0; |
|
do { |
|
// TODO: Use (rval * 0x100) if adding support for 33 to 53 bits. |
|
rval = (rval << 8) + this.data.getInt8(this.read++); |
|
n -= 8; |
|
}while (n > 0) |
|
return rval; |
|
}; |
|
/** |
|
* Gets a signed n-bit integer from this buffer in big-endian order, using |
|
* two's complement, and advances the read pointer by n/8. |
|
* |
|
* @param n the number of bits in the integer (8, 16, 24, or 32). |
|
* |
|
* @return the integer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getSignedInt = function(n) { |
|
// getInt checks n |
|
var x = this.getInt(n); |
|
var max = 2 << n - 2; |
|
if (x >= max) x -= max << 1; |
|
return x; |
|
}; |
|
/** |
|
* Reads bytes out as a binary encoded string and clears them from the |
|
* buffer. |
|
* |
|
* @param count the number of bytes to read, undefined or null for all. |
|
* |
|
* @return a binary encoded string of bytes. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.getBytes = function(count) { |
|
// TODO: deprecate this method, it is poorly named and |
|
// this.toString('binary') replaces it |
|
// add a toTypedArray()/toArrayBuffer() function |
|
var rval; |
|
if (count) { |
|
// read count bytes |
|
count = Math.min(this.length(), count); |
|
rval = this.data.slice(this.read, this.read + count); |
|
this.read += count; |
|
} else if (count === 0) rval = ''; |
|
else { |
|
// read all bytes, optimize to only copy when needed |
|
rval = this.read === 0 ? this.data : this.data.slice(this.read); |
|
this.clear(); |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Gets a binary encoded string of the bytes from this buffer without |
|
* modifying the read pointer. |
|
* |
|
* @param count the number of bytes to get, omit to get all. |
|
* |
|
* @return a string full of binary encoded characters. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.bytes = function(count) { |
|
// TODO: deprecate this method, it is poorly named, add "getString()" |
|
return typeof count === 'undefined' ? this.data.slice(this.read) : this.data.slice(this.read, this.read + count); |
|
}; |
|
/** |
|
* Gets a byte at the given index without modifying the read pointer. |
|
* |
|
* @param i the byte index. |
|
* |
|
* @return the byte. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.at = function(i) { |
|
return this.data.getUint8(this.read + i); |
|
}; |
|
/** |
|
* Puts a byte at the given index without modifying the read pointer. |
|
* |
|
* @param i the byte index. |
|
* @param b the byte to put. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.setAt = function(i, b) { |
|
this.data.setUint8(i, b); |
|
return this; |
|
}; |
|
/** |
|
* Gets the last byte without modifying the read pointer. |
|
* |
|
* @return the last byte. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.last = function() { |
|
return this.data.getUint8(this.write - 1); |
|
}; |
|
/** |
|
* Creates a copy of this buffer. |
|
* |
|
* @return the copy. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.copy = function() { |
|
return new $4143f576ffbec226$var$util.DataBuffer(this); |
|
}; |
|
/** |
|
* Compacts this buffer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.compact = function() { |
|
if (this.read > 0) { |
|
var src = new Uint8Array(this.data.buffer, this.read); |
|
var dst = new Uint8Array(src.byteLength); |
|
dst.set(src); |
|
this.data = new DataView(dst); |
|
this.write -= this.read; |
|
this.read = 0; |
|
} |
|
return this; |
|
}; |
|
/** |
|
* Clears this buffer. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.clear = function() { |
|
this.data = new DataView(new ArrayBuffer(0)); |
|
this.read = this.write = 0; |
|
return this; |
|
}; |
|
/** |
|
* Shortens this buffer by triming bytes off of the end of this buffer. |
|
* |
|
* @param count the number of bytes to trim off. |
|
* |
|
* @return this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.truncate = function(count) { |
|
this.write = Math.max(0, this.length() - count); |
|
this.read = Math.min(this.read, this.write); |
|
return this; |
|
}; |
|
/** |
|
* Converts this buffer to a hexadecimal string. |
|
* |
|
* @return a hexadecimal string. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.toHex = function() { |
|
var rval = ''; |
|
for(var i = this.read; i < this.data.byteLength; ++i){ |
|
var b = this.data.getUint8(i); |
|
if (b < 16) rval += '0'; |
|
rval += b.toString(16); |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Converts this buffer to a string, using the given encoding. If no |
|
* encoding is given, 'utf8' (UTF-8) is used. |
|
* |
|
* @param [encoding] the encoding to use: 'binary', 'utf8', 'utf16', 'hex', |
|
* 'base64' (default: 'utf8'). |
|
* |
|
* @return a string representation of the bytes in this buffer. |
|
*/ $4143f576ffbec226$var$util.DataBuffer.prototype.toString = function(encoding) { |
|
var view = new Uint8Array(this.data, this.read, this.length()); |
|
encoding = encoding || 'utf8'; |
|
// encode to string |
|
if (encoding === 'binary' || encoding === 'raw') return $4143f576ffbec226$var$util.binary.raw.encode(view); |
|
if (encoding === 'hex') return $4143f576ffbec226$var$util.binary.hex.encode(view); |
|
if (encoding === 'base64') return $4143f576ffbec226$var$util.binary.base64.encode(view); |
|
// decode to text |
|
if (encoding === 'utf8') return $4143f576ffbec226$var$util.text.utf8.decode(view); |
|
if (encoding === 'utf16') return $4143f576ffbec226$var$util.text.utf16.decode(view); |
|
throw new Error('Invalid encoding: ' + encoding); |
|
}; |
|
/** End Buffer w/UInt8Array backing */ /** |
|
* Creates a buffer that stores bytes. A value may be given to populate the |
|
* buffer with data. This value can either be string of encoded bytes or a |
|
* regular string of characters. When passing a string of binary encoded |
|
* bytes, the encoding `raw` should be given. This is also the default. When |
|
* passing a string of characters, the encoding `utf8` should be given. |
|
* |
|
* @param [input] a string with encoded bytes to store in the buffer. |
|
* @param [encoding] (default: 'raw', other: 'utf8'). |
|
*/ $4143f576ffbec226$var$util.createBuffer = function(input, encoding) { |
|
// TODO: deprecate, use new ByteBuffer() instead |
|
encoding = encoding || 'raw'; |
|
if (input !== undefined && encoding === 'utf8') input = $4143f576ffbec226$var$util.encodeUtf8(input); |
|
return new $4143f576ffbec226$var$util.ByteBuffer(input); |
|
}; |
|
/** |
|
* Fills a string with a particular value. If you want the string to be a byte |
|
* string, pass in String.fromCharCode(theByte). |
|
* |
|
* @param c the character to fill the string with, use String.fromCharCode |
|
* to fill the string with a byte value. |
|
* @param n the number of characters of value c to fill with. |
|
* |
|
* @return the filled string. |
|
*/ $4143f576ffbec226$var$util.fillString = function(c, n) { |
|
var s = ''; |
|
while(n > 0){ |
|
if (n & 1) s += c; |
|
n >>>= 1; |
|
if (n > 0) c += c; |
|
} |
|
return s; |
|
}; |
|
/** |
|
* Performs a per byte XOR between two byte strings and returns the result as a |
|
* string of bytes. |
|
* |
|
* @param s1 first string of bytes. |
|
* @param s2 second string of bytes. |
|
* @param n the number of bytes to XOR. |
|
* |
|
* @return the XOR'd result. |
|
*/ $4143f576ffbec226$var$util.xorBytes = function(s1, s2, n) { |
|
var s3 = ''; |
|
var b = ''; |
|
var t = ''; |
|
var i = 0; |
|
var c = 0; |
|
for(; n > 0; --n, ++i){ |
|
b = s1.charCodeAt(i) ^ s2.charCodeAt(i); |
|
if (c >= 10) { |
|
s3 += t; |
|
t = ''; |
|
c = 0; |
|
} |
|
t += String.fromCharCode(b); |
|
++c; |
|
} |
|
s3 += t; |
|
return s3; |
|
}; |
|
/** |
|
* Converts a hex string into a 'binary' encoded string of bytes. |
|
* |
|
* @param hex the hexadecimal string to convert. |
|
* |
|
* @return the binary-encoded string of bytes. |
|
*/ $4143f576ffbec226$var$util.hexToBytes = function(hex) { |
|
// TODO: deprecate: "Deprecated. Use util.binary.hex.decode instead." |
|
var rval = ''; |
|
var i = 0; |
|
if (hex.length & true) { |
|
// odd number of characters, convert first character alone |
|
i = 1; |
|
rval += String.fromCharCode(parseInt(hex[0], 16)); |
|
} |
|
// convert 2 characters (1 byte) at a time |
|
for(; i < hex.length; i += 2)rval += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); |
|
return rval; |
|
}; |
|
/** |
|
* Converts a 'binary' encoded string of bytes to hex. |
|
* |
|
* @param bytes the byte string to convert. |
|
* |
|
* @return the string of hexadecimal characters. |
|
*/ $4143f576ffbec226$var$util.bytesToHex = function(bytes) { |
|
// TODO: deprecate: "Deprecated. Use util.binary.hex.encode instead." |
|
return $4143f576ffbec226$var$util.createBuffer(bytes).toHex(); |
|
}; |
|
/** |
|
* Converts an 32-bit integer to 4-big-endian byte string. |
|
* |
|
* @param i the integer. |
|
* |
|
* @return the byte string. |
|
*/ $4143f576ffbec226$var$util.int32ToBytes = function(i) { |
|
return String.fromCharCode(i >> 24 & 255) + String.fromCharCode(i >> 16 & 255) + String.fromCharCode(i >> 8 & 255) + String.fromCharCode(i & 255); |
|
}; |
|
// base64 characters, reverse mapping |
|
var $4143f576ffbec226$var$_base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; |
|
var $4143f576ffbec226$var$_base64Idx = [ |
|
/*43 -43 = 0*/ /*'+', 1, 2, 3,'/' */ 62, |
|
-1, |
|
-1, |
|
-1, |
|
63, |
|
/*'0','1','2','3','4','5','6','7','8','9' */ 52, |
|
53, |
|
54, |
|
55, |
|
56, |
|
57, |
|
58, |
|
59, |
|
60, |
|
61, |
|
/*15, 16, 17,'=', 19, 20, 21 */ -1, |
|
-1, |
|
-1, |
|
64, |
|
-1, |
|
-1, |
|
-1, |
|
/*65 - 43 = 22*/ /*'A','B','C','D','E','F','G','H','I','J','K','L','M', */ 0, |
|
1, |
|
2, |
|
3, |
|
4, |
|
5, |
|
6, |
|
7, |
|
8, |
|
9, |
|
10, |
|
11, |
|
12, |
|
/*'N','O','P','Q','R','S','T','U','V','W','X','Y','Z' */ 13, |
|
14, |
|
15, |
|
16, |
|
17, |
|
18, |
|
19, |
|
20, |
|
21, |
|
22, |
|
23, |
|
24, |
|
25, |
|
/*91 - 43 = 48 */ /*48, 49, 50, 51, 52, 53 */ -1, |
|
-1, |
|
-1, |
|
-1, |
|
-1, |
|
-1, |
|
/*97 - 43 = 54*/ /*'a','b','c','d','e','f','g','h','i','j','k','l','m' */ 26, |
|
27, |
|
28, |
|
29, |
|
30, |
|
31, |
|
32, |
|
33, |
|
34, |
|
35, |
|
36, |
|
37, |
|
38, |
|
/*'n','o','p','q','r','s','t','u','v','w','x','y','z' */ 39, |
|
40, |
|
41, |
|
42, |
|
43, |
|
44, |
|
45, |
|
46, |
|
47, |
|
48, |
|
49, |
|
50, |
|
51 |
|
]; |
|
// base58 characters (Bitcoin alphabet) |
|
var $4143f576ffbec226$var$_base58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; |
|
/** |
|
* Base64 encodes a 'binary' encoded string of bytes. |
|
* |
|
* @param input the binary encoded string of bytes to base64-encode. |
|
* @param maxline the maximum number of encoded characters per line to use, |
|
* defaults to none. |
|
* |
|
* @return the base64-encoded output. |
|
*/ $4143f576ffbec226$var$util.encode64 = function(input, maxline) { |
|
// TODO: deprecate: "Deprecated. Use util.binary.base64.encode instead." |
|
var line = ''; |
|
var output = ''; |
|
var chr1, chr2, chr3; |
|
var i = 0; |
|
while(i < input.length){ |
|
chr1 = input.charCodeAt(i++); |
|
chr2 = input.charCodeAt(i++); |
|
chr3 = input.charCodeAt(i++); |
|
// encode 4 character group |
|
line += $4143f576ffbec226$var$_base64.charAt(chr1 >> 2); |
|
line += $4143f576ffbec226$var$_base64.charAt((chr1 & 3) << 4 | chr2 >> 4); |
|
if (isNaN(chr2)) line += '=='; |
|
else { |
|
line += $4143f576ffbec226$var$_base64.charAt((chr2 & 15) << 2 | chr3 >> 6); |
|
line += isNaN(chr3) ? '=' : $4143f576ffbec226$var$_base64.charAt(chr3 & 63); |
|
} |
|
if (maxline && line.length > maxline) { |
|
output += line.substr(0, maxline) + '\r\n'; |
|
line = line.substr(maxline); |
|
} |
|
} |
|
output += line; |
|
return output; |
|
}; |
|
/** |
|
* Base64 decodes a string into a 'binary' encoded string of bytes. |
|
* |
|
* @param input the base64-encoded input. |
|
* |
|
* @return the binary encoded string. |
|
*/ $4143f576ffbec226$var$util.decode64 = function(input) { |
|
// TODO: deprecate: "Deprecated. Use util.binary.base64.decode instead." |
|
// remove all non-base64 characters |
|
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); |
|
var output = ''; |
|
var enc1, enc2, enc3, enc4; |
|
var i = 0; |
|
while(i < input.length){ |
|
enc1 = $4143f576ffbec226$var$_base64Idx[input.charCodeAt(i++) - 43]; |
|
enc2 = $4143f576ffbec226$var$_base64Idx[input.charCodeAt(i++) - 43]; |
|
enc3 = $4143f576ffbec226$var$_base64Idx[input.charCodeAt(i++) - 43]; |
|
enc4 = $4143f576ffbec226$var$_base64Idx[input.charCodeAt(i++) - 43]; |
|
output += String.fromCharCode(enc1 << 2 | enc2 >> 4); |
|
if (enc3 !== 64) { |
|
// decoded at least 2 bytes |
|
output += String.fromCharCode((enc2 & 15) << 4 | enc3 >> 2); |
|
if (enc4 !== 64) // decoded 3 bytes |
|
output += String.fromCharCode((enc3 & 3) << 6 | enc4); |
|
} |
|
} |
|
return output; |
|
}; |
|
/** |
|
* Encodes the given string of characters (a standard JavaScript |
|
* string) as a binary encoded string where the bytes represent |
|
* a UTF-8 encoded string of characters. Non-ASCII characters will be |
|
* encoded as multiple bytes according to UTF-8. |
|
* |
|
* @param str a standard string of characters to encode. |
|
* |
|
* @return the binary encoded string. |
|
*/ $4143f576ffbec226$var$util.encodeUtf8 = function(str) { |
|
return unescape(encodeURIComponent(str)); |
|
}; |
|
/** |
|
* Decodes a binary encoded string that contains bytes that |
|
* represent a UTF-8 encoded string of characters -- into a |
|
* string of characters (a standard JavaScript string). |
|
* |
|
* @param str the binary encoded string to decode. |
|
* |
|
* @return the resulting standard string of characters. |
|
*/ $4143f576ffbec226$var$util.decodeUtf8 = function(str) { |
|
return decodeURIComponent(escape(str)); |
|
}; |
|
// binary encoding/decoding tools |
|
// FIXME: Experimental. Do not use yet. |
|
$4143f576ffbec226$var$util.binary = { |
|
raw: { |
|
}, |
|
hex: { |
|
}, |
|
base64: { |
|
}, |
|
base58: { |
|
}, |
|
baseN: { |
|
encode: $53abc20733f4b0dc$exports.encode, |
|
decode: $53abc20733f4b0dc$exports.decode |
|
} |
|
}; |
|
/** |
|
* Encodes a Uint8Array as a binary-encoded string. This encoding uses |
|
* a value between 0 and 255 for each character. |
|
* |
|
* @param bytes the Uint8Array to encode. |
|
* |
|
* @return the binary-encoded string. |
|
*/ $4143f576ffbec226$var$util.binary.raw.encode = function(bytes) { |
|
return String.fromCharCode.apply(null, bytes); |
|
}; |
|
/** |
|
* Decodes a binary-encoded string to a Uint8Array. This encoding uses |
|
* a value between 0 and 255 for each character. |
|
* |
|
* @param str the binary-encoded string to decode. |
|
* @param [output] an optional Uint8Array to write the output to; if it |
|
* is too small, an exception will be thrown. |
|
* @param [offset] the start offset for writing to the output (default: 0). |
|
* |
|
* @return the Uint8Array or the number of bytes written if output was given. |
|
*/ $4143f576ffbec226$var$util.binary.raw.decode = function(str, output, offset) { |
|
var out = output; |
|
if (!out) out = new Uint8Array(str.length); |
|
offset = offset || 0; |
|
var j = offset; |
|
for(var i = 0; i < str.length; ++i)out[j++] = str.charCodeAt(i); |
|
return output ? j - offset : out; |
|
}; |
|
/** |
|
* Encodes a 'binary' string, ArrayBuffer, DataView, TypedArray, or |
|
* ByteBuffer as a string of hexadecimal characters. |
|
* |
|
* @param bytes the bytes to convert. |
|
* |
|
* @return the string of hexadecimal characters. |
|
*/ $4143f576ffbec226$var$util.binary.hex.encode = $4143f576ffbec226$var$util.bytesToHex; |
|
/** |
|
* Decodes a hex-encoded string to a Uint8Array. |
|
* |
|
* @param hex the hexadecimal string to convert. |
|
* @param [output] an optional Uint8Array to write the output to; if it |
|
* is too small, an exception will be thrown. |
|
* @param [offset] the start offset for writing to the output (default: 0). |
|
* |
|
* @return the Uint8Array or the number of bytes written if output was given. |
|
*/ $4143f576ffbec226$var$util.binary.hex.decode = function(hex, output, offset) { |
|
var out = output; |
|
if (!out) out = new Uint8Array(Math.ceil(hex.length / 2)); |
|
offset = offset || 0; |
|
var i = 0, j = offset; |
|
if (hex.length & 1) { |
|
// odd number of characters, convert first character alone |
|
i = 1; |
|
out[j++] = parseInt(hex[0], 16); |
|
} |
|
// convert 2 characters (1 byte) at a time |
|
for(; i < hex.length; i += 2)out[j++] = parseInt(hex.substr(i, 2), 16); |
|
return output ? j - offset : out; |
|
}; |
|
/** |
|
* Base64-encodes a Uint8Array. |
|
* |
|
* @param input the Uint8Array to encode. |
|
* @param maxline the maximum number of encoded characters per line to use, |
|
* defaults to none. |
|
* |
|
* @return the base64-encoded output string. |
|
*/ $4143f576ffbec226$var$util.binary.base64.encode = function(input, maxline) { |
|
var line = ''; |
|
var output = ''; |
|
var chr1, chr2, chr3; |
|
var i = 0; |
|
while(i < input.byteLength){ |
|
chr1 = input[i++]; |
|
chr2 = input[i++]; |
|
chr3 = input[i++]; |
|
// encode 4 character group |
|
line += $4143f576ffbec226$var$_base64.charAt(chr1 >> 2); |
|
line += $4143f576ffbec226$var$_base64.charAt((chr1 & 3) << 4 | chr2 >> 4); |
|
if (isNaN(chr2)) line += '=='; |
|
else { |
|
line += $4143f576ffbec226$var$_base64.charAt((chr2 & 15) << 2 | chr3 >> 6); |
|
line += isNaN(chr3) ? '=' : $4143f576ffbec226$var$_base64.charAt(chr3 & 63); |
|
} |
|
if (maxline && line.length > maxline) { |
|
output += line.substr(0, maxline) + '\r\n'; |
|
line = line.substr(maxline); |
|
} |
|
} |
|
output += line; |
|
return output; |
|
}; |
|
/** |
|
* Decodes a base64-encoded string to a Uint8Array. |
|
* |
|
* @param input the base64-encoded input string. |
|
* @param [output] an optional Uint8Array to write the output to; if it |
|
* is too small, an exception will be thrown. |
|
* @param [offset] the start offset for writing to the output (default: 0). |
|
* |
|
* @return the Uint8Array or the number of bytes written if output was given. |
|
*/ $4143f576ffbec226$var$util.binary.base64.decode = function(input, output, offset) { |
|
var out = output; |
|
if (!out) out = new Uint8Array(Math.ceil(input.length / 4) * 3); |
|
// remove all non-base64 characters |
|
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); |
|
offset = offset || 0; |
|
var enc1, enc2, enc3, enc4; |
|
var i = 0, j = offset; |
|
while(i < input.length){ |
|
enc1 = $4143f576ffbec226$var$_base64Idx[input.charCodeAt(i++) - 43]; |
|
enc2 = $4143f576ffbec226$var$_base64Idx[input.charCodeAt(i++) - 43]; |
|
enc3 = $4143f576ffbec226$var$_base64Idx[input.charCodeAt(i++) - 43]; |
|
enc4 = $4143f576ffbec226$var$_base64Idx[input.charCodeAt(i++) - 43]; |
|
out[j++] = enc1 << 2 | enc2 >> 4; |
|
if (enc3 !== 64) { |
|
// decoded at least 2 bytes |
|
out[j++] = (enc2 & 15) << 4 | enc3 >> 2; |
|
if (enc4 !== 64) // decoded 3 bytes |
|
out[j++] = (enc3 & 3) << 6 | enc4; |
|
} |
|
} |
|
// make sure result is the exact decoded length |
|
return output ? j - offset : out.subarray(0, j); |
|
}; |
|
// add support for base58 encoding/decoding with Bitcoin alphabet |
|
$4143f576ffbec226$var$util.binary.base58.encode = function(input, maxline) { |
|
return $4143f576ffbec226$var$util.binary.baseN.encode(input, $4143f576ffbec226$var$_base58, maxline); |
|
}; |
|
$4143f576ffbec226$var$util.binary.base58.decode = function(input, maxline) { |
|
return $4143f576ffbec226$var$util.binary.baseN.decode(input, $4143f576ffbec226$var$_base58, maxline); |
|
}; |
|
// text encoding/decoding tools |
|
// FIXME: Experimental. Do not use yet. |
|
$4143f576ffbec226$var$util.text = { |
|
utf8: { |
|
}, |
|
utf16: { |
|
} |
|
}; |
|
/** |
|
* Encodes the given string as UTF-8 in a Uint8Array. |
|
* |
|
* @param str the string to encode. |
|
* @param [output] an optional Uint8Array to write the output to; if it |
|
* is too small, an exception will be thrown. |
|
* @param [offset] the start offset for writing to the output (default: 0). |
|
* |
|
* @return the Uint8Array or the number of bytes written if output was given. |
|
*/ $4143f576ffbec226$var$util.text.utf8.encode = function(str, output, offset) { |
|
str = $4143f576ffbec226$var$util.encodeUtf8(str); |
|
var out = output; |
|
if (!out) out = new Uint8Array(str.length); |
|
offset = offset || 0; |
|
var j = offset; |
|
for(var i = 0; i < str.length; ++i)out[j++] = str.charCodeAt(i); |
|
return output ? j - offset : out; |
|
}; |
|
/** |
|
* Decodes the UTF-8 contents from a Uint8Array. |
|
* |
|
* @param bytes the Uint8Array to decode. |
|
* |
|
* @return the resulting string. |
|
*/ $4143f576ffbec226$var$util.text.utf8.decode = function(bytes) { |
|
return $4143f576ffbec226$var$util.decodeUtf8(String.fromCharCode.apply(null, bytes)); |
|
}; |
|
/** |
|
* Encodes the given string as UTF-16 in a Uint8Array. |
|
* |
|
* @param str the string to encode. |
|
* @param [output] an optional Uint8Array to write the output to; if it |
|
* is too small, an exception will be thrown. |
|
* @param [offset] the start offset for writing to the output (default: 0). |
|
* |
|
* @return the Uint8Array or the number of bytes written if output was given. |
|
*/ $4143f576ffbec226$var$util.text.utf16.encode = function(str, output, offset) { |
|
var out = output; |
|
if (!out) out = new Uint8Array(str.length * 2); |
|
var view = new Uint16Array(out.buffer); |
|
offset = offset || 0; |
|
var j = offset; |
|
var k = offset; |
|
for(var i = 0; i < str.length; ++i){ |
|
view[k++] = str.charCodeAt(i); |
|
j += 2; |
|
} |
|
return output ? j - offset : out; |
|
}; |
|
/** |
|
* Decodes the UTF-16 contents from a Uint8Array. |
|
* |
|
* @param bytes the Uint8Array to decode. |
|
* |
|
* @return the resulting string. |
|
*/ $4143f576ffbec226$var$util.text.utf16.decode = function(bytes) { |
|
return String.fromCharCode.apply(null, new Uint16Array(bytes.buffer)); |
|
}; |
|
/** |
|
* Deflates the given data using a flash interface. |
|
* |
|
* @param api the flash interface. |
|
* @param bytes the data. |
|
* @param raw true to return only raw deflate data, false to include zlib |
|
* header and trailer. |
|
* |
|
* @return the deflated data as a string. |
|
*/ $4143f576ffbec226$var$util.deflate = function(api, bytes, raw) { |
|
bytes = $4143f576ffbec226$var$util.decode64(api.deflate($4143f576ffbec226$var$util.encode64(bytes)).rval); |
|
// strip zlib header and trailer if necessary |
|
if (raw) { |
|
// zlib header is 2 bytes (CMF,FLG) where FLG indicates that |
|
// there is a 4-byte DICT (alder-32) block before the data if |
|
// its 5th bit is set |
|
var start = 2; |
|
var flg = bytes.charCodeAt(1); |
|
if (flg & 32) start = 6; |
|
// zlib trailer is 4 bytes of adler-32 |
|
bytes = bytes.substring(start, bytes.length - 4); |
|
} |
|
return bytes; |
|
}; |
|
/** |
|
* Inflates the given data using a flash interface. |
|
* |
|
* @param api the flash interface. |
|
* @param bytes the data. |
|
* @param raw true if the incoming data has no zlib header or trailer and is |
|
* raw DEFLATE data. |
|
* |
|
* @return the inflated data as a string, null on error. |
|
*/ $4143f576ffbec226$var$util.inflate = function(api, bytes, raw) { |
|
// TODO: add zlib header and trailer if necessary/possible |
|
var rval = api.inflate($4143f576ffbec226$var$util.encode64(bytes)).rval; |
|
return rval === null ? null : $4143f576ffbec226$var$util.decode64(rval); |
|
}; |
|
/** |
|
* Sets a storage object. |
|
* |
|
* @param api the storage interface. |
|
* @param id the storage ID to use. |
|
* @param obj the storage object, null to remove. |
|
*/ var $4143f576ffbec226$var$_setStorageObject = function(api, id, obj) { |
|
if (!api) throw new Error('WebStorage not available.'); |
|
var rval; |
|
if (obj === null) rval = api.removeItem(id); |
|
else { |
|
// json-encode and base64-encode object |
|
obj = $4143f576ffbec226$var$util.encode64(JSON.stringify(obj)); |
|
rval = api.setItem(id, obj); |
|
} |
|
// handle potential flash error |
|
if (typeof rval !== 'undefined' && rval.rval !== true) { |
|
var error = new Error(rval.error.message); |
|
error.id = rval.error.id; |
|
error.name = rval.error.name; |
|
throw error; |
|
} |
|
}; |
|
/** |
|
* Gets a storage object. |
|
* |
|
* @param api the storage interface. |
|
* @param id the storage ID to use. |
|
* |
|
* @return the storage object entry or null if none exists. |
|
*/ var $4143f576ffbec226$var$_getStorageObject = function(api, id) { |
|
if (!api) throw new Error('WebStorage not available.'); |
|
// get the existing entry |
|
var rval = api.getItem(id); |
|
/* Note: We check api.init because we can't do (api == localStorage) |
|
on IE because of "Class doesn't support Automation" exception. Only |
|
the flash api has an init method so this works too, but we need a |
|
better solution in the future. */ // flash returns item wrapped in an object, handle special case |
|
if (api.init) { |
|
if (rval.rval === null) { |
|
if (rval.error) { |
|
var error = new Error(rval.error.message); |
|
error.id = rval.error.id; |
|
error.name = rval.error.name; |
|
throw error; |
|
} |
|
// no error, but also no item |
|
rval = null; |
|
} else rval = rval.rval; |
|
} |
|
// handle decoding |
|
if (rval !== null) // base64-decode and json-decode data |
|
rval = JSON.parse($4143f576ffbec226$var$util.decode64(rval)); |
|
return rval; |
|
}; |
|
/** |
|
* Stores an item in local storage. |
|
* |
|
* @param api the storage interface. |
|
* @param id the storage ID to use. |
|
* @param key the key for the item. |
|
* @param data the data for the item (any javascript object/primitive). |
|
*/ var $4143f576ffbec226$var$_setItem = function(api, id, key, data) { |
|
// get storage object |
|
var obj = $4143f576ffbec226$var$_getStorageObject(api, id); |
|
if (obj === null) // create a new storage object |
|
obj = { |
|
}; |
|
// update key |
|
obj[key] = data; |
|
// set storage object |
|
$4143f576ffbec226$var$_setStorageObject(api, id, obj); |
|
}; |
|
/** |
|
* Gets an item from local storage. |
|
* |
|
* @param api the storage interface. |
|
* @param id the storage ID to use. |
|
* @param key the key for the item. |
|
* |
|
* @return the item. |
|
*/ var $4143f576ffbec226$var$_getItem = function(api, id, key) { |
|
// get storage object |
|
var rval = $4143f576ffbec226$var$_getStorageObject(api, id); |
|
if (rval !== null) // return data at key |
|
rval = key in rval ? rval[key] : null; |
|
return rval; |
|
}; |
|
/** |
|
* Removes an item from local storage. |
|
* |
|
* @param api the storage interface. |
|
* @param id the storage ID to use. |
|
* @param key the key for the item. |
|
*/ var $4143f576ffbec226$var$_removeItem = function(api, id, key) { |
|
// get storage object |
|
var obj = $4143f576ffbec226$var$_getStorageObject(api, id); |
|
if (obj !== null && key in obj) { |
|
// remove key |
|
delete obj[key]; |
|
// see if entry has no keys remaining |
|
var empty = true; |
|
for(var prop in obj){ |
|
empty = false; |
|
break; |
|
} |
|
if (empty) // remove entry entirely if no keys are left |
|
obj = null; |
|
// set storage object |
|
$4143f576ffbec226$var$_setStorageObject(api, id, obj); |
|
} |
|
}; |
|
/** |
|
* Clears the local disk storage identified by the given ID. |
|
* |
|
* @param api the storage interface. |
|
* @param id the storage ID to use. |
|
*/ var $4143f576ffbec226$var$_clearItems = function(api, id) { |
|
$4143f576ffbec226$var$_setStorageObject(api, id, null); |
|
}; |
|
/** |
|
* Calls a storage function. |
|
* |
|
* @param func the function to call. |
|
* @param args the arguments for the function. |
|
* @param location the location argument. |
|
* |
|
* @return the return value from the function. |
|
*/ var $4143f576ffbec226$var$_callStorageFunction = function(func, args, location) { |
|
var rval = null; |
|
// default storage types |
|
if (typeof location === 'undefined') location = [ |
|
'web', |
|
'flash' |
|
]; |
|
// apply storage types in order of preference |
|
var type; |
|
var done = false; |
|
var exception = null; |
|
for(var idx in location){ |
|
type = location[idx]; |
|
try { |
|
if (type === 'flash' || type === 'both') { |
|
if (args[0] === null) throw new Error('Flash local storage not available.'); |
|
rval = func.apply(this, args); |
|
done = type === 'flash'; |
|
} |
|
if (type === 'web' || type === 'both') { |
|
args[0] = localStorage; |
|
rval = func.apply(this, args); |
|
done = true; |
|
} |
|
} catch (ex) { |
|
exception = ex; |
|
} |
|
if (done) break; |
|
} |
|
if (!done) throw exception; |
|
return rval; |
|
}; |
|
/** |
|
* Stores an item on local disk. |
|
* |
|
* The available types of local storage include 'flash', 'web', and 'both'. |
|
* |
|
* The type 'flash' refers to flash local storage (SharedObject). In order |
|
* to use flash local storage, the 'api' parameter must be valid. The type |
|
* 'web' refers to WebStorage, if supported by the browser. The type 'both' |
|
* refers to storing using both 'flash' and 'web', not just one or the |
|
* other. |
|
* |
|
* The location array should list the storage types to use in order of |
|
* preference: |
|
* |
|
* ['flash']: flash only storage |
|
* ['web']: web only storage |
|
* ['both']: try to store in both |
|
* ['flash','web']: store in flash first, but if not available, 'web' |
|
* ['web','flash']: store in web first, but if not available, 'flash' |
|
* |
|
* The location array defaults to: ['web', 'flash'] |
|
* |
|
* @param api the flash interface, null to use only WebStorage. |
|
* @param id the storage ID to use. |
|
* @param key the key for the item. |
|
* @param data the data for the item (any javascript object/primitive). |
|
* @param location an array with the preferred types of storage to use. |
|
*/ $4143f576ffbec226$var$util.setItem = function(api, id, key, data, location) { |
|
$4143f576ffbec226$var$_callStorageFunction($4143f576ffbec226$var$_setItem, arguments, location); |
|
}; |
|
/** |
|
* Gets an item on local disk. |
|
* |
|
* Set setItem() for details on storage types. |
|
* |
|
* @param api the flash interface, null to use only WebStorage. |
|
* @param id the storage ID to use. |
|
* @param key the key for the item. |
|
* @param location an array with the preferred types of storage to use. |
|
* |
|
* @return the item. |
|
*/ $4143f576ffbec226$var$util.getItem = function(api, id, key, location) { |
|
return $4143f576ffbec226$var$_callStorageFunction($4143f576ffbec226$var$_getItem, arguments, location); |
|
}; |
|
/** |
|
* Removes an item on local disk. |
|
* |
|
* Set setItem() for details on storage types. |
|
* |
|
* @param api the flash interface. |
|
* @param id the storage ID to use. |
|
* @param key the key for the item. |
|
* @param location an array with the preferred types of storage to use. |
|
*/ $4143f576ffbec226$var$util.removeItem = function(api, id, key, location) { |
|
$4143f576ffbec226$var$_callStorageFunction($4143f576ffbec226$var$_removeItem, arguments, location); |
|
}; |
|
/** |
|
* Clears the local disk storage identified by the given ID. |
|
* |
|
* Set setItem() for details on storage types. |
|
* |
|
* @param api the flash interface if flash is available. |
|
* @param id the storage ID to use. |
|
* @param location an array with the preferred types of storage to use. |
|
*/ $4143f576ffbec226$var$util.clearItems = function(api, id, location) { |
|
$4143f576ffbec226$var$_callStorageFunction($4143f576ffbec226$var$_clearItems, arguments, location); |
|
}; |
|
/** |
|
* Check if an object is empty. |
|
* |
|
* Taken from: |
|
* http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object-from-json/679937#679937 |
|
* |
|
* @param object the object to check. |
|
*/ $4143f576ffbec226$var$util.isEmpty = function(obj) { |
|
for(var prop in obj){ |
|
if (obj.hasOwnProperty(prop)) return false; |
|
} |
|
return true; |
|
}; |
|
/** |
|
* Format with simple printf-style interpolation. |
|
* |
|
* %%: literal '%' |
|
* %s,%o: convert next argument into a string. |
|
* |
|
* @param format the string to format. |
|
* @param ... arguments to interpolate into the format string. |
|
*/ $4143f576ffbec226$var$util.format = function(format) { |
|
var re = /%./g; |
|
// current match |
|
var match; |
|
// current part |
|
var part; |
|
// current arg index |
|
var argi = 0; |
|
// collected parts to recombine later |
|
var parts = []; |
|
// last index found |
|
var last = 0; |
|
// loop while matches remain |
|
while(match = re.exec(format)){ |
|
part = format.substring(last, re.lastIndex - 2); |
|
// don't add empty strings (ie, parts between %s%s) |
|
if (part.length > 0) parts.push(part); |
|
last = re.lastIndex; |
|
// switch on % code |
|
var code = match[0][1]; |
|
switch(code){ |
|
case 's': |
|
case 'o': |
|
// check if enough arguments were given |
|
if (argi < arguments.length) parts.push(arguments[(argi++) + 1]); |
|
else parts.push('<?>'); |
|
break; |
|
// FIXME: do proper formating for numbers, etc |
|
//case 'f': |
|
//case 'd': |
|
case '%': |
|
parts.push('%'); |
|
break; |
|
default: |
|
parts.push('<%' + code + '?>'); |
|
} |
|
} |
|
// add trailing part of format string |
|
parts.push(format.substring(last)); |
|
return parts.join(''); |
|
}; |
|
/** |
|
* Formats a number. |
|
* |
|
* http://snipplr.com/view/5945/javascript-numberformat--ported-from-php/ |
|
*/ $4143f576ffbec226$var$util.formatNumber = function(number, decimals, dec_point, thousands_sep) { |
|
// http://kevin.vanzonneveld.net |
|
// + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) |
|
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) |
|
// + bugfix by: Michael White (http://crestidg.com) |
|
// + bugfix by: Benjamin Lupton |
|
// + bugfix by: Allan Jensen (http://www.winternet.no) |
|
// + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) |
|
// * example 1: number_format(1234.5678, 2, '.', ''); |
|
// * returns 1: 1234.57 |
|
var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals; |
|
var d = dec_point === undefined ? ',' : dec_point; |
|
var t = thousands_sep === undefined ? '.' : thousands_sep, s = n < 0 ? '-' : ''; |
|
var i = parseInt(n = Math.abs(+n || 0).toFixed(c), 10) + ''; |
|
var j = i.length > 3 ? i.length % 3 : 0; |
|
return s + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ''); |
|
}; |
|
/** |
|
* Formats a byte size. |
|
* |
|
* http://snipplr.com/view/5949/format-humanize-file-byte-size-presentation-in-javascript/ |
|
*/ $4143f576ffbec226$var$util.formatSize = function(size) { |
|
if (size >= 1073741824) size = $4143f576ffbec226$var$util.formatNumber(size / 1073741824, 2, '.', '') + ' GiB'; |
|
else if (size >= 1048576) size = $4143f576ffbec226$var$util.formatNumber(size / 1048576, 2, '.', '') + ' MiB'; |
|
else if (size >= 1024) size = $4143f576ffbec226$var$util.formatNumber(size / 1024, 0) + ' KiB'; |
|
else size = $4143f576ffbec226$var$util.formatNumber(size, 0) + ' bytes'; |
|
return size; |
|
}; |
|
/** |
|
* Converts an IPv4 or IPv6 string representation into bytes (in network order). |
|
* |
|
* @param ip the IPv4 or IPv6 address to convert. |
|
* |
|
* @return the 4-byte IPv6 or 16-byte IPv6 address or null if the address can't |
|
* be parsed. |
|
*/ $4143f576ffbec226$var$util.bytesFromIP = function(ip) { |
|
if (ip.indexOf('.') !== -1) return $4143f576ffbec226$var$util.bytesFromIPv4(ip); |
|
if (ip.indexOf(':') !== -1) return $4143f576ffbec226$var$util.bytesFromIPv6(ip); |
|
return null; |
|
}; |
|
/** |
|
* Converts an IPv4 string representation into bytes (in network order). |
|
* |
|
* @param ip the IPv4 address to convert. |
|
* |
|
* @return the 4-byte address or null if the address can't be parsed. |
|
*/ $4143f576ffbec226$var$util.bytesFromIPv4 = function(ip) { |
|
ip = ip.split('.'); |
|
if (ip.length !== 4) return null; |
|
var b = $4143f576ffbec226$var$util.createBuffer(); |
|
for(var i = 0; i < ip.length; ++i){ |
|
var num = parseInt(ip[i], 10); |
|
if (isNaN(num)) return null; |
|
b.putByte(num); |
|
} |
|
return b.getBytes(); |
|
}; |
|
/** |
|
* Converts an IPv6 string representation into bytes (in network order). |
|
* |
|
* @param ip the IPv6 address to convert. |
|
* |
|
* @return the 16-byte address or null if the address can't be parsed. |
|
*/ $4143f576ffbec226$var$util.bytesFromIPv6 = function(ip) { |
|
var blanks = 0; |
|
ip = ip.split(':').filter(function(e) { |
|
if (e.length === 0) ++blanks; |
|
return true; |
|
}); |
|
var zeros = (8 - ip.length + blanks) * 2; |
|
var b = $4143f576ffbec226$var$util.createBuffer(); |
|
for(var i = 0; i < 8; ++i){ |
|
if (!ip[i] || ip[i].length === 0) { |
|
b.fillWithByte(0, zeros); |
|
zeros = 0; |
|
continue; |
|
} |
|
var bytes = $4143f576ffbec226$var$util.hexToBytes(ip[i]); |
|
if (bytes.length < 2) b.putByte(0); |
|
b.putBytes(bytes); |
|
} |
|
return b.getBytes(); |
|
}; |
|
/** |
|
* Converts 4-bytes into an IPv4 string representation or 16-bytes into |
|
* an IPv6 string representation. The bytes must be in network order. |
|
* |
|
* @param bytes the bytes to convert. |
|
* |
|
* @return the IPv4 or IPv6 string representation if 4 or 16 bytes, |
|
* respectively, are given, otherwise null. |
|
*/ $4143f576ffbec226$var$util.bytesToIP = function(bytes) { |
|
if (bytes.length === 4) return $4143f576ffbec226$var$util.bytesToIPv4(bytes); |
|
if (bytes.length === 16) return $4143f576ffbec226$var$util.bytesToIPv6(bytes); |
|
return null; |
|
}; |
|
/** |
|
* Converts 4-bytes into an IPv4 string representation. The bytes must be |
|
* in network order. |
|
* |
|
* @param bytes the bytes to convert. |
|
* |
|
* @return the IPv4 string representation or null for an invalid # of bytes. |
|
*/ $4143f576ffbec226$var$util.bytesToIPv4 = function(bytes) { |
|
if (bytes.length !== 4) return null; |
|
var ip = []; |
|
for(var i = 0; i < bytes.length; ++i)ip.push(bytes.charCodeAt(i)); |
|
return ip.join('.'); |
|
}; |
|
/** |
|
* Converts 16-bytes into an IPv16 string representation. The bytes must be |
|
* in network order. |
|
* |
|
* @param bytes the bytes to convert. |
|
* |
|
* @return the IPv16 string representation or null for an invalid # of bytes. |
|
*/ $4143f576ffbec226$var$util.bytesToIPv6 = function(bytes) { |
|
if (bytes.length !== 16) return null; |
|
var ip = []; |
|
var zeroGroups = []; |
|
var zeroMaxGroup = 0; |
|
for(var i = 0; i < bytes.length; i += 2){ |
|
var hex = $4143f576ffbec226$var$util.bytesToHex(bytes[i] + bytes[i + 1]); |
|
// canonicalize zero representation |
|
while(hex[0] === '0' && hex !== '0')hex = hex.substr(1); |
|
if (hex === '0') { |
|
var last = zeroGroups[zeroGroups.length - 1]; |
|
var idx = ip.length; |
|
if (!last || idx !== last.end + 1) zeroGroups.push({ |
|
start: idx, |
|
end: idx |
|
}); |
|
else { |
|
last.end = idx; |
|
if (last.end - last.start > zeroGroups[zeroMaxGroup].end - zeroGroups[zeroMaxGroup].start) zeroMaxGroup = zeroGroups.length - 1; |
|
} |
|
} |
|
ip.push(hex); |
|
} |
|
if (zeroGroups.length > 0) { |
|
var group = zeroGroups[zeroMaxGroup]; |
|
// only shorten group of length > 0 |
|
if (group.end - group.start > 0) { |
|
ip.splice(group.start, group.end - group.start + 1, ''); |
|
if (group.start === 0) ip.unshift(''); |
|
if (group.end === 7) ip.push(''); |
|
} |
|
} |
|
return ip.join(':'); |
|
}; |
|
/** |
|
* Estimates the number of processes that can be run concurrently. If |
|
* creating Web Workers, keep in mind that the main JavaScript process needs |
|
* its own core. |
|
* |
|
* @param options the options to use: |
|
* update true to force an update (not use the cached value). |
|
* @param callback(err, max) called once the operation completes. |
|
*/ $4143f576ffbec226$var$util.estimateCores = function(options, callback1) { |
|
if (typeof options === 'function') { |
|
callback1 = options; |
|
options = { |
|
}; |
|
} |
|
options = options || { |
|
}; |
|
if ('cores' in $4143f576ffbec226$var$util && !options.update) return callback1(null, $4143f576ffbec226$var$util.cores); |
|
if (typeof navigator !== 'undefined' && 'hardwareConcurrency' in navigator && navigator.hardwareConcurrency > 0) { |
|
$4143f576ffbec226$var$util.cores = navigator.hardwareConcurrency; |
|
return callback1(null, $4143f576ffbec226$var$util.cores); |
|
} |
|
if (typeof Worker === 'undefined') { |
|
// workers not available |
|
$4143f576ffbec226$var$util.cores = 1; |
|
return callback1(null, $4143f576ffbec226$var$util.cores); |
|
} |
|
if (typeof Blob === 'undefined') { |
|
// can't estimate, default to 2 |
|
$4143f576ffbec226$var$util.cores = 2; |
|
return callback1(null, $4143f576ffbec226$var$util.cores); |
|
} |
|
// create worker concurrency estimation code as blob |
|
var blobUrl = URL.createObjectURL(new Blob([ |
|
'(', |
|
(function() { |
|
self.addEventListener('message', function(e) { |
|
// run worker for 4 ms |
|
var st = Date.now(); |
|
var et = st + 4; |
|
while(Date.now() < et); |
|
self.postMessage({ |
|
st: st, |
|
et: et |
|
}); |
|
}); |
|
}).toString(), |
|
')()' |
|
], { |
|
type: 'application/javascript' |
|
})); |
|
// take 5 samples using 16 workers |
|
sample([], 5, 16); |
|
function sample(max, samples, numWorkers) { |
|
if (samples === 0) { |
|
// get overlap average |
|
var avg1 = Math.floor(max.reduce(function(avg, x) { |
|
return avg + x; |
|
}, 0) / max.length); |
|
$4143f576ffbec226$var$util.cores = Math.max(1, avg1); |
|
URL.revokeObjectURL(blobUrl); |
|
return callback1(null, $4143f576ffbec226$var$util.cores); |
|
} |
|
map(numWorkers, function(err, results) { |
|
max.push(reduce(numWorkers, results)); |
|
sample(max, samples - 1, numWorkers); |
|
}); |
|
} |
|
function map(numWorkers, callback) { |
|
var workers = []; |
|
var results = []; |
|
for(var i1 = 0; i1 < numWorkers; ++i1){ |
|
var worker = new Worker(blobUrl); |
|
worker.addEventListener('message', function(e) { |
|
results.push(e.data); |
|
if (results.length === numWorkers) { |
|
for(var i = 0; i < numWorkers; ++i)workers[i].terminate(); |
|
callback(null, results); |
|
} |
|
}); |
|
workers.push(worker); |
|
} |
|
for(var i1 = 0; i1 < numWorkers; ++i1)workers[i1].postMessage(i1); |
|
} |
|
function reduce(numWorkers, results) { |
|
// find overlapping time windows |
|
var overlaps = []; |
|
for(var n = 0; n < numWorkers; ++n){ |
|
var r1 = results[n]; |
|
var overlap = overlaps[n] = []; |
|
for(var i = 0; i < numWorkers; ++i){ |
|
if (n === i) continue; |
|
var r2 = results[i]; |
|
if (r1.st > r2.st && r1.st < r2.et || r2.st > r1.st && r2.st < r1.et) overlap.push(i); |
|
} |
|
} |
|
// get maximum overlaps ... don't include overlapping worker itself |
|
// as the main JS process was also being scheduled during the work and |
|
// would have to be subtracted from the estimate anyway |
|
return overlaps.reduce(function(max, overlap) { |
|
return Math.max(max, overlap.length); |
|
}, 0); |
|
} |
|
}; |
|
|
|
|
|
$871289bd32ea5f15$exports = $iGlOy.cipher = $iGlOy.cipher || { |
|
}; |
|
// registered algorithms |
|
$iGlOy.cipher.algorithms = $iGlOy.cipher.algorithms || { |
|
}; |
|
/** |
|
* Creates a cipher object that can be used to encrypt data using the given |
|
* algorithm and key. The algorithm may be provided as a string value for a |
|
* previously registered algorithm or it may be given as a cipher algorithm |
|
* API object. |
|
* |
|
* @param algorithm the algorithm to use, either a string or an algorithm API |
|
* object. |
|
* @param key the key to use, as a binary-encoded string of bytes or a |
|
* byte buffer. |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.cipher.createCipher = function(algorithm, key) { |
|
var api = algorithm; |
|
if (typeof api === 'string') { |
|
api = $iGlOy.cipher.getAlgorithm(api); |
|
if (api) api = api(); |
|
} |
|
if (!api) throw new Error('Unsupported algorithm: ' + algorithm); |
|
// assume block cipher |
|
return new $iGlOy.cipher.BlockCipher({ |
|
algorithm: api, |
|
key: key, |
|
decrypt: false |
|
}); |
|
}; |
|
/** |
|
* Creates a decipher object that can be used to decrypt data using the given |
|
* algorithm and key. The algorithm may be provided as a string value for a |
|
* previously registered algorithm or it may be given as a cipher algorithm |
|
* API object. |
|
* |
|
* @param algorithm the algorithm to use, either a string or an algorithm API |
|
* object. |
|
* @param key the key to use, as a binary-encoded string of bytes or a |
|
* byte buffer. |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.cipher.createDecipher = function(algorithm, key) { |
|
var api = algorithm; |
|
if (typeof api === 'string') { |
|
api = $iGlOy.cipher.getAlgorithm(api); |
|
if (api) api = api(); |
|
} |
|
if (!api) throw new Error('Unsupported algorithm: ' + algorithm); |
|
// assume block cipher |
|
return new $iGlOy.cipher.BlockCipher({ |
|
algorithm: api, |
|
key: key, |
|
decrypt: true |
|
}); |
|
}; |
|
/** |
|
* Registers an algorithm by name. If the name was already registered, the |
|
* algorithm API object will be overwritten. |
|
* |
|
* @param name the name of the algorithm. |
|
* @param algorithm the algorithm API object. |
|
*/ $iGlOy.cipher.registerAlgorithm = function(name, algorithm) { |
|
name = name.toUpperCase(); |
|
$iGlOy.cipher.algorithms[name] = algorithm; |
|
}; |
|
/** |
|
* Gets a registered algorithm by name. |
|
* |
|
* @param name the name of the algorithm. |
|
* |
|
* @return the algorithm, if found, null if not. |
|
*/ $iGlOy.cipher.getAlgorithm = function(name) { |
|
name = name.toUpperCase(); |
|
if (name in $iGlOy.cipher.algorithms) return $iGlOy.cipher.algorithms[name]; |
|
return null; |
|
}; |
|
var $871289bd32ea5f15$var$BlockCipher = $iGlOy.cipher.BlockCipher = function(options) { |
|
this.algorithm = options.algorithm; |
|
this.mode = this.algorithm.mode; |
|
this.blockSize = this.mode.blockSize; |
|
this._finish = false; |
|
this._input = null; |
|
this.output = null; |
|
this._op = options.decrypt ? this.mode.decrypt : this.mode.encrypt; |
|
this._decrypt = options.decrypt; |
|
this.algorithm.initialize(options); |
|
}; |
|
/** |
|
* Starts or restarts the encryption or decryption process, whichever |
|
* was previously configured. |
|
* |
|
* For non-GCM mode, the IV may be a binary-encoded string of bytes, an array |
|
* of bytes, a byte buffer, or an array of 32-bit integers. If the IV is in |
|
* bytes, then it must be Nb (16) bytes in length. If the IV is given in as |
|
* 32-bit integers, then it must be 4 integers long. |
|
* |
|
* Note: an IV is not required or used in ECB mode. |
|
* |
|
* For GCM-mode, the IV must be given as a binary-encoded string of bytes or |
|
* a byte buffer. The number of bytes should be 12 (96 bits) as recommended |
|
* by NIST SP-800-38D but another length may be given. |
|
* |
|
* @param options the options to use: |
|
* iv the initialization vector to use as a binary-encoded string of |
|
* bytes, null to reuse the last ciphered block from a previous |
|
* update() (this "residue" method is for legacy support only). |
|
* additionalData additional authentication data as a binary-encoded |
|
* string of bytes, for 'GCM' mode, (default: none). |
|
* tagLength desired length of authentication tag, in bits, for |
|
* 'GCM' mode (0-128, default: 128). |
|
* tag the authentication tag to check if decrypting, as a |
|
* binary-encoded string of bytes. |
|
* output the output the buffer to write to, null to create one. |
|
*/ $871289bd32ea5f15$var$BlockCipher.prototype.start = function(options) { |
|
options = options || { |
|
}; |
|
var opts = { |
|
}; |
|
for(var key in options)opts[key] = options[key]; |
|
opts.decrypt = this._decrypt; |
|
this._finish = false; |
|
this._input = $iGlOy.util.createBuffer(); |
|
this.output = options.output || $iGlOy.util.createBuffer(); |
|
this.mode.start(opts); |
|
}; |
|
/** |
|
* Updates the next block according to the cipher mode. |
|
* |
|
* @param input the buffer to read from. |
|
*/ $871289bd32ea5f15$var$BlockCipher.prototype.update = function(input) { |
|
if (input) // input given, so empty it into the input buffer |
|
this._input.putBuffer(input); |
|
// do cipher operation until it needs more input and not finished |
|
while(!this._op.call(this.mode, this._input, this.output, this._finish) && !this._finish); |
|
// free consumed memory from input buffer |
|
this._input.compact(); |
|
}; |
|
/** |
|
* Finishes encrypting or decrypting. |
|
* |
|
* @param pad a padding function to use in CBC mode, null for default, |
|
* signature(blockSize, buffer, decrypt). |
|
* |
|
* @return true if successful, false on error. |
|
*/ $871289bd32ea5f15$var$BlockCipher.prototype.finish = function(pad) { |
|
// backwards-compatibility w/deprecated padding API |
|
// Note: will overwrite padding functions even after another start() call |
|
if (pad && (this.mode.name === 'ECB' || this.mode.name === 'CBC')) { |
|
this.mode.pad = function(input) { |
|
return pad(this.blockSize, input, false); |
|
}; |
|
this.mode.unpad = function(output) { |
|
return pad(this.blockSize, output, true); |
|
}; |
|
} |
|
// build options for padding and afterFinish functions |
|
var options = { |
|
}; |
|
options.decrypt = this._decrypt; |
|
// get # of bytes that won't fill a block |
|
options.overflow = this._input.length() % this.blockSize; |
|
if (!this._decrypt && this.mode.pad) { |
|
if (!this.mode.pad(this._input, options)) return false; |
|
} |
|
// do final update |
|
this._finish = true; |
|
this.update(); |
|
if (this._decrypt && this.mode.unpad) { |
|
if (!this.mode.unpad(this.output, options)) return false; |
|
} |
|
if (this.mode.afterFinish) { |
|
if (!this.mode.afterFinish(this.output, options)) return false; |
|
} |
|
return true; |
|
}; |
|
|
|
|
|
var $8e7d87db09a5396f$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
$iGlOy.cipher = $iGlOy.cipher || { |
|
}; |
|
// supported cipher modes |
|
var $8e7d87db09a5396f$var$modes = $8e7d87db09a5396f$exports = $iGlOy.cipher.modes = $iGlOy.cipher.modes || { |
|
}; |
|
/** Electronic codebook (ECB) (Don't use this; it's not secure) **/ $8e7d87db09a5396f$var$modes.ecb = function(options) { |
|
options = options || { |
|
}; |
|
this.name = 'ECB'; |
|
this.cipher = options.cipher; |
|
this.blockSize = options.blockSize || 16; |
|
this._ints = this.blockSize / 4; |
|
this._inBlock = new Array(this._ints); |
|
this._outBlock = new Array(this._ints); |
|
}; |
|
$8e7d87db09a5396f$var$modes.ecb.prototype.start = function(options) { |
|
}; |
|
$8e7d87db09a5396f$var$modes.ecb.prototype.encrypt = function(input, output, finish) { |
|
// not enough input to encrypt |
|
if (input.length() < this.blockSize && !(finish && input.length() > 0)) return true; |
|
// get next block |
|
for(var i = 0; i < this._ints; ++i)this._inBlock[i] = input.getInt32(); |
|
// encrypt block |
|
this.cipher.encrypt(this._inBlock, this._outBlock); |
|
// write output |
|
for(var i = 0; i < this._ints; ++i)output.putInt32(this._outBlock[i]); |
|
}; |
|
$8e7d87db09a5396f$var$modes.ecb.prototype.decrypt = function(input, output, finish) { |
|
// not enough input to decrypt |
|
if (input.length() < this.blockSize && !(finish && input.length() > 0)) return true; |
|
// get next block |
|
for(var i = 0; i < this._ints; ++i)this._inBlock[i] = input.getInt32(); |
|
// decrypt block |
|
this.cipher.decrypt(this._inBlock, this._outBlock); |
|
// write output |
|
for(var i = 0; i < this._ints; ++i)output.putInt32(this._outBlock[i]); |
|
}; |
|
$8e7d87db09a5396f$var$modes.ecb.prototype.pad = function(input, options) { |
|
// add PKCS#7 padding to block (each pad byte is the |
|
// value of the number of pad bytes) |
|
var padding = input.length() === this.blockSize ? this.blockSize : this.blockSize - input.length(); |
|
input.fillWithByte(padding, padding); |
|
return true; |
|
}; |
|
$8e7d87db09a5396f$var$modes.ecb.prototype.unpad = function(output, options) { |
|
// check for error: input data not a multiple of blockSize |
|
if (options.overflow > 0) return false; |
|
// ensure padding byte count is valid |
|
var len = output.length(); |
|
var count = output.at(len - 1); |
|
if (count > this.blockSize << 2) return false; |
|
// trim off padding bytes |
|
output.truncate(count); |
|
return true; |
|
}; |
|
/** Cipher-block Chaining (CBC) **/ $8e7d87db09a5396f$var$modes.cbc = function(options) { |
|
options = options || { |
|
}; |
|
this.name = 'CBC'; |
|
this.cipher = options.cipher; |
|
this.blockSize = options.blockSize || 16; |
|
this._ints = this.blockSize / 4; |
|
this._inBlock = new Array(this._ints); |
|
this._outBlock = new Array(this._ints); |
|
}; |
|
$8e7d87db09a5396f$var$modes.cbc.prototype.start = function(options) { |
|
// Note: legacy support for using IV residue (has security flaws) |
|
// if IV is null, reuse block from previous processing |
|
if (options.iv === null) { |
|
// must have a previous block |
|
if (!this._prev) throw new Error('Invalid IV parameter.'); |
|
this._iv = this._prev.slice(0); |
|
} else if (!('iv' in options)) throw new Error('Invalid IV parameter.'); |
|
else { |
|
// save IV as "previous" block |
|
this._iv = $8e7d87db09a5396f$var$transformIV(options.iv, this.blockSize); |
|
this._prev = this._iv.slice(0); |
|
} |
|
}; |
|
$8e7d87db09a5396f$var$modes.cbc.prototype.encrypt = function(input, output, finish) { |
|
// not enough input to encrypt |
|
if (input.length() < this.blockSize && !(finish && input.length() > 0)) return true; |
|
// get next block |
|
// CBC XOR's IV (or previous block) with plaintext |
|
for(var i = 0; i < this._ints; ++i)this._inBlock[i] = this._prev[i] ^ input.getInt32(); |
|
// encrypt block |
|
this.cipher.encrypt(this._inBlock, this._outBlock); |
|
// write output, save previous block |
|
for(var i = 0; i < this._ints; ++i)output.putInt32(this._outBlock[i]); |
|
this._prev = this._outBlock; |
|
}; |
|
$8e7d87db09a5396f$var$modes.cbc.prototype.decrypt = function(input, output, finish) { |
|
// not enough input to decrypt |
|
if (input.length() < this.blockSize && !(finish && input.length() > 0)) return true; |
|
// get next block |
|
for(var i = 0; i < this._ints; ++i)this._inBlock[i] = input.getInt32(); |
|
// decrypt block |
|
this.cipher.decrypt(this._inBlock, this._outBlock); |
|
// write output, save previous ciphered block |
|
// CBC XOR's IV (or previous block) with ciphertext |
|
for(var i = 0; i < this._ints; ++i)output.putInt32(this._prev[i] ^ this._outBlock[i]); |
|
this._prev = this._inBlock.slice(0); |
|
}; |
|
$8e7d87db09a5396f$var$modes.cbc.prototype.pad = function(input, options) { |
|
// add PKCS#7 padding to block (each pad byte is the |
|
// value of the number of pad bytes) |
|
var padding = input.length() === this.blockSize ? this.blockSize : this.blockSize - input.length(); |
|
input.fillWithByte(padding, padding); |
|
return true; |
|
}; |
|
$8e7d87db09a5396f$var$modes.cbc.prototype.unpad = function(output, options) { |
|
// check for error: input data not a multiple of blockSize |
|
if (options.overflow > 0) return false; |
|
// ensure padding byte count is valid |
|
var len = output.length(); |
|
var count = output.at(len - 1); |
|
if (count > this.blockSize << 2) return false; |
|
// trim off padding bytes |
|
output.truncate(count); |
|
return true; |
|
}; |
|
/** Cipher feedback (CFB) **/ $8e7d87db09a5396f$var$modes.cfb = function(options) { |
|
options = options || { |
|
}; |
|
this.name = 'CFB'; |
|
this.cipher = options.cipher; |
|
this.blockSize = options.blockSize || 16; |
|
this._ints = this.blockSize / 4; |
|
this._inBlock = null; |
|
this._outBlock = new Array(this._ints); |
|
this._partialBlock = new Array(this._ints); |
|
this._partialOutput = $iGlOy.util.createBuffer(); |
|
this._partialBytes = 0; |
|
}; |
|
$8e7d87db09a5396f$var$modes.cfb.prototype.start = function(options) { |
|
if (!('iv' in options)) throw new Error('Invalid IV parameter.'); |
|
// use IV as first input |
|
this._iv = $8e7d87db09a5396f$var$transformIV(options.iv, this.blockSize); |
|
this._inBlock = this._iv.slice(0); |
|
this._partialBytes = 0; |
|
}; |
|
$8e7d87db09a5396f$var$modes.cfb.prototype.encrypt = function(input, output, finish) { |
|
// not enough input to encrypt |
|
var inputLength = input.length(); |
|
if (inputLength === 0) return true; |
|
// encrypt block |
|
this.cipher.encrypt(this._inBlock, this._outBlock); |
|
// handle full block |
|
if (this._partialBytes === 0 && inputLength >= this.blockSize) { |
|
// XOR input with output, write input as output |
|
for(var i = 0; i < this._ints; ++i){ |
|
this._inBlock[i] = input.getInt32() ^ this._outBlock[i]; |
|
output.putInt32(this._inBlock[i]); |
|
} |
|
return; |
|
} |
|
// handle partial block |
|
var partialBytes = (this.blockSize - inputLength) % this.blockSize; |
|
if (partialBytes > 0) partialBytes = this.blockSize - partialBytes; |
|
// XOR input with output, write input as partial output |
|
this._partialOutput.clear(); |
|
for(var i = 0; i < this._ints; ++i){ |
|
this._partialBlock[i] = input.getInt32() ^ this._outBlock[i]; |
|
this._partialOutput.putInt32(this._partialBlock[i]); |
|
} |
|
if (partialBytes > 0) // block still incomplete, restore input buffer |
|
input.read -= this.blockSize; |
|
else // block complete, update input block |
|
for(var i = 0; i < this._ints; ++i)this._inBlock[i] = this._partialBlock[i]; |
|
// skip any previous partial bytes |
|
if (this._partialBytes > 0) this._partialOutput.getBytes(this._partialBytes); |
|
if (partialBytes > 0 && !finish) { |
|
output.putBytes(this._partialOutput.getBytes(partialBytes - this._partialBytes)); |
|
this._partialBytes = partialBytes; |
|
return true; |
|
} |
|
output.putBytes(this._partialOutput.getBytes(inputLength - this._partialBytes)); |
|
this._partialBytes = 0; |
|
}; |
|
$8e7d87db09a5396f$var$modes.cfb.prototype.decrypt = function(input, output, finish) { |
|
// not enough input to decrypt |
|
var inputLength = input.length(); |
|
if (inputLength === 0) return true; |
|
// encrypt block (CFB always uses encryption mode) |
|
this.cipher.encrypt(this._inBlock, this._outBlock); |
|
// handle full block |
|
if (this._partialBytes === 0 && inputLength >= this.blockSize) { |
|
// XOR input with output, write input as output |
|
for(var i = 0; i < this._ints; ++i){ |
|
this._inBlock[i] = input.getInt32(); |
|
output.putInt32(this._inBlock[i] ^ this._outBlock[i]); |
|
} |
|
return; |
|
} |
|
// handle partial block |
|
var partialBytes = (this.blockSize - inputLength) % this.blockSize; |
|
if (partialBytes > 0) partialBytes = this.blockSize - partialBytes; |
|
// XOR input with output, write input as partial output |
|
this._partialOutput.clear(); |
|
for(var i = 0; i < this._ints; ++i){ |
|
this._partialBlock[i] = input.getInt32(); |
|
this._partialOutput.putInt32(this._partialBlock[i] ^ this._outBlock[i]); |
|
} |
|
if (partialBytes > 0) // block still incomplete, restore input buffer |
|
input.read -= this.blockSize; |
|
else // block complete, update input block |
|
for(var i = 0; i < this._ints; ++i)this._inBlock[i] = this._partialBlock[i]; |
|
// skip any previous partial bytes |
|
if (this._partialBytes > 0) this._partialOutput.getBytes(this._partialBytes); |
|
if (partialBytes > 0 && !finish) { |
|
output.putBytes(this._partialOutput.getBytes(partialBytes - this._partialBytes)); |
|
this._partialBytes = partialBytes; |
|
return true; |
|
} |
|
output.putBytes(this._partialOutput.getBytes(inputLength - this._partialBytes)); |
|
this._partialBytes = 0; |
|
}; |
|
/** Output feedback (OFB) **/ $8e7d87db09a5396f$var$modes.ofb = function(options) { |
|
options = options || { |
|
}; |
|
this.name = 'OFB'; |
|
this.cipher = options.cipher; |
|
this.blockSize = options.blockSize || 16; |
|
this._ints = this.blockSize / 4; |
|
this._inBlock = null; |
|
this._outBlock = new Array(this._ints); |
|
this._partialOutput = $iGlOy.util.createBuffer(); |
|
this._partialBytes = 0; |
|
}; |
|
$8e7d87db09a5396f$var$modes.ofb.prototype.start = function(options) { |
|
if (!('iv' in options)) throw new Error('Invalid IV parameter.'); |
|
// use IV as first input |
|
this._iv = $8e7d87db09a5396f$var$transformIV(options.iv, this.blockSize); |
|
this._inBlock = this._iv.slice(0); |
|
this._partialBytes = 0; |
|
}; |
|
$8e7d87db09a5396f$var$modes.ofb.prototype.encrypt = function(input, output, finish) { |
|
// not enough input to encrypt |
|
var inputLength = input.length(); |
|
if (input.length() === 0) return true; |
|
// encrypt block (OFB always uses encryption mode) |
|
this.cipher.encrypt(this._inBlock, this._outBlock); |
|
// handle full block |
|
if (this._partialBytes === 0 && inputLength >= this.blockSize) { |
|
// XOR input with output and update next input |
|
for(var i = 0; i < this._ints; ++i){ |
|
output.putInt32(input.getInt32() ^ this._outBlock[i]); |
|
this._inBlock[i] = this._outBlock[i]; |
|
} |
|
return; |
|
} |
|
// handle partial block |
|
var partialBytes = (this.blockSize - inputLength) % this.blockSize; |
|
if (partialBytes > 0) partialBytes = this.blockSize - partialBytes; |
|
// XOR input with output |
|
this._partialOutput.clear(); |
|
for(var i = 0; i < this._ints; ++i)this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]); |
|
if (partialBytes > 0) // block still incomplete, restore input buffer |
|
input.read -= this.blockSize; |
|
else // block complete, update input block |
|
for(var i = 0; i < this._ints; ++i)this._inBlock[i] = this._outBlock[i]; |
|
// skip any previous partial bytes |
|
if (this._partialBytes > 0) this._partialOutput.getBytes(this._partialBytes); |
|
if (partialBytes > 0 && !finish) { |
|
output.putBytes(this._partialOutput.getBytes(partialBytes - this._partialBytes)); |
|
this._partialBytes = partialBytes; |
|
return true; |
|
} |
|
output.putBytes(this._partialOutput.getBytes(inputLength - this._partialBytes)); |
|
this._partialBytes = 0; |
|
}; |
|
$8e7d87db09a5396f$var$modes.ofb.prototype.decrypt = $8e7d87db09a5396f$var$modes.ofb.prototype.encrypt; |
|
/** Counter (CTR) **/ $8e7d87db09a5396f$var$modes.ctr = function(options) { |
|
options = options || { |
|
}; |
|
this.name = 'CTR'; |
|
this.cipher = options.cipher; |
|
this.blockSize = options.blockSize || 16; |
|
this._ints = this.blockSize / 4; |
|
this._inBlock = null; |
|
this._outBlock = new Array(this._ints); |
|
this._partialOutput = $iGlOy.util.createBuffer(); |
|
this._partialBytes = 0; |
|
}; |
|
$8e7d87db09a5396f$var$modes.ctr.prototype.start = function(options) { |
|
if (!('iv' in options)) throw new Error('Invalid IV parameter.'); |
|
// use IV as first input |
|
this._iv = $8e7d87db09a5396f$var$transformIV(options.iv, this.blockSize); |
|
this._inBlock = this._iv.slice(0); |
|
this._partialBytes = 0; |
|
}; |
|
$8e7d87db09a5396f$var$modes.ctr.prototype.encrypt = function(input, output, finish) { |
|
// not enough input to encrypt |
|
var inputLength = input.length(); |
|
if (inputLength === 0) return true; |
|
// encrypt block (CTR always uses encryption mode) |
|
this.cipher.encrypt(this._inBlock, this._outBlock); |
|
// handle full block |
|
if (this._partialBytes === 0 && inputLength >= this.blockSize) // XOR input with output |
|
for(var i = 0; i < this._ints; ++i)output.putInt32(input.getInt32() ^ this._outBlock[i]); |
|
else { |
|
// handle partial block |
|
var partialBytes = (this.blockSize - inputLength) % this.blockSize; |
|
if (partialBytes > 0) partialBytes = this.blockSize - partialBytes; |
|
// XOR input with output |
|
this._partialOutput.clear(); |
|
for(var i = 0; i < this._ints; ++i)this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]); |
|
if (partialBytes > 0) // block still incomplete, restore input buffer |
|
input.read -= this.blockSize; |
|
// skip any previous partial bytes |
|
if (this._partialBytes > 0) this._partialOutput.getBytes(this._partialBytes); |
|
if (partialBytes > 0 && !finish) { |
|
output.putBytes(this._partialOutput.getBytes(partialBytes - this._partialBytes)); |
|
this._partialBytes = partialBytes; |
|
return true; |
|
} |
|
output.putBytes(this._partialOutput.getBytes(inputLength - this._partialBytes)); |
|
this._partialBytes = 0; |
|
} |
|
// block complete, increment counter (input block) |
|
$8e7d87db09a5396f$var$inc32(this._inBlock); |
|
}; |
|
$8e7d87db09a5396f$var$modes.ctr.prototype.decrypt = $8e7d87db09a5396f$var$modes.ctr.prototype.encrypt; |
|
/** Galois/Counter Mode (GCM) **/ $8e7d87db09a5396f$var$modes.gcm = function(options) { |
|
options = options || { |
|
}; |
|
this.name = 'GCM'; |
|
this.cipher = options.cipher; |
|
this.blockSize = options.blockSize || 16; |
|
this._ints = this.blockSize / 4; |
|
this._inBlock = new Array(this._ints); |
|
this._outBlock = new Array(this._ints); |
|
this._partialOutput = $iGlOy.util.createBuffer(); |
|
this._partialBytes = 0; |
|
// R is actually this value concatenated with 120 more zero bits, but |
|
// we only XOR against R so the other zeros have no effect -- we just |
|
// apply this value to the first integer in a block |
|
this._R = 3774873600; |
|
}; |
|
$8e7d87db09a5396f$var$modes.gcm.prototype.start = function(options) { |
|
if (!('iv' in options)) throw new Error('Invalid IV parameter.'); |
|
// ensure IV is a byte buffer |
|
var iv = $iGlOy.util.createBuffer(options.iv); |
|
// no ciphered data processed yet |
|
this._cipherLength = 0; |
|
// default additional data is none |
|
var additionalData; |
|
if ('additionalData' in options) additionalData = $iGlOy.util.createBuffer(options.additionalData); |
|
else additionalData = $iGlOy.util.createBuffer(); |
|
// default tag length is 128 bits |
|
if ('tagLength' in options) this._tagLength = options.tagLength; |
|
else this._tagLength = 128; |
|
// if tag is given, ensure tag matches tag length |
|
this._tag = null; |
|
if (options.decrypt) { |
|
// save tag to check later |
|
this._tag = $iGlOy.util.createBuffer(options.tag).getBytes(); |
|
if (this._tag.length !== this._tagLength / 8) throw new Error('Authentication tag does not match tag length.'); |
|
} |
|
// create tmp storage for hash calculation |
|
this._hashBlock = new Array(this._ints); |
|
// no tag generated yet |
|
this.tag = null; |
|
// generate hash subkey |
|
// (apply block cipher to "zero" block) |
|
this._hashSubkey = new Array(this._ints); |
|
this.cipher.encrypt([ |
|
0, |
|
0, |
|
0, |
|
0 |
|
], this._hashSubkey); |
|
// generate table M |
|
// use 4-bit tables (32 component decomposition of a 16 byte value) |
|
// 8-bit tables take more space and are known to have security |
|
// vulnerabilities (in native implementations) |
|
this.componentBits = 4; |
|
this._m = this.generateHashTable(this._hashSubkey, this.componentBits); |
|
// Note: support IV length different from 96 bits? (only supporting |
|
// 96 bits is recommended by NIST SP-800-38D) |
|
// generate J_0 |
|
var ivLength = iv.length(); |
|
if (ivLength === 12) // 96-bit IV |
|
this._j0 = [ |
|
iv.getInt32(), |
|
iv.getInt32(), |
|
iv.getInt32(), |
|
1 |
|
]; |
|
else { |
|
// IV is NOT 96-bits |
|
this._j0 = [ |
|
0, |
|
0, |
|
0, |
|
0 |
|
]; |
|
while(iv.length() > 0)this._j0 = this.ghash(this._hashSubkey, this._j0, [ |
|
iv.getInt32(), |
|
iv.getInt32(), |
|
iv.getInt32(), |
|
iv.getInt32() |
|
]); |
|
this._j0 = this.ghash(this._hashSubkey, this._j0, [ |
|
0, |
|
0 |
|
].concat($8e7d87db09a5396f$var$from64To32(ivLength * 8))); |
|
} |
|
// generate ICB (initial counter block) |
|
this._inBlock = this._j0.slice(0); |
|
$8e7d87db09a5396f$var$inc32(this._inBlock); |
|
this._partialBytes = 0; |
|
// consume authentication data |
|
additionalData = $iGlOy.util.createBuffer(additionalData); |
|
// save additional data length as a BE 64-bit number |
|
this._aDataLength = $8e7d87db09a5396f$var$from64To32(additionalData.length() * 8); |
|
// pad additional data to 128 bit (16 byte) block size |
|
var overflow = additionalData.length() % this.blockSize; |
|
if (overflow) additionalData.fillWithByte(0, this.blockSize - overflow); |
|
this._s = [ |
|
0, |
|
0, |
|
0, |
|
0 |
|
]; |
|
while(additionalData.length() > 0)this._s = this.ghash(this._hashSubkey, this._s, [ |
|
additionalData.getInt32(), |
|
additionalData.getInt32(), |
|
additionalData.getInt32(), |
|
additionalData.getInt32() |
|
]); |
|
}; |
|
$8e7d87db09a5396f$var$modes.gcm.prototype.encrypt = function(input, output, finish) { |
|
// not enough input to encrypt |
|
var inputLength = input.length(); |
|
if (inputLength === 0) return true; |
|
// encrypt block |
|
this.cipher.encrypt(this._inBlock, this._outBlock); |
|
// handle full block |
|
if (this._partialBytes === 0 && inputLength >= this.blockSize) { |
|
// XOR input with output |
|
for(var i = 0; i < this._ints; ++i)output.putInt32(this._outBlock[i] ^= input.getInt32()); |
|
this._cipherLength += this.blockSize; |
|
} else { |
|
// handle partial block |
|
var partialBytes = (this.blockSize - inputLength) % this.blockSize; |
|
if (partialBytes > 0) partialBytes = this.blockSize - partialBytes; |
|
// XOR input with output |
|
this._partialOutput.clear(); |
|
for(var i = 0; i < this._ints; ++i)this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]); |
|
if (partialBytes <= 0 || finish) { |
|
// handle overflow prior to hashing |
|
if (finish) { |
|
// get block overflow |
|
var overflow = inputLength % this.blockSize; |
|
this._cipherLength += overflow; |
|
// truncate for hash function |
|
this._partialOutput.truncate(this.blockSize - overflow); |
|
} else this._cipherLength += this.blockSize; |
|
// get output block for hashing |
|
for(var i = 0; i < this._ints; ++i)this._outBlock[i] = this._partialOutput.getInt32(); |
|
this._partialOutput.read -= this.blockSize; |
|
} |
|
// skip any previous partial bytes |
|
if (this._partialBytes > 0) this._partialOutput.getBytes(this._partialBytes); |
|
if (partialBytes > 0 && !finish) { |
|
// block still incomplete, restore input buffer, get partial output, |
|
// and return early |
|
input.read -= this.blockSize; |
|
output.putBytes(this._partialOutput.getBytes(partialBytes - this._partialBytes)); |
|
this._partialBytes = partialBytes; |
|
return true; |
|
} |
|
output.putBytes(this._partialOutput.getBytes(inputLength - this._partialBytes)); |
|
this._partialBytes = 0; |
|
} |
|
// update hash block S |
|
this._s = this.ghash(this._hashSubkey, this._s, this._outBlock); |
|
// increment counter (input block) |
|
$8e7d87db09a5396f$var$inc32(this._inBlock); |
|
}; |
|
$8e7d87db09a5396f$var$modes.gcm.prototype.decrypt = function(input, output, finish) { |
|
// not enough input to decrypt |
|
var inputLength = input.length(); |
|
if (inputLength < this.blockSize && !(finish && inputLength > 0)) return true; |
|
// encrypt block (GCM always uses encryption mode) |
|
this.cipher.encrypt(this._inBlock, this._outBlock); |
|
// increment counter (input block) |
|
$8e7d87db09a5396f$var$inc32(this._inBlock); |
|
// update hash block S |
|
this._hashBlock[0] = input.getInt32(); |
|
this._hashBlock[1] = input.getInt32(); |
|
this._hashBlock[2] = input.getInt32(); |
|
this._hashBlock[3] = input.getInt32(); |
|
this._s = this.ghash(this._hashSubkey, this._s, this._hashBlock); |
|
// XOR hash input with output |
|
for(var i = 0; i < this._ints; ++i)output.putInt32(this._outBlock[i] ^ this._hashBlock[i]); |
|
// increment cipher data length |
|
if (inputLength < this.blockSize) this._cipherLength += inputLength % this.blockSize; |
|
else this._cipherLength += this.blockSize; |
|
}; |
|
$8e7d87db09a5396f$var$modes.gcm.prototype.afterFinish = function(output, options) { |
|
var rval = true; |
|
// handle overflow |
|
if (options.decrypt && options.overflow) output.truncate(this.blockSize - options.overflow); |
|
// handle authentication tag |
|
this.tag = $iGlOy.util.createBuffer(); |
|
// concatenate additional data length with cipher length |
|
var lengths = this._aDataLength.concat($8e7d87db09a5396f$var$from64To32(this._cipherLength * 8)); |
|
// include lengths in hash |
|
this._s = this.ghash(this._hashSubkey, this._s, lengths); |
|
// do GCTR(J_0, S) |
|
var tag = []; |
|
this.cipher.encrypt(this._j0, tag); |
|
for(var i = 0; i < this._ints; ++i)this.tag.putInt32(this._s[i] ^ tag[i]); |
|
// trim tag to length |
|
this.tag.truncate(this.tag.length() % (this._tagLength / 8)); |
|
// check authentication tag |
|
if (options.decrypt && this.tag.bytes() !== this._tag) rval = false; |
|
return rval; |
|
}; |
|
/** |
|
* See NIST SP-800-38D 6.3 (Algorithm 1). This function performs Galois |
|
* field multiplication. The field, GF(2^128), is defined by the polynomial: |
|
* |
|
* x^128 + x^7 + x^2 + x + 1 |
|
* |
|
* Which is represented in little-endian binary form as: 11100001 (0xe1). When |
|
* the value of a coefficient is 1, a bit is set. The value R, is the |
|
* concatenation of this value and 120 zero bits, yielding a 128-bit value |
|
* which matches the block size. |
|
* |
|
* This function will multiply two elements (vectors of bytes), X and Y, in |
|
* the field GF(2^128). The result is initialized to zero. For each bit of |
|
* X (out of 128), x_i, if x_i is set, then the result is multiplied (XOR'd) |
|
* by the current value of Y. For each bit, the value of Y will be raised by |
|
* a power of x (multiplied by the polynomial x). This can be achieved by |
|
* shifting Y once to the right. If the current value of Y, prior to being |
|
* multiplied by x, has 0 as its LSB, then it is a 127th degree polynomial. |
|
* Otherwise, we must divide by R after shifting to find the remainder. |
|
* |
|
* @param x the first block to multiply by the second. |
|
* @param y the second block to multiply by the first. |
|
* |
|
* @return the block result of the multiplication. |
|
*/ $8e7d87db09a5396f$var$modes.gcm.prototype.multiply = function(x, y) { |
|
var z_i = [ |
|
0, |
|
0, |
|
0, |
|
0 |
|
]; |
|
var v_i = y.slice(0); |
|
// calculate Z_128 (block has 128 bits) |
|
for(var i = 0; i < 128; ++i){ |
|
// if x_i is 0, Z_{i+1} = Z_i (unchanged) |
|
// else Z_{i+1} = Z_i ^ V_i |
|
// get x_i by finding 32-bit int position, then left shift 1 by remainder |
|
var x_i = x[i / 32 | 0] & 1 << 31 - i % 32; |
|
if (x_i) { |
|
z_i[0] ^= v_i[0]; |
|
z_i[1] ^= v_i[1]; |
|
z_i[2] ^= v_i[2]; |
|
z_i[3] ^= v_i[3]; |
|
} |
|
// if LSB(V_i) is 1, V_i = V_i >> 1 |
|
// else V_i = (V_i >> 1) ^ R |
|
this.pow(v_i, v_i); |
|
} |
|
return z_i; |
|
}; |
|
$8e7d87db09a5396f$var$modes.gcm.prototype.pow = function(x, out) { |
|
// if LSB(x) is 1, x = x >>> 1 |
|
// else x = (x >>> 1) ^ R |
|
var lsb = x[3] & 1; |
|
// always do x >>> 1: |
|
// starting with the rightmost integer, shift each integer to the right |
|
// one bit, pulling in the bit from the integer to the left as its top |
|
// most bit (do this for the last 3 integers) |
|
for(var i = 3; i > 0; --i)out[i] = x[i] >>> 1 | (x[i - 1] & 1) << 31; |
|
// shift the first integer normally |
|
out[0] = x[0] >>> 1; |
|
// if lsb was not set, then polynomial had a degree of 127 and doesn't |
|
// need to divided; otherwise, XOR with R to find the remainder; we only |
|
// need to XOR the first integer since R technically ends w/120 zero bits |
|
if (lsb) out[0] ^= this._R; |
|
}; |
|
$8e7d87db09a5396f$var$modes.gcm.prototype.tableMultiply = function(x) { |
|
// assumes 4-bit tables are used |
|
var z = [ |
|
0, |
|
0, |
|
0, |
|
0 |
|
]; |
|
for(var i = 0; i < 32; ++i){ |
|
var idx = i / 8 | 0; |
|
var x_i = x[idx] >>> (7 - i % 8) * 4 & 15; |
|
var ah = this._m[i][x_i]; |
|
z[0] ^= ah[0]; |
|
z[1] ^= ah[1]; |
|
z[2] ^= ah[2]; |
|
z[3] ^= ah[3]; |
|
} |
|
return z; |
|
}; |
|
/** |
|
* A continuing version of the GHASH algorithm that operates on a single |
|
* block. The hash block, last hash value (Ym) and the new block to hash |
|
* are given. |
|
* |
|
* @param h the hash block. |
|
* @param y the previous value for Ym, use [0, 0, 0, 0] for a new hash. |
|
* @param x the block to hash. |
|
* |
|
* @return the hashed value (Ym). |
|
*/ $8e7d87db09a5396f$var$modes.gcm.prototype.ghash = function(h, y, x) { |
|
y[0] ^= x[0]; |
|
y[1] ^= x[1]; |
|
y[2] ^= x[2]; |
|
y[3] ^= x[3]; |
|
return this.tableMultiply(y); |
|
//return this.multiply(y, h); |
|
}; |
|
/** |
|
* Precomputes a table for multiplying against the hash subkey. This |
|
* mechanism provides a substantial speed increase over multiplication |
|
* performed without a table. The table-based multiplication this table is |
|
* for solves X * H by multiplying each component of X by H and then |
|
* composing the results together using XOR. |
|
* |
|
* This function can be used to generate tables with different bit sizes |
|
* for the components, however, this implementation assumes there are |
|
* 32 components of X (which is a 16 byte vector), therefore each component |
|
* takes 4-bits (so the table is constructed with bits=4). |
|
* |
|
* @param h the hash subkey. |
|
* @param bits the bit size for a component. |
|
*/ $8e7d87db09a5396f$var$modes.gcm.prototype.generateHashTable = function(h, bits) { |
|
// TODO: There are further optimizations that would use only the |
|
// first table M_0 (or some variant) along with a remainder table; |
|
// this can be explored in the future |
|
var multiplier = 8 / bits; |
|
var perInt = 4 * multiplier; |
|
var size = 16 * multiplier; |
|
var m = new Array(size); |
|
for(var i = 0; i < size; ++i){ |
|
var tmp = [ |
|
0, |
|
0, |
|
0, |
|
0 |
|
]; |
|
var idx = i / perInt | 0; |
|
var shft = (perInt - 1 - i % perInt) * bits; |
|
tmp[idx] = 1 << bits - 1 << shft; |
|
m[i] = this.generateSubHashTable(this.multiply(tmp, h), bits); |
|
} |
|
return m; |
|
}; |
|
/** |
|
* Generates a table for multiplying against the hash subkey for one |
|
* particular component (out of all possible component values). |
|
* |
|
* @param mid the pre-multiplied value for the middle key of the table. |
|
* @param bits the bit size for a component. |
|
*/ $8e7d87db09a5396f$var$modes.gcm.prototype.generateSubHashTable = function(mid, bits) { |
|
// compute the table quickly by minimizing the number of |
|
// POW operations -- they only need to be performed for powers of 2, |
|
// all other entries can be composed from those powers using XOR |
|
var size = 1 << bits; |
|
var half = size >>> 1; |
|
var m = new Array(size); |
|
m[half] = mid.slice(0); |
|
var i = half >>> 1; |
|
while(i > 0){ |
|
// raise m0[2 * i] and store in m0[i] |
|
this.pow(m[2 * i], m[i] = []); |
|
i >>= 1; |
|
} |
|
i = 2; |
|
while(i < half){ |
|
for(var j = 1; j < i; ++j){ |
|
var m_i = m[i]; |
|
var m_j = m[j]; |
|
m[i + j] = [ |
|
m_i[0] ^ m_j[0], |
|
m_i[1] ^ m_j[1], |
|
m_i[2] ^ m_j[2], |
|
m_i[3] ^ m_j[3] |
|
]; |
|
} |
|
i *= 2; |
|
} |
|
m[0] = [ |
|
0, |
|
0, |
|
0, |
|
0 |
|
]; |
|
/* Note: We could avoid storing these by doing composition during multiply |
|
calculate top half using composition by speed is preferred. */ for(i = half + 1; i < size; ++i){ |
|
var c = m[i ^ half]; |
|
m[i] = [ |
|
mid[0] ^ c[0], |
|
mid[1] ^ c[1], |
|
mid[2] ^ c[2], |
|
mid[3] ^ c[3] |
|
]; |
|
} |
|
return m; |
|
}; |
|
/** Utility functions */ function $8e7d87db09a5396f$var$transformIV(iv, blockSize) { |
|
if (typeof iv === 'string') // convert iv string into byte buffer |
|
iv = $iGlOy.util.createBuffer(iv); |
|
if ($iGlOy.util.isArray(iv) && iv.length > 4) { |
|
// convert iv byte array into byte buffer |
|
var tmp = iv; |
|
iv = $iGlOy.util.createBuffer(); |
|
for(var i = 0; i < tmp.length; ++i)iv.putByte(tmp[i]); |
|
} |
|
if (iv.length() < blockSize) throw new Error('Invalid IV length; got ' + iv.length() + ' bytes and expected ' + blockSize + ' bytes.'); |
|
if (!$iGlOy.util.isArray(iv)) { |
|
// convert iv byte buffer into 32-bit integer array |
|
var ints = []; |
|
var blocks = blockSize / 4; |
|
for(var i = 0; i < blocks; ++i)ints.push(iv.getInt32()); |
|
iv = ints; |
|
} |
|
return iv; |
|
} |
|
function $8e7d87db09a5396f$var$inc32(block) { |
|
// increment last 32 bits of block only |
|
block[block.length - 1] = block[block.length - 1] + 1 & 4294967295; |
|
} |
|
function $8e7d87db09a5396f$var$from64To32(num) { |
|
// convert 64-bit number to two BE Int32s |
|
return [ |
|
num / 4294967296 | 0, |
|
num & 4294967295 |
|
]; |
|
} |
|
|
|
|
|
|
|
/* AES API */ $ca9d5cba0afae339$exports = $iGlOy.aes = $iGlOy.aes || { |
|
}; |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* var cipher = forge.cipher.createCipher('AES-<mode>', key); |
|
* cipher.start({iv: iv}); |
|
* |
|
* Creates an AES cipher object to encrypt data using the given symmetric key. |
|
* The output will be stored in the 'output' member of the returned cipher. |
|
* |
|
* The key and iv may be given as a string of bytes, an array of bytes, |
|
* a byte buffer, or an array of 32-bit words. |
|
* |
|
* @param key the symmetric key to use. |
|
* @param iv the initialization vector to use. |
|
* @param output the buffer to write to, null to create one. |
|
* @param mode the cipher mode to use (default: 'CBC'). |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.aes.startEncrypting = function(key, iv, output, mode) { |
|
var cipher = $ca9d5cba0afae339$var$_createCipher({ |
|
key: key, |
|
output: output, |
|
decrypt: false, |
|
mode: mode |
|
}); |
|
cipher.start(iv); |
|
return cipher; |
|
}; |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* var cipher = forge.cipher.createCipher('AES-<mode>', key); |
|
* |
|
* Creates an AES cipher object to encrypt data using the given symmetric key. |
|
* |
|
* The key may be given as a string of bytes, an array of bytes, a |
|
* byte buffer, or an array of 32-bit words. |
|
* |
|
* @param key the symmetric key to use. |
|
* @param mode the cipher mode to use (default: 'CBC'). |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.aes.createEncryptionCipher = function(key, mode) { |
|
return $ca9d5cba0afae339$var$_createCipher({ |
|
key: key, |
|
output: null, |
|
decrypt: false, |
|
mode: mode |
|
}); |
|
}; |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* var decipher = forge.cipher.createDecipher('AES-<mode>', key); |
|
* decipher.start({iv: iv}); |
|
* |
|
* Creates an AES cipher object to decrypt data using the given symmetric key. |
|
* The output will be stored in the 'output' member of the returned cipher. |
|
* |
|
* The key and iv may be given as a string of bytes, an array of bytes, |
|
* a byte buffer, or an array of 32-bit words. |
|
* |
|
* @param key the symmetric key to use. |
|
* @param iv the initialization vector to use. |
|
* @param output the buffer to write to, null to create one. |
|
* @param mode the cipher mode to use (default: 'CBC'). |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.aes.startDecrypting = function(key, iv, output, mode) { |
|
var cipher = $ca9d5cba0afae339$var$_createCipher({ |
|
key: key, |
|
output: output, |
|
decrypt: true, |
|
mode: mode |
|
}); |
|
cipher.start(iv); |
|
return cipher; |
|
}; |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* var decipher = forge.cipher.createDecipher('AES-<mode>', key); |
|
* |
|
* Creates an AES cipher object to decrypt data using the given symmetric key. |
|
* |
|
* The key may be given as a string of bytes, an array of bytes, a |
|
* byte buffer, or an array of 32-bit words. |
|
* |
|
* @param key the symmetric key to use. |
|
* @param mode the cipher mode to use (default: 'CBC'). |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.aes.createDecryptionCipher = function(key, mode) { |
|
return $ca9d5cba0afae339$var$_createCipher({ |
|
key: key, |
|
output: null, |
|
decrypt: true, |
|
mode: mode |
|
}); |
|
}; |
|
/** |
|
* Creates a new AES cipher algorithm object. |
|
* |
|
* @param name the name of the algorithm. |
|
* @param mode the mode factory function. |
|
* |
|
* @return the AES algorithm object. |
|
*/ $iGlOy.aes.Algorithm = function(name, mode) { |
|
if (!$ca9d5cba0afae339$var$init) $ca9d5cba0afae339$var$initialize(); |
|
var self = this; |
|
self.name = name; |
|
self.mode = new mode({ |
|
blockSize: 16, |
|
cipher: { |
|
encrypt: function(inBlock, outBlock) { |
|
return $ca9d5cba0afae339$var$_updateBlock(self._w, inBlock, outBlock, false); |
|
}, |
|
decrypt: function(inBlock, outBlock) { |
|
return $ca9d5cba0afae339$var$_updateBlock(self._w, inBlock, outBlock, true); |
|
} |
|
} |
|
}); |
|
self._init = false; |
|
}; |
|
/** |
|
* Initializes this AES algorithm by expanding its key. |
|
* |
|
* @param options the options to use. |
|
* key the key to use with this algorithm. |
|
* decrypt true if the algorithm should be initialized for decryption, |
|
* false for encryption. |
|
*/ $iGlOy.aes.Algorithm.prototype.initialize = function(options) { |
|
if (this._init) return; |
|
var key = options.key; |
|
var tmp; |
|
/* Note: The key may be a string of bytes, an array of bytes, a byte |
|
buffer, or an array of 32-bit integers. If the key is in bytes, then |
|
it must be 16, 24, or 32 bytes in length. If it is in 32-bit |
|
integers, it must be 4, 6, or 8 integers long. */ if (typeof key === 'string' && (key.length === 16 || key.length === 24 || key.length === 32)) // convert key string into byte buffer |
|
key = $iGlOy.util.createBuffer(key); |
|
else if ($iGlOy.util.isArray(key) && (key.length === 16 || key.length === 24 || key.length === 32)) { |
|
// convert key integer array into byte buffer |
|
tmp = key; |
|
key = $iGlOy.util.createBuffer(); |
|
for(var i = 0; i < tmp.length; ++i)key.putByte(tmp[i]); |
|
} |
|
// convert key byte buffer into 32-bit integer array |
|
if (!$iGlOy.util.isArray(key)) { |
|
tmp = key; |
|
key = []; |
|
// key lengths of 16, 24, 32 bytes allowed |
|
var len = tmp.length(); |
|
if (len === 16 || len === 24 || len === 32) { |
|
len = len >>> 2; |
|
for(var i = 0; i < len; ++i)key.push(tmp.getInt32()); |
|
} |
|
} |
|
// key must be an array of 32-bit integers by now |
|
if (!$iGlOy.util.isArray(key) || !(key.length === 4 || key.length === 6 || key.length === 8)) throw new Error('Invalid key parameter.'); |
|
// encryption operation is always used for these modes |
|
var mode = this.mode.name; |
|
var encryptOp = [ |
|
'CFB', |
|
'OFB', |
|
'CTR', |
|
'GCM' |
|
].indexOf(mode) !== -1; |
|
// do key expansion |
|
this._w = $ca9d5cba0afae339$var$_expandKey(key, options.decrypt && !encryptOp); |
|
this._init = true; |
|
}; |
|
/** |
|
* Expands a key. Typically only used for testing. |
|
* |
|
* @param key the symmetric key to expand, as an array of 32-bit words. |
|
* @param decrypt true to expand for decryption, false for encryption. |
|
* |
|
* @return the expanded key. |
|
*/ $iGlOy.aes._expandKey = function(key, decrypt) { |
|
if (!$ca9d5cba0afae339$var$init) $ca9d5cba0afae339$var$initialize(); |
|
return $ca9d5cba0afae339$var$_expandKey(key, decrypt); |
|
}; |
|
/** |
|
* Updates a single block. Typically only used for testing. |
|
* |
|
* @param w the expanded key to use. |
|
* @param input an array of block-size 32-bit words. |
|
* @param output an array of block-size 32-bit words. |
|
* @param decrypt true to decrypt, false to encrypt. |
|
*/ $iGlOy.aes._updateBlock = $ca9d5cba0afae339$var$_updateBlock; |
|
/** Register AES algorithms **/ $ca9d5cba0afae339$var$registerAlgorithm('AES-ECB', $iGlOy.cipher.modes.ecb); |
|
$ca9d5cba0afae339$var$registerAlgorithm('AES-CBC', $iGlOy.cipher.modes.cbc); |
|
$ca9d5cba0afae339$var$registerAlgorithm('AES-CFB', $iGlOy.cipher.modes.cfb); |
|
$ca9d5cba0afae339$var$registerAlgorithm('AES-OFB', $iGlOy.cipher.modes.ofb); |
|
$ca9d5cba0afae339$var$registerAlgorithm('AES-CTR', $iGlOy.cipher.modes.ctr); |
|
$ca9d5cba0afae339$var$registerAlgorithm('AES-GCM', $iGlOy.cipher.modes.gcm); |
|
function $ca9d5cba0afae339$var$registerAlgorithm(name, mode) { |
|
var factory = function() { |
|
return new $iGlOy.aes.Algorithm(name, mode); |
|
}; |
|
$iGlOy.cipher.registerAlgorithm(name, factory); |
|
} |
|
/** AES implementation **/ var $ca9d5cba0afae339$var$init = false; // not yet initialized |
|
var $ca9d5cba0afae339$var$Nb = 4; // number of words comprising the state (AES = 4) |
|
var $ca9d5cba0afae339$var$sbox; // non-linear substitution table used in key expansion |
|
var $ca9d5cba0afae339$var$isbox; // inversion of sbox |
|
var $ca9d5cba0afae339$var$rcon; // round constant word array |
|
var $ca9d5cba0afae339$var$mix; // mix-columns table |
|
var $ca9d5cba0afae339$var$imix; // inverse mix-columns table |
|
/** |
|
* Performs initialization, ie: precomputes tables to optimize for speed. |
|
* |
|
* One way to understand how AES works is to imagine that 'addition' and |
|
* 'multiplication' are interfaces that require certain mathematical |
|
* properties to hold true (ie: they are associative) but they might have |
|
* different implementations and produce different kinds of results ... |
|
* provided that their mathematical properties remain true. AES defines |
|
* its own methods of addition and multiplication but keeps some important |
|
* properties the same, ie: associativity and distributivity. The |
|
* explanation below tries to shed some light on how AES defines addition |
|
* and multiplication of bytes and 32-bit words in order to perform its |
|
* encryption and decryption algorithms. |
|
* |
|
* The basics: |
|
* |
|
* The AES algorithm views bytes as binary representations of polynomials |
|
* that have either 1 or 0 as the coefficients. It defines the addition |
|
* or subtraction of two bytes as the XOR operation. It also defines the |
|
* multiplication of two bytes as a finite field referred to as GF(2^8) |
|
* (Note: 'GF' means "Galois Field" which is a field that contains a finite |
|
* number of elements so GF(2^8) has 256 elements). |
|
* |
|
* This means that any two bytes can be represented as binary polynomials; |
|
* when they multiplied together and modularly reduced by an irreducible |
|
* polynomial of the 8th degree, the results are the field GF(2^8). The |
|
* specific irreducible polynomial that AES uses in hexadecimal is 0x11b. |
|
* This multiplication is associative with 0x01 as the identity: |
|
* |
|
* (b * 0x01 = GF(b, 0x01) = b). |
|
* |
|
* The operation GF(b, 0x02) can be performed at the byte level by left |
|
* shifting b once and then XOR'ing it (to perform the modular reduction) |
|
* with 0x11b if b is >= 128. Repeated application of the multiplication |
|
* of 0x02 can be used to implement the multiplication of any two bytes. |
|
* |
|
* For instance, multiplying 0x57 and 0x13, denoted as GF(0x57, 0x13), can |
|
* be performed by factoring 0x13 into 0x01, 0x02, and 0x10. Then these |
|
* factors can each be multiplied by 0x57 and then added together. To do |
|
* the multiplication, values for 0x57 multiplied by each of these 3 factors |
|
* can be precomputed and stored in a table. To add them, the values from |
|
* the table are XOR'd together. |
|
* |
|
* AES also defines addition and multiplication of words, that is 4-byte |
|
* numbers represented as polynomials of 3 degrees where the coefficients |
|
* are the values of the bytes. |
|
* |
|
* The word [a0, a1, a2, a3] is a polynomial a3x^3 + a2x^2 + a1x + a0. |
|
* |
|
* Addition is performed by XOR'ing like powers of x. Multiplication |
|
* is performed in two steps, the first is an algebriac expansion as |
|
* you would do normally (where addition is XOR). But the result is |
|
* a polynomial larger than 3 degrees and thus it cannot fit in a word. So |
|
* next the result is modularly reduced by an AES-specific polynomial of |
|
* degree 4 which will always produce a polynomial of less than 4 degrees |
|
* such that it will fit in a word. In AES, this polynomial is x^4 + 1. |
|
* |
|
* The modular product of two polynomials 'a' and 'b' is thus: |
|
* |
|
* d(x) = d3x^3 + d2x^2 + d1x + d0 |
|
* with |
|
* d0 = GF(a0, b0) ^ GF(a3, b1) ^ GF(a2, b2) ^ GF(a1, b3) |
|
* d1 = GF(a1, b0) ^ GF(a0, b1) ^ GF(a3, b2) ^ GF(a2, b3) |
|
* d2 = GF(a2, b0) ^ GF(a1, b1) ^ GF(a0, b2) ^ GF(a3, b3) |
|
* d3 = GF(a3, b0) ^ GF(a2, b1) ^ GF(a1, b2) ^ GF(a0, b3) |
|
* |
|
* As a matrix: |
|
* |
|
* [d0] = [a0 a3 a2 a1][b0] |
|
* [d1] [a1 a0 a3 a2][b1] |
|
* [d2] [a2 a1 a0 a3][b2] |
|
* [d3] [a3 a2 a1 a0][b3] |
|
* |
|
* Special polynomials defined by AES (0x02 == {02}): |
|
* a(x) = {03}x^3 + {01}x^2 + {01}x + {02} |
|
* a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. |
|
* |
|
* These polynomials are used in the MixColumns() and InverseMixColumns() |
|
* operations, respectively, to cause each element in the state to affect |
|
* the output (referred to as diffusing). |
|
* |
|
* RotWord() uses: a0 = a1 = a2 = {00} and a3 = {01}, which is the |
|
* polynomial x3. |
|
* |
|
* The ShiftRows() method modifies the last 3 rows in the state (where |
|
* the state is 4 words with 4 bytes per word) by shifting bytes cyclically. |
|
* The 1st byte in the second row is moved to the end of the row. The 1st |
|
* and 2nd bytes in the third row are moved to the end of the row. The 1st, |
|
* 2nd, and 3rd bytes are moved in the fourth row. |
|
* |
|
* More details on how AES arithmetic works: |
|
* |
|
* In the polynomial representation of binary numbers, XOR performs addition |
|
* and subtraction and multiplication in GF(2^8) denoted as GF(a, b) |
|
* corresponds with the multiplication of polynomials modulo an irreducible |
|
* polynomial of degree 8. In other words, for AES, GF(a, b) will multiply |
|
* polynomial 'a' with polynomial 'b' and then do a modular reduction by |
|
* an AES-specific irreducible polynomial of degree 8. |
|
* |
|
* A polynomial is irreducible if its only divisors are one and itself. For |
|
* the AES algorithm, this irreducible polynomial is: |
|
* |
|
* m(x) = x^8 + x^4 + x^3 + x + 1, |
|
* |
|
* or {01}{1b} in hexadecimal notation, where each coefficient is a bit: |
|
* 100011011 = 283 = 0x11b. |
|
* |
|
* For example, GF(0x57, 0x83) = 0xc1 because |
|
* |
|
* 0x57 = 87 = 01010111 = x^6 + x^4 + x^2 + x + 1 |
|
* 0x85 = 131 = 10000101 = x^7 + x + 1 |
|
* |
|
* (x^6 + x^4 + x^2 + x + 1) * (x^7 + x + 1) |
|
* = x^13 + x^11 + x^9 + x^8 + x^7 + |
|
* x^7 + x^5 + x^3 + x^2 + x + |
|
* x^6 + x^4 + x^2 + x + 1 |
|
* = x^13 + x^11 + x^9 + x^8 + x^6 + x^5 + x^4 + x^3 + 1 = y |
|
* y modulo (x^8 + x^4 + x^3 + x + 1) |
|
* = x^7 + x^6 + 1. |
|
* |
|
* The modular reduction by m(x) guarantees the result will be a binary |
|
* polynomial of less than degree 8, so that it can fit in a byte. |
|
* |
|
* The operation to multiply a binary polynomial b with x (the polynomial |
|
* x in binary representation is 00000010) is: |
|
* |
|
* b_7x^8 + b_6x^7 + b_5x^6 + b_4x^5 + b_3x^4 + b_2x^3 + b_1x^2 + b_0x^1 |
|
* |
|
* To get GF(b, x) we must reduce that by m(x). If b_7 is 0 (that is the |
|
* most significant bit is 0 in b) then the result is already reduced. If |
|
* it is 1, then we can reduce it by subtracting m(x) via an XOR. |
|
* |
|
* It follows that multiplication by x (00000010 or 0x02) can be implemented |
|
* by performing a left shift followed by a conditional bitwise XOR with |
|
* 0x1b. This operation on bytes is denoted by xtime(). Multiplication by |
|
* higher powers of x can be implemented by repeated application of xtime(). |
|
* |
|
* By adding intermediate results, multiplication by any constant can be |
|
* implemented. For instance: |
|
* |
|
* GF(0x57, 0x13) = 0xfe because: |
|
* |
|
* xtime(b) = (b & 128) ? (b << 1 ^ 0x11b) : (b << 1) |
|
* |
|
* Note: We XOR with 0x11b instead of 0x1b because in javascript our |
|
* datatype for b can be larger than 1 byte, so a left shift will not |
|
* automatically eliminate bits that overflow a byte ... by XOR'ing the |
|
* overflow bit with 1 (the extra one from 0x11b) we zero it out. |
|
* |
|
* GF(0x57, 0x02) = xtime(0x57) = 0xae |
|
* GF(0x57, 0x04) = xtime(0xae) = 0x47 |
|
* GF(0x57, 0x08) = xtime(0x47) = 0x8e |
|
* GF(0x57, 0x10) = xtime(0x8e) = 0x07 |
|
* |
|
* GF(0x57, 0x13) = GF(0x57, (0x01 ^ 0x02 ^ 0x10)) |
|
* |
|
* And by the distributive property (since XOR is addition and GF() is |
|
* multiplication): |
|
* |
|
* = GF(0x57, 0x01) ^ GF(0x57, 0x02) ^ GF(0x57, 0x10) |
|
* = 0x57 ^ 0xae ^ 0x07 |
|
* = 0xfe. |
|
*/ function $ca9d5cba0afae339$var$initialize() { |
|
$ca9d5cba0afae339$var$init = true; |
|
/* Populate the Rcon table. These are the values given by |
|
[x^(i-1),{00},{00},{00}] where x^(i-1) are powers of x (and x = 0x02) |
|
in the field of GF(2^8), where i starts at 1. |
|
|
|
rcon[0] = [0x00, 0x00, 0x00, 0x00] |
|
rcon[1] = [0x01, 0x00, 0x00, 0x00] 2^(1-1) = 2^0 = 1 |
|
rcon[2] = [0x02, 0x00, 0x00, 0x00] 2^(2-1) = 2^1 = 2 |
|
... |
|
rcon[9] = [0x1B, 0x00, 0x00, 0x00] 2^(9-1) = 2^8 = 0x1B |
|
rcon[10] = [0x36, 0x00, 0x00, 0x00] 2^(10-1) = 2^9 = 0x36 |
|
|
|
We only store the first byte because it is the only one used. |
|
*/ $ca9d5cba0afae339$var$rcon = [ |
|
0, |
|
1, |
|
2, |
|
4, |
|
8, |
|
16, |
|
32, |
|
64, |
|
128, |
|
27, |
|
54 |
|
]; |
|
// compute xtime table which maps i onto GF(i, 0x02) |
|
var xtime = new Array(256); |
|
for(var i = 0; i < 128; ++i){ |
|
xtime[i] = i << 1; |
|
xtime[i + 128] = i + 128 << 1 ^ 283; |
|
} |
|
// compute all other tables |
|
$ca9d5cba0afae339$var$sbox = new Array(256); |
|
$ca9d5cba0afae339$var$isbox = new Array(256); |
|
$ca9d5cba0afae339$var$mix = new Array(4); |
|
$ca9d5cba0afae339$var$imix = new Array(4); |
|
for(var i = 0; i < 4; ++i){ |
|
$ca9d5cba0afae339$var$mix[i] = new Array(256); |
|
$ca9d5cba0afae339$var$imix[i] = new Array(256); |
|
} |
|
var e = 0, ei = 0, e2, e4, e8, sx, sx2, me, ime; |
|
for(var i = 0; i < 256; ++i){ |
|
/* We need to generate the SubBytes() sbox and isbox tables so that |
|
we can perform byte substitutions. This requires us to traverse |
|
all of the elements in GF, find their multiplicative inverses, |
|
and apply to each the following affine transformation: |
|
|
|
bi' = bi ^ b(i + 4) mod 8 ^ b(i + 5) mod 8 ^ b(i + 6) mod 8 ^ |
|
b(i + 7) mod 8 ^ ci |
|
for 0 <= i < 8, where bi is the ith bit of the byte, and ci is the |
|
ith bit of a byte c with the value {63} or {01100011}. |
|
|
|
It is possible to traverse every possible value in a Galois field |
|
using what is referred to as a 'generator'. There are many |
|
generators (128 out of 256): 3,5,6,9,11,82 to name a few. To fully |
|
traverse GF we iterate 255 times, multiplying by our generator |
|
each time. |
|
|
|
On each iteration we can determine the multiplicative inverse for |
|
the current element. |
|
|
|
Suppose there is an element in GF 'e'. For a given generator 'g', |
|
e = g^x. The multiplicative inverse of e is g^(255 - x). It turns |
|
out that if use the inverse of a generator as another generator |
|
it will produce all of the corresponding multiplicative inverses |
|
at the same time. For this reason, we choose 5 as our inverse |
|
generator because it only requires 2 multiplies and 1 add and its |
|
inverse, 82, requires relatively few operations as well. |
|
|
|
In order to apply the affine transformation, the multiplicative |
|
inverse 'ei' of 'e' can be repeatedly XOR'd (4 times) with a |
|
bit-cycling of 'ei'. To do this 'ei' is first stored in 's' and |
|
'x'. Then 's' is left shifted and the high bit of 's' is made the |
|
low bit. The resulting value is stored in 's'. Then 'x' is XOR'd |
|
with 's' and stored in 'x'. On each subsequent iteration the same |
|
operation is performed. When 4 iterations are complete, 'x' is |
|
XOR'd with 'c' (0x63) and the transformed value is stored in 'x'. |
|
For example: |
|
|
|
s = 01000001 |
|
x = 01000001 |
|
|
|
iteration 1: s = 10000010, x ^= s |
|
iteration 2: s = 00000101, x ^= s |
|
iteration 3: s = 00001010, x ^= s |
|
iteration 4: s = 00010100, x ^= s |
|
x ^= 0x63 |
|
|
|
This can be done with a loop where s = (s << 1) | (s >> 7). However, |
|
it can also be done by using a single 16-bit (in this case 32-bit) |
|
number 'sx'. Since XOR is an associative operation, we can set 'sx' |
|
to 'ei' and then XOR it with 'sx' left-shifted 1,2,3, and 4 times. |
|
The most significant bits will flow into the high 8 bit positions |
|
and be correctly XOR'd with one another. All that remains will be |
|
to cycle the high 8 bits by XOR'ing them all with the lower 8 bits |
|
afterwards. |
|
|
|
At the same time we're populating sbox and isbox we can precompute |
|
the multiplication we'll need to do to do MixColumns() later. |
|
*/ // apply affine transformation |
|
sx = ei ^ ei << 1 ^ ei << 2 ^ ei << 3 ^ ei << 4; |
|
sx = sx >> 8 ^ sx & 255 ^ 99; |
|
// update tables |
|
$ca9d5cba0afae339$var$sbox[e] = sx; |
|
$ca9d5cba0afae339$var$isbox[sx] = e; |
|
/* Mixing columns is done using matrix multiplication. The columns |
|
that are to be mixed are each a single word in the current state. |
|
The state has Nb columns (4 columns). Therefore each column is a |
|
4 byte word. So to mix the columns in a single column 'c' where |
|
its rows are r0, r1, r2, and r3, we use the following matrix |
|
multiplication: |
|
|
|
[2 3 1 1]*[r0,c]=[r'0,c] |
|
[1 2 3 1] [r1,c] [r'1,c] |
|
[1 1 2 3] [r2,c] [r'2,c] |
|
[3 1 1 2] [r3,c] [r'3,c] |
|
|
|
r0, r1, r2, and r3 are each 1 byte of one of the words in the |
|
state (a column). To do matrix multiplication for each mixed |
|
column c' we multiply the corresponding row from the left matrix |
|
with the corresponding column from the right matrix. In total, we |
|
get 4 equations: |
|
|
|
r0,c' = 2*r0,c + 3*r1,c + 1*r2,c + 1*r3,c |
|
r1,c' = 1*r0,c + 2*r1,c + 3*r2,c + 1*r3,c |
|
r2,c' = 1*r0,c + 1*r1,c + 2*r2,c + 3*r3,c |
|
r3,c' = 3*r0,c + 1*r1,c + 1*r2,c + 2*r3,c |
|
|
|
As usual, the multiplication is as previously defined and the |
|
addition is XOR. In order to optimize mixing columns we can store |
|
the multiplication results in tables. If you think of the whole |
|
column as a word (it might help to visualize by mentally rotating |
|
the equations above by counterclockwise 90 degrees) then you can |
|
see that it would be useful to map the multiplications performed on |
|
each byte (r0, r1, r2, r3) onto a word as well. For instance, we |
|
could map 2*r0,1*r0,1*r0,3*r0 onto a word by storing 2*r0 in the |
|
highest 8 bits and 3*r0 in the lowest 8 bits (with the other two |
|
respectively in the middle). This means that a table can be |
|
constructed that uses r0 as an index to the word. We can do the |
|
same with r1, r2, and r3, creating a total of 4 tables. |
|
|
|
To construct a full c', we can just look up each byte of c in |
|
their respective tables and XOR the results together. |
|
|
|
Also, to build each table we only have to calculate the word |
|
for 2,1,1,3 for every byte ... which we can do on each iteration |
|
of this loop since we will iterate over every byte. After we have |
|
calculated 2,1,1,3 we can get the results for the other tables |
|
by cycling the byte at the end to the beginning. For instance |
|
we can take the result of table 2,1,1,3 and produce table 3,2,1,1 |
|
by moving the right most byte to the left most position just like |
|
how you can imagine the 3 moved out of 2,1,1,3 and to the front |
|
to produce 3,2,1,1. |
|
|
|
There is another optimization in that the same multiples of |
|
the current element we need in order to advance our generator |
|
to the next iteration can be reused in performing the 2,1,1,3 |
|
calculation. We also calculate the inverse mix column tables, |
|
with e,9,d,b being the inverse of 2,1,1,3. |
|
|
|
When we're done, and we need to actually mix columns, the first |
|
byte of each state word should be put through mix[0] (2,1,1,3), |
|
the second through mix[1] (3,2,1,1) and so forth. Then they should |
|
be XOR'd together to produce the fully mixed column. |
|
*/ // calculate mix and imix table values |
|
sx2 = xtime[sx]; |
|
e2 = xtime[e]; |
|
e4 = xtime[e2]; |
|
e8 = xtime[e4]; |
|
me = sx2 << 24 ^ sx << 16 ^ sx << 8 ^ (sx ^ sx2); // 3 |
|
ime = (e2 ^ e4 ^ e8) << 24 ^ (e ^ e8) << 16 ^ (e ^ e4 ^ e8) << 8 ^ (e ^ e2 ^ e8); // B (11) |
|
// produce each of the mix tables by rotating the 2,1,1,3 value |
|
for(var n = 0; n < 4; ++n){ |
|
$ca9d5cba0afae339$var$mix[n][e] = me; |
|
$ca9d5cba0afae339$var$imix[n][sx] = ime; |
|
// cycle the right most byte to the left most position |
|
// ie: 2,1,1,3 becomes 3,2,1,1 |
|
me = me << 24 | me >>> 8; |
|
ime = ime << 24 | ime >>> 8; |
|
} |
|
// get next element and inverse |
|
if (e === 0) // 1 is the inverse of 1 |
|
e = ei = 1; |
|
else { |
|
// e = 2e + 2*2*2*(10e)) = multiply e by 82 (chosen generator) |
|
// ei = ei + 2*2*ei = multiply ei by 5 (inverse generator) |
|
e = e2 ^ xtime[xtime[xtime[e2 ^ e8]]]; |
|
ei ^= xtime[xtime[ei]]; |
|
} |
|
} |
|
} |
|
/** |
|
* Generates a key schedule using the AES key expansion algorithm. |
|
* |
|
* The AES algorithm takes the Cipher Key, K, and performs a Key Expansion |
|
* routine to generate a key schedule. The Key Expansion generates a total |
|
* of Nb*(Nr + 1) words: the algorithm requires an initial set of Nb words, |
|
* and each of the Nr rounds requires Nb words of key data. The resulting |
|
* key schedule consists of a linear array of 4-byte words, denoted [wi ], |
|
* with i in the range 0 <= i < Nb(Nr + 1). |
|
* |
|
* KeyExpansion(byte key[4*Nk], word w[Nb*(Nr+1)], Nk) |
|
* AES-128 (Nb=4, Nk=4, Nr=10) |
|
* AES-192 (Nb=4, Nk=6, Nr=12) |
|
* AES-256 (Nb=4, Nk=8, Nr=14) |
|
* Note: Nr=Nk+6. |
|
* |
|
* Nb is the number of columns (32-bit words) comprising the State (or |
|
* number of bytes in a block). For AES, Nb=4. |
|
* |
|
* @param key the key to schedule (as an array of 32-bit words). |
|
* @param decrypt true to modify the key schedule to decrypt, false not to. |
|
* |
|
* @return the generated key schedule. |
|
*/ function $ca9d5cba0afae339$var$_expandKey(key, decrypt) { |
|
// copy the key's words to initialize the key schedule |
|
var w = key.slice(0); |
|
/* RotWord() will rotate a word, moving the first byte to the last |
|
byte's position (shifting the other bytes left). |
|
|
|
We will be getting the value of Rcon at i / Nk. 'i' will iterate |
|
from Nk to (Nb * Nr+1). Nk = 4 (4 byte key), Nb = 4 (4 words in |
|
a block), Nr = Nk + 6 (10). Therefore 'i' will iterate from |
|
4 to 44 (exclusive). Each time we iterate 4 times, i / Nk will |
|
increase by 1. We use a counter iNk to keep track of this. |
|
*/ // go through the rounds expanding the key |
|
var temp, iNk = 1; |
|
var Nk = w.length; |
|
var Nr1 = Nk + 6 + 1; |
|
var end = $ca9d5cba0afae339$var$Nb * Nr1; |
|
for(var i = Nk; i < end; ++i){ |
|
temp = w[i - 1]; |
|
if (i % Nk === 0) { |
|
// temp = SubWord(RotWord(temp)) ^ Rcon[i / Nk] |
|
temp = $ca9d5cba0afae339$var$sbox[temp >>> 16 & 255] << 24 ^ $ca9d5cba0afae339$var$sbox[temp >>> 8 & 255] << 16 ^ $ca9d5cba0afae339$var$sbox[temp & 255] << 8 ^ $ca9d5cba0afae339$var$sbox[temp >>> 24] ^ $ca9d5cba0afae339$var$rcon[iNk] << 24; |
|
iNk++; |
|
} else if (Nk > 6 && i % Nk === 4) // temp = SubWord(temp) |
|
temp = $ca9d5cba0afae339$var$sbox[temp >>> 24] << 24 ^ $ca9d5cba0afae339$var$sbox[temp >>> 16 & 255] << 16 ^ $ca9d5cba0afae339$var$sbox[temp >>> 8 & 255] << 8 ^ $ca9d5cba0afae339$var$sbox[temp & 255]; |
|
w[i] = w[i - Nk] ^ temp; |
|
} |
|
/* When we are updating a cipher block we always use the code path for |
|
encryption whether we are decrypting or not (to shorten code and |
|
simplify the generation of look up tables). However, because there |
|
are differences in the decryption algorithm, other than just swapping |
|
in different look up tables, we must transform our key schedule to |
|
account for these changes: |
|
|
|
1. The decryption algorithm gets its key rounds in reverse order. |
|
2. The decryption algorithm adds the round key before mixing columns |
|
instead of afterwards. |
|
|
|
We don't need to modify our key schedule to handle the first case, |
|
we can just traverse the key schedule in reverse order when decrypting. |
|
|
|
The second case requires a little work. |
|
|
|
The tables we built for performing rounds will take an input and then |
|
perform SubBytes() and MixColumns() or, for the decrypt version, |
|
InvSubBytes() and InvMixColumns(). But the decrypt algorithm requires |
|
us to AddRoundKey() before InvMixColumns(). This means we'll need to |
|
apply some transformations to the round key to inverse-mix its columns |
|
so they'll be correct for moving AddRoundKey() to after the state has |
|
had its columns inverse-mixed. |
|
|
|
To inverse-mix the columns of the state when we're decrypting we use a |
|
lookup table that will apply InvSubBytes() and InvMixColumns() at the |
|
same time. However, the round key's bytes are not inverse-substituted |
|
in the decryption algorithm. To get around this problem, we can first |
|
substitute the bytes in the round key so that when we apply the |
|
transformation via the InvSubBytes()+InvMixColumns() table, it will |
|
undo our substitution leaving us with the original value that we |
|
want -- and then inverse-mix that value. |
|
|
|
This change will correctly alter our key schedule so that we can XOR |
|
each round key with our already transformed decryption state. This |
|
allows us to use the same code path as the encryption algorithm. |
|
|
|
We make one more change to the decryption key. Since the decryption |
|
algorithm runs in reverse from the encryption algorithm, we reverse |
|
the order of the round keys to avoid having to iterate over the key |
|
schedule backwards when running the encryption algorithm later in |
|
decryption mode. In addition to reversing the order of the round keys, |
|
we also swap each round key's 2nd and 4th rows. See the comments |
|
section where rounds are performed for more details about why this is |
|
done. These changes are done inline with the other substitution |
|
described above. |
|
*/ if (decrypt) { |
|
var tmp; |
|
var m0 = $ca9d5cba0afae339$var$imix[0]; |
|
var m1 = $ca9d5cba0afae339$var$imix[1]; |
|
var m2 = $ca9d5cba0afae339$var$imix[2]; |
|
var m3 = $ca9d5cba0afae339$var$imix[3]; |
|
var wnew = w.slice(0); |
|
end = w.length; |
|
for(var i = 0, wi = end - $ca9d5cba0afae339$var$Nb; i < end; i += $ca9d5cba0afae339$var$Nb, wi -= $ca9d5cba0afae339$var$Nb){ |
|
// do not sub the first or last round key (round keys are Nb |
|
// words) as no column mixing is performed before they are added, |
|
// but do change the key order |
|
if (i === 0 || i === end - $ca9d5cba0afae339$var$Nb) { |
|
wnew[i] = w[wi]; |
|
wnew[i + 1] = w[wi + 3]; |
|
wnew[i + 2] = w[wi + 2]; |
|
wnew[i + 3] = w[wi + 1]; |
|
} else // substitute each round key byte because the inverse-mix |
|
// table will inverse-substitute it (effectively cancel the |
|
// substitution because round key bytes aren't sub'd in |
|
// decryption mode) and swap indexes 3 and 1 |
|
for(var n = 0; n < $ca9d5cba0afae339$var$Nb; ++n){ |
|
tmp = w[wi + n]; |
|
wnew[i + (3 & -n)] = m0[$ca9d5cba0afae339$var$sbox[tmp >>> 24]] ^ m1[$ca9d5cba0afae339$var$sbox[tmp >>> 16 & 255]] ^ m2[$ca9d5cba0afae339$var$sbox[tmp >>> 8 & 255]] ^ m3[$ca9d5cba0afae339$var$sbox[tmp & 255]]; |
|
} |
|
} |
|
w = wnew; |
|
} |
|
return w; |
|
} |
|
/** |
|
* Updates a single block (16 bytes) using AES. The update will either |
|
* encrypt or decrypt the block. |
|
* |
|
* @param w the key schedule. |
|
* @param input the input block (an array of 32-bit words). |
|
* @param output the updated output block. |
|
* @param decrypt true to decrypt the block, false to encrypt it. |
|
*/ function $ca9d5cba0afae339$var$_updateBlock(w, input, output, decrypt) { |
|
/* |
|
Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)]) |
|
begin |
|
byte state[4,Nb] |
|
state = in |
|
AddRoundKey(state, w[0, Nb-1]) |
|
for round = 1 step 1 to Nr-1 |
|
SubBytes(state) |
|
ShiftRows(state) |
|
MixColumns(state) |
|
AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) |
|
end for |
|
SubBytes(state) |
|
ShiftRows(state) |
|
AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) |
|
out = state |
|
end |
|
|
|
InvCipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)]) |
|
begin |
|
byte state[4,Nb] |
|
state = in |
|
AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) |
|
for round = Nr-1 step -1 downto 1 |
|
InvShiftRows(state) |
|
InvSubBytes(state) |
|
AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) |
|
InvMixColumns(state) |
|
end for |
|
InvShiftRows(state) |
|
InvSubBytes(state) |
|
AddRoundKey(state, w[0, Nb-1]) |
|
out = state |
|
end |
|
*/ // Encrypt: AddRoundKey(state, w[0, Nb-1]) |
|
// Decrypt: AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) |
|
var Nr = w.length / 4 - 1; |
|
var m0, m1, m2, m3, sub; |
|
if (decrypt) { |
|
m0 = $ca9d5cba0afae339$var$imix[0]; |
|
m1 = $ca9d5cba0afae339$var$imix[1]; |
|
m2 = $ca9d5cba0afae339$var$imix[2]; |
|
m3 = $ca9d5cba0afae339$var$imix[3]; |
|
sub = $ca9d5cba0afae339$var$isbox; |
|
} else { |
|
m0 = $ca9d5cba0afae339$var$mix[0]; |
|
m1 = $ca9d5cba0afae339$var$mix[1]; |
|
m2 = $ca9d5cba0afae339$var$mix[2]; |
|
m3 = $ca9d5cba0afae339$var$mix[3]; |
|
sub = $ca9d5cba0afae339$var$sbox; |
|
} |
|
var a, b, c, d, a2, b2, c2; |
|
a = input[0] ^ w[0]; |
|
b = input[decrypt ? 3 : 1] ^ w[1]; |
|
c = input[2] ^ w[2]; |
|
d = input[decrypt ? 1 : 3] ^ w[3]; |
|
var i = 3; |
|
/* In order to share code we follow the encryption algorithm when both |
|
encrypting and decrypting. To account for the changes required in the |
|
decryption algorithm, we use different lookup tables when decrypting |
|
and use a modified key schedule to account for the difference in the |
|
order of transformations applied when performing rounds. We also get |
|
key rounds in reverse order (relative to encryption). */ for(var round = 1; round < Nr; ++round){ |
|
/* As described above, we'll be using table lookups to perform the |
|
column mixing. Each column is stored as a word in the state (the |
|
array 'input' has one column as a word at each index). In order to |
|
mix a column, we perform these transformations on each row in c, |
|
which is 1 byte in each word. The new column for c0 is c'0: |
|
|
|
m0 m1 m2 m3 |
|
r0,c'0 = 2*r0,c0 + 3*r1,c0 + 1*r2,c0 + 1*r3,c0 |
|
r1,c'0 = 1*r0,c0 + 2*r1,c0 + 3*r2,c0 + 1*r3,c0 |
|
r2,c'0 = 1*r0,c0 + 1*r1,c0 + 2*r2,c0 + 3*r3,c0 |
|
r3,c'0 = 3*r0,c0 + 1*r1,c0 + 1*r2,c0 + 2*r3,c0 |
|
|
|
So using mix tables where c0 is a word with r0 being its upper |
|
8 bits and r3 being its lower 8 bits: |
|
|
|
m0[c0 >> 24] will yield this word: [2*r0,1*r0,1*r0,3*r0] |
|
... |
|
m3[c0 & 255] will yield this word: [1*r3,1*r3,3*r3,2*r3] |
|
|
|
Therefore to mix the columns in each word in the state we |
|
do the following (& 255 omitted for brevity): |
|
c'0,r0 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] |
|
c'0,r1 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] |
|
c'0,r2 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] |
|
c'0,r3 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] |
|
|
|
However, before mixing, the algorithm requires us to perform |
|
ShiftRows(). The ShiftRows() transformation cyclically shifts the |
|
last 3 rows of the state over different offsets. The first row |
|
(r = 0) is not shifted. |
|
|
|
s'_r,c = s_r,(c + shift(r, Nb) mod Nb |
|
for 0 < r < 4 and 0 <= c < Nb and |
|
shift(1, 4) = 1 |
|
shift(2, 4) = 2 |
|
shift(3, 4) = 3. |
|
|
|
This causes the first byte in r = 1 to be moved to the end of |
|
the row, the first 2 bytes in r = 2 to be moved to the end of |
|
the row, the first 3 bytes in r = 3 to be moved to the end of |
|
the row: |
|
|
|
r1: [c0 c1 c2 c3] => [c1 c2 c3 c0] |
|
r2: [c0 c1 c2 c3] [c2 c3 c0 c1] |
|
r3: [c0 c1 c2 c3] [c3 c0 c1 c2] |
|
|
|
We can make these substitutions inline with our column mixing to |
|
generate an updated set of equations to produce each word in the |
|
state (note the columns have changed positions): |
|
|
|
c0 c1 c2 c3 => c0 c1 c2 c3 |
|
c0 c1 c2 c3 c1 c2 c3 c0 (cycled 1 byte) |
|
c0 c1 c2 c3 c2 c3 c0 c1 (cycled 2 bytes) |
|
c0 c1 c2 c3 c3 c0 c1 c2 (cycled 3 bytes) |
|
|
|
Therefore: |
|
|
|
c'0 = 2*r0,c0 + 3*r1,c1 + 1*r2,c2 + 1*r3,c3 |
|
c'0 = 1*r0,c0 + 2*r1,c1 + 3*r2,c2 + 1*r3,c3 |
|
c'0 = 1*r0,c0 + 1*r1,c1 + 2*r2,c2 + 3*r3,c3 |
|
c'0 = 3*r0,c0 + 1*r1,c1 + 1*r2,c2 + 2*r3,c3 |
|
|
|
c'1 = 2*r0,c1 + 3*r1,c2 + 1*r2,c3 + 1*r3,c0 |
|
c'1 = 1*r0,c1 + 2*r1,c2 + 3*r2,c3 + 1*r3,c0 |
|
c'1 = 1*r0,c1 + 1*r1,c2 + 2*r2,c3 + 3*r3,c0 |
|
c'1 = 3*r0,c1 + 1*r1,c2 + 1*r2,c3 + 2*r3,c0 |
|
|
|
... and so forth for c'2 and c'3. The important distinction is |
|
that the columns are cycling, with c0 being used with the m0 |
|
map when calculating c0, but c1 being used with the m0 map when |
|
calculating c1 ... and so forth. |
|
|
|
When performing the inverse we transform the mirror image and |
|
skip the bottom row, instead of the top one, and move upwards: |
|
|
|
c3 c2 c1 c0 => c0 c3 c2 c1 (cycled 3 bytes) *same as encryption |
|
c3 c2 c1 c0 c1 c0 c3 c2 (cycled 2 bytes) |
|
c3 c2 c1 c0 c2 c1 c0 c3 (cycled 1 byte) *same as encryption |
|
c3 c2 c1 c0 c3 c2 c1 c0 |
|
|
|
If you compare the resulting matrices for ShiftRows()+MixColumns() |
|
and for InvShiftRows()+InvMixColumns() the 2nd and 4th columns are |
|
different (in encrypt mode vs. decrypt mode). So in order to use |
|
the same code to handle both encryption and decryption, we will |
|
need to do some mapping. |
|
|
|
If in encryption mode we let a=c0, b=c1, c=c2, d=c3, and r<N> be |
|
a row number in the state, then the resulting matrix in encryption |
|
mode for applying the above transformations would be: |
|
|
|
r1: a b c d |
|
r2: b c d a |
|
r3: c d a b |
|
r4: d a b c |
|
|
|
If we did the same in decryption mode we would get: |
|
|
|
r1: a d c b |
|
r2: b a d c |
|
r3: c b a d |
|
r4: d c b a |
|
|
|
If instead we swap d and b (set b=c3 and d=c1), then we get: |
|
|
|
r1: a b c d |
|
r2: d a b c |
|
r3: c d a b |
|
r4: b c d a |
|
|
|
Now the 1st and 3rd rows are the same as the encryption matrix. All |
|
we need to do then to make the mapping exactly the same is to swap |
|
the 2nd and 4th rows when in decryption mode. To do this without |
|
having to do it on each iteration, we swapped the 2nd and 4th rows |
|
in the decryption key schedule. We also have to do the swap above |
|
when we first pull in the input and when we set the final output. */ a2 = m0[a >>> 24] ^ m1[b >>> 16 & 255] ^ m2[c >>> 8 & 255] ^ m3[d & 255] ^ w[++i]; |
|
b2 = m0[b >>> 24] ^ m1[c >>> 16 & 255] ^ m2[d >>> 8 & 255] ^ m3[a & 255] ^ w[++i]; |
|
c2 = m0[c >>> 24] ^ m1[d >>> 16 & 255] ^ m2[a >>> 8 & 255] ^ m3[b & 255] ^ w[++i]; |
|
d = m0[d >>> 24] ^ m1[a >>> 16 & 255] ^ m2[b >>> 8 & 255] ^ m3[c & 255] ^ w[++i]; |
|
a = a2; |
|
b = b2; |
|
c = c2; |
|
} |
|
/* |
|
Encrypt: |
|
SubBytes(state) |
|
ShiftRows(state) |
|
AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) |
|
|
|
Decrypt: |
|
InvShiftRows(state) |
|
InvSubBytes(state) |
|
AddRoundKey(state, w[0, Nb-1]) |
|
*/ // Note: rows are shifted inline |
|
output[0] = sub[a >>> 24] << 24 ^ sub[b >>> 16 & 255] << 16 ^ sub[c >>> 8 & 255] << 8 ^ sub[d & 255] ^ w[++i]; |
|
output[decrypt ? 3 : 1] = sub[b >>> 24] << 24 ^ sub[c >>> 16 & 255] << 16 ^ sub[d >>> 8 & 255] << 8 ^ sub[a & 255] ^ w[++i]; |
|
output[2] = sub[c >>> 24] << 24 ^ sub[d >>> 16 & 255] << 16 ^ sub[a >>> 8 & 255] << 8 ^ sub[b & 255] ^ w[++i]; |
|
output[decrypt ? 1 : 3] = sub[d >>> 24] << 24 ^ sub[a >>> 16 & 255] << 16 ^ sub[b >>> 8 & 255] << 8 ^ sub[c & 255] ^ w[++i]; |
|
} |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* forge.cipher.createCipher('AES-<mode>', key); |
|
* forge.cipher.createDecipher('AES-<mode>', key); |
|
* |
|
* Creates a deprecated AES cipher object. This object's mode will default to |
|
* CBC (cipher-block-chaining). |
|
* |
|
* The key and iv may be given as a string of bytes, an array of bytes, a |
|
* byte buffer, or an array of 32-bit words. |
|
* |
|
* @param options the options to use. |
|
* key the symmetric key to use. |
|
* output the buffer to write to. |
|
* decrypt true for decryption, false for encryption. |
|
* mode the cipher mode to use (default: 'CBC'). |
|
* |
|
* @return the cipher. |
|
*/ function $ca9d5cba0afae339$var$_createCipher(options1) { |
|
options1 = options1 || { |
|
}; |
|
var mode = (options1.mode || 'CBC').toUpperCase(); |
|
var algorithm = 'AES-' + mode; |
|
var cipher; |
|
if (options1.decrypt) cipher = $iGlOy.cipher.createDecipher(algorithm, options1.key); |
|
else cipher = $iGlOy.cipher.createCipher(algorithm, options1.key); |
|
// backwards compatible start API |
|
var start = cipher.start; |
|
cipher.start = function(iv, options) { |
|
// backwards compatibility: support second arg as output buffer |
|
var output = null; |
|
if (options instanceof $iGlOy.util.ByteBuffer) { |
|
output = options; |
|
options = { |
|
}; |
|
} |
|
options = options || { |
|
}; |
|
options.output = output; |
|
options.iv = iv; |
|
start.call(cipher, options); |
|
}; |
|
return cipher; |
|
} |
|
|
|
|
|
var $48103dfbc323e2e4$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
var $e55982d45da68b81$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
var $579f29a8775d6845$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
var $10862ec0f65326f9$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
$iGlOy.pki = $iGlOy.pki || { |
|
}; |
|
var $10862ec0f65326f9$var$oids = $10862ec0f65326f9$exports = $iGlOy.pki.oids = $iGlOy.oids = $iGlOy.oids || { |
|
}; |
|
// set id to name mapping and name to id mapping |
|
function $10862ec0f65326f9$var$_IN(id, name) { |
|
$10862ec0f65326f9$var$oids[id] = name; |
|
$10862ec0f65326f9$var$oids[name] = id; |
|
} |
|
// set id to name mapping only |
|
function $10862ec0f65326f9$var$_I_(id, name) { |
|
$10862ec0f65326f9$var$oids[id] = name; |
|
} |
|
// algorithm OIDs |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.1', 'rsaEncryption'); |
|
// Note: md2 & md4 not implemented |
|
//_IN('1.2.840.113549.1.1.2', 'md2WithRSAEncryption'); |
|
//_IN('1.2.840.113549.1.1.3', 'md4WithRSAEncryption'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.4', 'md5WithRSAEncryption'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.5', 'sha1WithRSAEncryption'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.7', 'RSAES-OAEP'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.8', 'mgf1'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.9', 'pSpecified'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.10', 'RSASSA-PSS'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.11', 'sha256WithRSAEncryption'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.12', 'sha384WithRSAEncryption'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.1.13', 'sha512WithRSAEncryption'); |
|
// Edwards-curve Digital Signature Algorithm (EdDSA) Ed25519 |
|
$10862ec0f65326f9$var$_IN('1.3.101.112', 'EdDSA25519'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.10040.4.3', 'dsa-with-sha1'); |
|
$10862ec0f65326f9$var$_IN('1.3.14.3.2.7', 'desCBC'); |
|
$10862ec0f65326f9$var$_IN('1.3.14.3.2.26', 'sha1'); |
|
// Deprecated equivalent of sha1WithRSAEncryption |
|
$10862ec0f65326f9$var$_IN('1.3.14.3.2.29', 'sha1WithRSASignature'); |
|
$10862ec0f65326f9$var$_IN('2.16.840.1.101.3.4.2.1', 'sha256'); |
|
$10862ec0f65326f9$var$_IN('2.16.840.1.101.3.4.2.2', 'sha384'); |
|
$10862ec0f65326f9$var$_IN('2.16.840.1.101.3.4.2.3', 'sha512'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.2.5', 'md5'); |
|
// pkcs#7 content types |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.7.1', 'data'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.7.2', 'signedData'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.7.3', 'envelopedData'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.7.4', 'signedAndEnvelopedData'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.7.5', 'digestedData'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.7.6', 'encryptedData'); |
|
// pkcs#9 oids |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.1', 'emailAddress'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.2', 'unstructuredName'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.3', 'contentType'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.4', 'messageDigest'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.5', 'signingTime'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.6', 'counterSignature'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.7', 'challengePassword'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.8', 'unstructuredAddress'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.14', 'extensionRequest'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.20', 'friendlyName'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.21', 'localKeyId'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.9.22.1', 'x509Certificate'); |
|
// pkcs#12 safe bags |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.10.1.1', 'keyBag'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.10.1.2', 'pkcs8ShroudedKeyBag'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.10.1.3', 'certBag'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.10.1.4', 'crlBag'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.10.1.5', 'secretBag'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.10.1.6', 'safeContentsBag'); |
|
// password-based-encryption for pkcs#12 |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.5.13', 'pkcs5PBES2'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.5.12', 'pkcs5PBKDF2'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.1.1', 'pbeWithSHAAnd128BitRC4'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.1.2', 'pbeWithSHAAnd40BitRC4'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.1.3', 'pbeWithSHAAnd3-KeyTripleDES-CBC'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.1.4', 'pbeWithSHAAnd2-KeyTripleDES-CBC'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.1.5', 'pbeWithSHAAnd128BitRC2-CBC'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.1.12.1.6', 'pbewithSHAAnd40BitRC2-CBC'); |
|
// hmac OIDs |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.2.7', 'hmacWithSHA1'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.2.8', 'hmacWithSHA224'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.2.9', 'hmacWithSHA256'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.2.10', 'hmacWithSHA384'); |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.2.11', 'hmacWithSHA512'); |
|
// symmetric key algorithm oids |
|
$10862ec0f65326f9$var$_IN('1.2.840.113549.3.7', 'des-EDE3-CBC'); |
|
$10862ec0f65326f9$var$_IN('2.16.840.1.101.3.4.1.2', 'aes128-CBC'); |
|
$10862ec0f65326f9$var$_IN('2.16.840.1.101.3.4.1.22', 'aes192-CBC'); |
|
$10862ec0f65326f9$var$_IN('2.16.840.1.101.3.4.1.42', 'aes256-CBC'); |
|
// certificate issuer/subject OIDs |
|
$10862ec0f65326f9$var$_IN('2.5.4.3', 'commonName'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.4', 'surname'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.5', 'serialNumber'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.6', 'countryName'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.7', 'localityName'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.8', 'stateOrProvinceName'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.9', 'streetAddress'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.10', 'organizationName'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.11', 'organizationalUnitName'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.12', 'title'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.13', 'description'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.15', 'businessCategory'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.17', 'postalCode'); |
|
$10862ec0f65326f9$var$_IN('2.5.4.42', 'givenName'); |
|
$10862ec0f65326f9$var$_IN('1.3.6.1.4.1.311.60.2.1.2', 'jurisdictionOfIncorporationStateOrProvinceName'); |
|
$10862ec0f65326f9$var$_IN('1.3.6.1.4.1.311.60.2.1.3', 'jurisdictionOfIncorporationCountryName'); |
|
// X.509 extension OIDs |
|
$10862ec0f65326f9$var$_IN('2.16.840.1.113730.1.1', 'nsCertType'); |
|
$10862ec0f65326f9$var$_IN('2.16.840.1.113730.1.13', 'nsComment'); // deprecated in theory; still widely used |
|
$10862ec0f65326f9$var$_I_('2.5.29.1', 'authorityKeyIdentifier'); // deprecated, use .35 |
|
$10862ec0f65326f9$var$_I_('2.5.29.2', 'keyAttributes'); // obsolete use .37 or .15 |
|
$10862ec0f65326f9$var$_I_('2.5.29.3', 'certificatePolicies'); // deprecated, use .32 |
|
$10862ec0f65326f9$var$_I_('2.5.29.4', 'keyUsageRestriction'); // obsolete use .37 or .15 |
|
$10862ec0f65326f9$var$_I_('2.5.29.5', 'policyMapping'); // deprecated use .33 |
|
$10862ec0f65326f9$var$_I_('2.5.29.6', 'subtreesConstraint'); // obsolete use .30 |
|
$10862ec0f65326f9$var$_I_('2.5.29.7', 'subjectAltName'); // deprecated use .17 |
|
$10862ec0f65326f9$var$_I_('2.5.29.8', 'issuerAltName'); // deprecated use .18 |
|
$10862ec0f65326f9$var$_I_('2.5.29.9', 'subjectDirectoryAttributes'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.10', 'basicConstraints'); // deprecated use .19 |
|
$10862ec0f65326f9$var$_I_('2.5.29.11', 'nameConstraints'); // deprecated use .30 |
|
$10862ec0f65326f9$var$_I_('2.5.29.12', 'policyConstraints'); // deprecated use .36 |
|
$10862ec0f65326f9$var$_I_('2.5.29.13', 'basicConstraints'); // deprecated use .19 |
|
$10862ec0f65326f9$var$_IN('2.5.29.14', 'subjectKeyIdentifier'); |
|
$10862ec0f65326f9$var$_IN('2.5.29.15', 'keyUsage'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.16', 'privateKeyUsagePeriod'); |
|
$10862ec0f65326f9$var$_IN('2.5.29.17', 'subjectAltName'); |
|
$10862ec0f65326f9$var$_IN('2.5.29.18', 'issuerAltName'); |
|
$10862ec0f65326f9$var$_IN('2.5.29.19', 'basicConstraints'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.20', 'cRLNumber'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.21', 'cRLReason'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.22', 'expirationDate'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.23', 'instructionCode'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.24', 'invalidityDate'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.25', 'cRLDistributionPoints'); // deprecated use .31 |
|
$10862ec0f65326f9$var$_I_('2.5.29.26', 'issuingDistributionPoint'); // deprecated use .28 |
|
$10862ec0f65326f9$var$_I_('2.5.29.27', 'deltaCRLIndicator'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.28', 'issuingDistributionPoint'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.29', 'certificateIssuer'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.30', 'nameConstraints'); |
|
$10862ec0f65326f9$var$_IN('2.5.29.31', 'cRLDistributionPoints'); |
|
$10862ec0f65326f9$var$_IN('2.5.29.32', 'certificatePolicies'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.33', 'policyMappings'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.34', 'policyConstraints'); // deprecated use .36 |
|
$10862ec0f65326f9$var$_IN('2.5.29.35', 'authorityKeyIdentifier'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.36', 'policyConstraints'); |
|
$10862ec0f65326f9$var$_IN('2.5.29.37', 'extKeyUsage'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.46', 'freshestCRL'); |
|
$10862ec0f65326f9$var$_I_('2.5.29.54', 'inhibitAnyPolicy'); |
|
// extKeyUsage purposes |
|
$10862ec0f65326f9$var$_IN('1.3.6.1.4.1.11129.2.4.2', 'timestampList'); |
|
$10862ec0f65326f9$var$_IN('1.3.6.1.5.5.7.1.1', 'authorityInfoAccess'); |
|
$10862ec0f65326f9$var$_IN('1.3.6.1.5.5.7.3.1', 'serverAuth'); |
|
$10862ec0f65326f9$var$_IN('1.3.6.1.5.5.7.3.2', 'clientAuth'); |
|
$10862ec0f65326f9$var$_IN('1.3.6.1.5.5.7.3.3', 'codeSigning'); |
|
$10862ec0f65326f9$var$_IN('1.3.6.1.5.5.7.3.4', 'emailProtection'); |
|
$10862ec0f65326f9$var$_IN('1.3.6.1.5.5.7.3.8', 'timeStamping'); |
|
|
|
|
|
/* ASN.1 API */ var $579f29a8775d6845$var$asn1 = $579f29a8775d6845$exports = $iGlOy.asn1 = $iGlOy.asn1 || { |
|
}; |
|
/** |
|
* ASN.1 classes. |
|
*/ $579f29a8775d6845$var$asn1.Class = { |
|
UNIVERSAL: 0, |
|
APPLICATION: 64, |
|
CONTEXT_SPECIFIC: 128, |
|
PRIVATE: 192 |
|
}; |
|
/** |
|
* ASN.1 types. Not all types are supported by this implementation, only |
|
* those necessary to implement a simple PKI are implemented. |
|
*/ $579f29a8775d6845$var$asn1.Type = { |
|
NONE: 0, |
|
BOOLEAN: 1, |
|
INTEGER: 2, |
|
BITSTRING: 3, |
|
OCTETSTRING: 4, |
|
NULL: 5, |
|
OID: 6, |
|
ODESC: 7, |
|
EXTERNAL: 8, |
|
REAL: 9, |
|
ENUMERATED: 10, |
|
EMBEDDED: 11, |
|
UTF8: 12, |
|
ROID: 13, |
|
SEQUENCE: 16, |
|
SET: 17, |
|
PRINTABLESTRING: 19, |
|
IA5STRING: 22, |
|
UTCTIME: 23, |
|
GENERALIZEDTIME: 24, |
|
BMPSTRING: 30 |
|
}; |
|
/** |
|
* Creates a new asn1 object. |
|
* |
|
* @param tagClass the tag class for the object. |
|
* @param type the data type (tag number) for the object. |
|
* @param constructed true if the asn1 object is in constructed form. |
|
* @param value the value for the object, if it is not constructed. |
|
* @param [options] the options to use: |
|
* [bitStringContents] the plain BIT STRING content including padding |
|
* byte. |
|
* |
|
* @return the asn1 object. |
|
*/ $579f29a8775d6845$var$asn1.create = function(tagClass, type, constructed, value, options) { |
|
/* An asn1 object has a tagClass, a type, a constructed flag, and a |
|
value. The value's type depends on the constructed flag. If |
|
constructed, it will contain a list of other asn1 objects. If not, |
|
it will contain the ASN.1 value as an array of bytes formatted |
|
according to the ASN.1 data type. */ // remove undefined values |
|
if ($iGlOy.util.isArray(value)) { |
|
var tmp = []; |
|
for(var i = 0; i < value.length; ++i)if (value[i] !== undefined) tmp.push(value[i]); |
|
value = tmp; |
|
} |
|
var obj = { |
|
tagClass: tagClass, |
|
type: type, |
|
constructed: constructed, |
|
composed: constructed || $iGlOy.util.isArray(value), |
|
value: value |
|
}; |
|
if (options && 'bitStringContents' in options) { |
|
// TODO: copy byte buffer if it's a buffer not a string |
|
obj.bitStringContents = options.bitStringContents; |
|
// TODO: add readonly flag to avoid this overhead |
|
// save copy to detect changes |
|
obj.original = $579f29a8775d6845$var$asn1.copy(obj); |
|
} |
|
return obj; |
|
}; |
|
/** |
|
* Copies an asn1 object. |
|
* |
|
* @param obj the asn1 object. |
|
* @param [options] copy options: |
|
* [excludeBitStringContents] true to not copy bitStringContents |
|
* |
|
* @return the a copy of the asn1 object. |
|
*/ $579f29a8775d6845$var$asn1.copy = function(obj, options) { |
|
var copy; |
|
if ($iGlOy.util.isArray(obj)) { |
|
copy = []; |
|
for(var i = 0; i < obj.length; ++i)copy.push($579f29a8775d6845$var$asn1.copy(obj[i], options)); |
|
return copy; |
|
} |
|
if (typeof obj === 'string') // TODO: copy byte buffer if it's a buffer not a string |
|
return obj; |
|
copy = { |
|
tagClass: obj.tagClass, |
|
type: obj.type, |
|
constructed: obj.constructed, |
|
composed: obj.composed, |
|
value: $579f29a8775d6845$var$asn1.copy(obj.value, options) |
|
}; |
|
if (options && !options.excludeBitStringContents) // TODO: copy byte buffer if it's a buffer not a string |
|
copy.bitStringContents = obj.bitStringContents; |
|
return copy; |
|
}; |
|
/** |
|
* Compares asn1 objects for equality. |
|
* |
|
* Note this function does not run in constant time. |
|
* |
|
* @param obj1 the first asn1 object. |
|
* @param obj2 the second asn1 object. |
|
* @param [options] compare options: |
|
* [includeBitStringContents] true to compare bitStringContents |
|
* |
|
* @return true if the asn1 objects are equal. |
|
*/ $579f29a8775d6845$var$asn1.equals = function(obj1, obj2, options) { |
|
if ($iGlOy.util.isArray(obj1)) { |
|
if (!$iGlOy.util.isArray(obj2)) return false; |
|
if (obj1.length !== obj2.length) return false; |
|
for(var i = 0; i < obj1.length; ++i){ |
|
if (!$579f29a8775d6845$var$asn1.equals(obj1[i], obj2[i])) return false; |
|
} |
|
return true; |
|
} |
|
if (typeof obj1 !== typeof obj2) return false; |
|
if (typeof obj1 === 'string') return obj1 === obj2; |
|
var equal = obj1.tagClass === obj2.tagClass && obj1.type === obj2.type && obj1.constructed === obj2.constructed && obj1.composed === obj2.composed && $579f29a8775d6845$var$asn1.equals(obj1.value, obj2.value); |
|
if (options && options.includeBitStringContents) equal = equal && obj1.bitStringContents === obj2.bitStringContents; |
|
return equal; |
|
}; |
|
/** |
|
* Gets the length of a BER-encoded ASN.1 value. |
|
* |
|
* In case the length is not specified, undefined is returned. |
|
* |
|
* @param b the BER-encoded ASN.1 byte buffer, starting with the first |
|
* length byte. |
|
* |
|
* @return the length of the BER-encoded ASN.1 value or undefined. |
|
*/ $579f29a8775d6845$var$asn1.getBerValueLength = function(b) { |
|
// TODO: move this function and related DER/BER functions to a der.js |
|
// file; better abstract ASN.1 away from der/ber. |
|
var b2 = b.getByte(); |
|
if (b2 === 128) return undefined; |
|
// see if the length is "short form" or "long form" (bit 8 set) |
|
var length; |
|
var longForm = b2 & 128; |
|
if (!longForm) // length is just the first byte |
|
length = b2; |
|
else // the number of bytes the length is specified in bits 7 through 1 |
|
// and each length byte is in big-endian base-256 |
|
length = b.getInt((b2 & 127) << 3); |
|
return length; |
|
}; |
|
/** |
|
* Check if the byte buffer has enough bytes. Throws an Error if not. |
|
* |
|
* @param bytes the byte buffer to parse from. |
|
* @param remaining the bytes remaining in the current parsing state. |
|
* @param n the number of bytes the buffer must have. |
|
*/ function $579f29a8775d6845$var$_checkBufferLength(bytes, remaining, n) { |
|
if (n > remaining) { |
|
var error = new Error('Too few bytes to parse DER.'); |
|
error.available = bytes.length(); |
|
error.remaining = remaining; |
|
error.requested = n; |
|
throw error; |
|
} |
|
} |
|
/** |
|
* Gets the length of a BER-encoded ASN.1 value. |
|
* |
|
* In case the length is not specified, undefined is returned. |
|
* |
|
* @param bytes the byte buffer to parse from. |
|
* @param remaining the bytes remaining in the current parsing state. |
|
* |
|
* @return the length of the BER-encoded ASN.1 value or undefined. |
|
*/ var $579f29a8775d6845$var$_getValueLength = function(bytes, remaining) { |
|
// TODO: move this function and related DER/BER functions to a der.js |
|
// file; better abstract ASN.1 away from der/ber. |
|
// fromDer already checked that this byte exists |
|
var b2 = bytes.getByte(); |
|
remaining--; |
|
if (b2 === 128) return undefined; |
|
// see if the length is "short form" or "long form" (bit 8 set) |
|
var length; |
|
var longForm = b2 & 128; |
|
if (!longForm) // length is just the first byte |
|
length = b2; |
|
else { |
|
// the number of bytes the length is specified in bits 7 through 1 |
|
// and each length byte is in big-endian base-256 |
|
var longFormBytes = b2 & 127; |
|
$579f29a8775d6845$var$_checkBufferLength(bytes, remaining, longFormBytes); |
|
length = bytes.getInt(longFormBytes << 3); |
|
} |
|
// FIXME: this will only happen for 32 bit getInt with high bit set |
|
if (length < 0) throw new Error('Negative length: ' + length); |
|
return length; |
|
}; |
|
/** |
|
* Parses an asn1 object from a byte buffer in DER format. |
|
* |
|
* @param bytes the byte buffer to parse from. |
|
* @param [strict] true to be strict when checking value lengths, false to |
|
* allow truncated values (default: true). |
|
* @param [options] object with options or boolean strict flag |
|
* [strict] true to be strict when checking value lengths, false to |
|
* allow truncated values (default: true). |
|
* [decodeBitStrings] true to attempt to decode the content of |
|
* BIT STRINGs (not OCTET STRINGs) using strict mode. Note that |
|
* without schema support to understand the data context this can |
|
* erroneously decode values that happen to be valid ASN.1. This |
|
* flag will be deprecated or removed as soon as schema support is |
|
* available. (default: true) |
|
* |
|
* @return the parsed asn1 object. |
|
*/ $579f29a8775d6845$var$asn1.fromDer = function(bytes, options) { |
|
if (options === undefined) options = { |
|
strict: true, |
|
decodeBitStrings: true |
|
}; |
|
if (typeof options === 'boolean') options = { |
|
strict: options, |
|
decodeBitStrings: true |
|
}; |
|
if (!('strict' in options)) options.strict = true; |
|
if (!('decodeBitStrings' in options)) options.decodeBitStrings = true; |
|
// wrap in buffer if needed |
|
if (typeof bytes === 'string') bytes = $iGlOy.util.createBuffer(bytes); |
|
return $579f29a8775d6845$var$_fromDer(bytes, bytes.length(), 0, options); |
|
}; |
|
/** |
|
* Internal function to parse an asn1 object from a byte buffer in DER format. |
|
* |
|
* @param bytes the byte buffer to parse from. |
|
* @param remaining the number of bytes remaining for this chunk. |
|
* @param depth the current parsing depth. |
|
* @param options object with same options as fromDer(). |
|
* |
|
* @return the parsed asn1 object. |
|
*/ function $579f29a8775d6845$var$_fromDer(bytes, remaining, depth, options) { |
|
// temporary storage for consumption calculations |
|
var start; |
|
// minimum length for ASN.1 DER structure is 2 |
|
$579f29a8775d6845$var$_checkBufferLength(bytes, remaining, 2); |
|
// get the first byte |
|
var b1 = bytes.getByte(); |
|
// consumed one byte |
|
remaining--; |
|
// get the tag class |
|
var tagClass = b1 & 192; |
|
// get the type (bits 1-5) |
|
var type = b1 & 31; |
|
// get the variable value length and adjust remaining bytes |
|
start = bytes.length(); |
|
var length = $579f29a8775d6845$var$_getValueLength(bytes, remaining); |
|
remaining -= start - bytes.length(); |
|
// ensure there are enough bytes to get the value |
|
if (length !== undefined && length > remaining) { |
|
if (options.strict) { |
|
var error = new Error('Too few bytes to read ASN.1 value.'); |
|
error.available = bytes.length(); |
|
error.remaining = remaining; |
|
error.requested = length; |
|
throw error; |
|
} |
|
// Note: be lenient with truncated values and use remaining state bytes |
|
length = remaining; |
|
} |
|
// value storage |
|
var value; |
|
// possible BIT STRING contents storage |
|
var bitStringContents; |
|
// constructed flag is bit 6 (32 = 0x20) of the first byte |
|
var constructed = (b1 & 32) === 32; |
|
if (constructed) { |
|
// parse child asn1 objects from the value |
|
value = []; |
|
if (length === undefined) // asn1 object of indefinite length, read until end tag |
|
for(;;){ |
|
$579f29a8775d6845$var$_checkBufferLength(bytes, remaining, 2); |
|
if (bytes.bytes(2) === String.fromCharCode(0, 0)) { |
|
bytes.getBytes(2); |
|
remaining -= 2; |
|
break; |
|
} |
|
start = bytes.length(); |
|
value.push($579f29a8775d6845$var$_fromDer(bytes, remaining, depth + 1, options)); |
|
remaining -= start - bytes.length(); |
|
} |
|
else // parsing asn1 object of definite length |
|
while(length > 0){ |
|
start = bytes.length(); |
|
value.push($579f29a8775d6845$var$_fromDer(bytes, length, depth + 1, options)); |
|
remaining -= start - bytes.length(); |
|
length -= start - bytes.length(); |
|
} |
|
} |
|
// if a BIT STRING, save the contents including padding |
|
if (value === undefined && tagClass === $579f29a8775d6845$var$asn1.Class.UNIVERSAL && type === $579f29a8775d6845$var$asn1.Type.BITSTRING) bitStringContents = bytes.bytes(length); |
|
// determine if a non-constructed value should be decoded as a composed |
|
// value that contains other ASN.1 objects. BIT STRINGs (and OCTET STRINGs) |
|
// can be used this way. |
|
if (value === undefined && options.decodeBitStrings && tagClass === $579f29a8775d6845$var$asn1.Class.UNIVERSAL && type === $579f29a8775d6845$var$asn1.Type.BITSTRING /*|| type === asn1.Type.OCTETSTRING*/ && length > 1) { |
|
// save read position |
|
var savedRead = bytes.read; |
|
var savedRemaining = remaining; |
|
var unused = 0; |
|
if (type === $579f29a8775d6845$var$asn1.Type.BITSTRING) { |
|
/* The first octet gives the number of bits by which the length of the |
|
bit string is less than the next multiple of eight (this is called |
|
the "number of unused bits"). |
|
|
|
The second and following octets give the value of the bit string |
|
converted to an octet string. */ $579f29a8775d6845$var$_checkBufferLength(bytes, remaining, 1); |
|
unused = bytes.getByte(); |
|
remaining--; |
|
} |
|
// if all bits are used, maybe the BIT/OCTET STRING holds ASN.1 objs |
|
if (unused === 0) try { |
|
// attempt to parse child asn1 object from the value |
|
// (stored in array to signal composed value) |
|
start = bytes.length(); |
|
var subOptions = { |
|
// enforce strict mode to avoid parsing ASN.1 from plain data |
|
verbose: options.verbose, |
|
strict: true, |
|
decodeBitStrings: true |
|
}; |
|
var composed = $579f29a8775d6845$var$_fromDer(bytes, remaining, depth + 1, subOptions); |
|
var used = start - bytes.length(); |
|
remaining -= used; |
|
if (type == $579f29a8775d6845$var$asn1.Type.BITSTRING) used++; |
|
// if the data all decoded and the class indicates UNIVERSAL or |
|
// CONTEXT_SPECIFIC then assume we've got an encapsulated ASN.1 object |
|
var tc = composed.tagClass; |
|
if (used === length && (tc === $579f29a8775d6845$var$asn1.Class.UNIVERSAL || tc === $579f29a8775d6845$var$asn1.Class.CONTEXT_SPECIFIC)) value = [ |
|
composed |
|
]; |
|
} catch (ex) { |
|
} |
|
if (value === undefined) { |
|
// restore read position |
|
bytes.read = savedRead; |
|
remaining = savedRemaining; |
|
} |
|
} |
|
if (value === undefined) { |
|
// asn1 not constructed or composed, get raw value |
|
// TODO: do DER to OID conversion and vice-versa in .toDer? |
|
if (length === undefined) { |
|
if (options.strict) throw new Error('Non-constructed ASN.1 object of indefinite length.'); |
|
// be lenient and use remaining state bytes |
|
length = remaining; |
|
} |
|
if (type === $579f29a8775d6845$var$asn1.Type.BMPSTRING) { |
|
value = ''; |
|
for(; length > 0; length -= 2){ |
|
$579f29a8775d6845$var$_checkBufferLength(bytes, remaining, 2); |
|
value += String.fromCharCode(bytes.getInt16()); |
|
remaining -= 2; |
|
} |
|
} else value = bytes.getBytes(length); |
|
} |
|
// add BIT STRING contents if available |
|
var asn1Options = bitStringContents === undefined ? null : { |
|
bitStringContents: bitStringContents |
|
}; |
|
// create and return asn1 object |
|
return $579f29a8775d6845$var$asn1.create(tagClass, type, constructed, value, asn1Options); |
|
} |
|
/** |
|
* Converts the given asn1 object to a buffer of bytes in DER format. |
|
* |
|
* @param asn1 the asn1 object to convert to bytes. |
|
* |
|
* @return the buffer of bytes. |
|
*/ $579f29a8775d6845$var$asn1.toDer = function(obj) { |
|
var bytes = $iGlOy.util.createBuffer(); |
|
// build the first byte |
|
var b1 = obj.tagClass | obj.type; |
|
// for storing the ASN.1 value |
|
var value = $iGlOy.util.createBuffer(); |
|
// use BIT STRING contents if available and data not changed |
|
var useBitStringContents = false; |
|
if ('bitStringContents' in obj) { |
|
useBitStringContents = true; |
|
if (obj.original) useBitStringContents = $579f29a8775d6845$var$asn1.equals(obj, obj.original); |
|
} |
|
if (useBitStringContents) value.putBytes(obj.bitStringContents); |
|
else if (obj.composed) { |
|
// if composed, use each child asn1 object's DER bytes as value |
|
// turn on 6th bit (0x20 = 32) to indicate asn1 is constructed |
|
// from other asn1 objects |
|
if (obj.constructed) b1 |= 32; |
|
else // type is a bit string, add unused bits of 0x00 |
|
value.putByte(0); |
|
// add all of the child DER bytes together |
|
for(var i = 0; i < obj.value.length; ++i)if (obj.value[i] !== undefined) value.putBuffer($579f29a8775d6845$var$asn1.toDer(obj.value[i])); |
|
} else { |
|
// use asn1.value directly |
|
if (obj.type === $579f29a8775d6845$var$asn1.Type.BMPSTRING) for(var i = 0; i < obj.value.length; ++i)value.putInt16(obj.value.charCodeAt(i)); |
|
else // ensure integer is minimally-encoded |
|
// TODO: should all leading bytes be stripped vs just one? |
|
// .. ex '00 00 01' => '01'? |
|
if (obj.type === $579f29a8775d6845$var$asn1.Type.INTEGER && obj.value.length > 1 && (obj.value.charCodeAt(0) === 0 && (obj.value.charCodeAt(1) & 128) === 0 || obj.value.charCodeAt(0) === 255 && (obj.value.charCodeAt(1) & 128) === 128)) value.putBytes(obj.value.substr(1)); |
|
else value.putBytes(obj.value); |
|
} |
|
// add tag byte |
|
bytes.putByte(b1); |
|
// use "short form" encoding |
|
if (value.length() <= 127) // one byte describes the length |
|
// bit 8 = 0 and bits 7-1 = length |
|
bytes.putByte(value.length() & 127); |
|
else { |
|
// use "long form" encoding |
|
// 2 to 127 bytes describe the length |
|
// first byte: bit 8 = 1 and bits 7-1 = # of additional bytes |
|
// other bytes: length in base 256, big-endian |
|
var len = value.length(); |
|
var lenBytes = ''; |
|
do { |
|
lenBytes += String.fromCharCode(len & 255); |
|
len = len >>> 8; |
|
}while (len > 0) |
|
// set first byte to # bytes used to store the length and turn on |
|
// bit 8 to indicate long-form length is used |
|
bytes.putByte(lenBytes.length | 128); |
|
// concatenate length bytes in reverse since they were generated |
|
// little endian and we need big endian |
|
for(var i = lenBytes.length - 1; i >= 0; --i)bytes.putByte(lenBytes.charCodeAt(i)); |
|
} |
|
// concatenate value bytes |
|
bytes.putBuffer(value); |
|
return bytes; |
|
}; |
|
/** |
|
* Converts an OID dot-separated string to a byte buffer. The byte buffer |
|
* contains only the DER-encoded value, not any tag or length bytes. |
|
* |
|
* @param oid the OID dot-separated string. |
|
* |
|
* @return the byte buffer. |
|
*/ $579f29a8775d6845$var$asn1.oidToDer = function(oid) { |
|
// split OID into individual values |
|
var values = oid.split('.'); |
|
var bytes = $iGlOy.util.createBuffer(); |
|
// first byte is 40 * value1 + value2 |
|
bytes.putByte(40 * parseInt(values[0], 10) + parseInt(values[1], 10)); |
|
// other bytes are each value in base 128 with 8th bit set except for |
|
// the last byte for each value |
|
var last, valueBytes, value, b; |
|
for(var i = 2; i < values.length; ++i){ |
|
// produce value bytes in reverse because we don't know how many |
|
// bytes it will take to store the value |
|
last = true; |
|
valueBytes = []; |
|
value = parseInt(values[i], 10); |
|
do { |
|
b = value & 127; |
|
value = value >>> 7; |
|
// if value is not last, then turn on 8th bit |
|
if (!last) b |= 128; |
|
valueBytes.push(b); |
|
last = false; |
|
}while (value > 0) |
|
// add value bytes in reverse (needs to be in big endian) |
|
for(var n = valueBytes.length - 1; n >= 0; --n)bytes.putByte(valueBytes[n]); |
|
} |
|
return bytes; |
|
}; |
|
/** |
|
* Converts a DER-encoded byte buffer to an OID dot-separated string. The |
|
* byte buffer should contain only the DER-encoded value, not any tag or |
|
* length bytes. |
|
* |
|
* @param bytes the byte buffer. |
|
* |
|
* @return the OID dot-separated string. |
|
*/ $579f29a8775d6845$var$asn1.derToOid = function(bytes) { |
|
var oid; |
|
// wrap in buffer if needed |
|
if (typeof bytes === 'string') bytes = $iGlOy.util.createBuffer(bytes); |
|
// first byte is 40 * value1 + value2 |
|
var b = bytes.getByte(); |
|
oid = Math.floor(b / 40) + '.' + b % 40; |
|
// other bytes are each value in base 128 with 8th bit set except for |
|
// the last byte for each value |
|
var value = 0; |
|
while(bytes.length() > 0){ |
|
b = bytes.getByte(); |
|
value = value << 7; |
|
// not the last byte for the value |
|
if (b & 128) value += b & 127; |
|
else { |
|
// last byte |
|
oid += '.' + (value + b); |
|
value = 0; |
|
} |
|
} |
|
return oid; |
|
}; |
|
/** |
|
* Converts a UTCTime value to a date. |
|
* |
|
* Note: GeneralizedTime has 4 digits for the year and is used for X.509 |
|
* dates past 2049. Parsing that structure hasn't been implemented yet. |
|
* |
|
* @param utc the UTCTime value to convert. |
|
* |
|
* @return the date. |
|
*/ $579f29a8775d6845$var$asn1.utcTimeToDate = function(utc) { |
|
/* The following formats can be used: |
|
|
|
YYMMDDhhmmZ |
|
YYMMDDhhmm+hh'mm' |
|
YYMMDDhhmm-hh'mm' |
|
YYMMDDhhmmssZ |
|
YYMMDDhhmmss+hh'mm' |
|
YYMMDDhhmmss-hh'mm' |
|
|
|
Where: |
|
|
|
YY is the least significant two digits of the year |
|
MM is the month (01 to 12) |
|
DD is the day (01 to 31) |
|
hh is the hour (00 to 23) |
|
mm are the minutes (00 to 59) |
|
ss are the seconds (00 to 59) |
|
Z indicates that local time is GMT, + indicates that local time is |
|
later than GMT, and - indicates that local time is earlier than GMT |
|
hh' is the absolute value of the offset from GMT in hours |
|
mm' is the absolute value of the offset from GMT in minutes */ var date = new Date(); |
|
// if YY >= 50 use 19xx, if YY < 50 use 20xx |
|
var year = parseInt(utc.substr(0, 2), 10); |
|
year = year >= 50 ? 1900 + year : 2000 + year; |
|
var MM = parseInt(utc.substr(2, 2), 10) - 1; // use 0-11 for month |
|
var DD = parseInt(utc.substr(4, 2), 10); |
|
var hh = parseInt(utc.substr(6, 2), 10); |
|
var mm = parseInt(utc.substr(8, 2), 10); |
|
var ss = 0; |
|
// not just YYMMDDhhmmZ |
|
if (utc.length > 11) { |
|
// get character after minutes |
|
var c = utc.charAt(10); |
|
var end = 10; |
|
// see if seconds are present |
|
if (c !== '+' && c !== '-') { |
|
// get seconds |
|
ss = parseInt(utc.substr(10, 2), 10); |
|
end += 2; |
|
} |
|
} |
|
// update date |
|
date.setUTCFullYear(year, MM, DD); |
|
date.setUTCHours(hh, mm, ss, 0); |
|
if (end) { |
|
// get +/- after end of time |
|
c = utc.charAt(end); |
|
if (c === '+' || c === '-') { |
|
// get hours+minutes offset |
|
var hhoffset = parseInt(utc.substr(end + 1, 2), 10); |
|
var mmoffset = parseInt(utc.substr(end + 4, 2), 10); |
|
// calculate offset in milliseconds |
|
var offset = hhoffset * 60 + mmoffset; |
|
offset *= 60000; |
|
// apply offset |
|
if (c === '+') date.setTime(+date - offset); |
|
else date.setTime(+date + offset); |
|
} |
|
} |
|
return date; |
|
}; |
|
/** |
|
* Converts a GeneralizedTime value to a date. |
|
* |
|
* @param gentime the GeneralizedTime value to convert. |
|
* |
|
* @return the date. |
|
*/ $579f29a8775d6845$var$asn1.generalizedTimeToDate = function(gentime) { |
|
/* The following formats can be used: |
|
|
|
YYYYMMDDHHMMSS |
|
YYYYMMDDHHMMSS.fff |
|
YYYYMMDDHHMMSSZ |
|
YYYYMMDDHHMMSS.fffZ |
|
YYYYMMDDHHMMSS+hh'mm' |
|
YYYYMMDDHHMMSS.fff+hh'mm' |
|
YYYYMMDDHHMMSS-hh'mm' |
|
YYYYMMDDHHMMSS.fff-hh'mm' |
|
|
|
Where: |
|
|
|
YYYY is the year |
|
MM is the month (01 to 12) |
|
DD is the day (01 to 31) |
|
hh is the hour (00 to 23) |
|
mm are the minutes (00 to 59) |
|
ss are the seconds (00 to 59) |
|
.fff is the second fraction, accurate to three decimal places |
|
Z indicates that local time is GMT, + indicates that local time is |
|
later than GMT, and - indicates that local time is earlier than GMT |
|
hh' is the absolute value of the offset from GMT in hours |
|
mm' is the absolute value of the offset from GMT in minutes */ var date = new Date(); |
|
var YYYY = parseInt(gentime.substr(0, 4), 10); |
|
var MM = parseInt(gentime.substr(4, 2), 10) - 1; // use 0-11 for month |
|
var DD = parseInt(gentime.substr(6, 2), 10); |
|
var hh = parseInt(gentime.substr(8, 2), 10); |
|
var mm = parseInt(gentime.substr(10, 2), 10); |
|
var ss = parseInt(gentime.substr(12, 2), 10); |
|
var fff = 0; |
|
var offset = 0; |
|
var isUTC = false; |
|
if (gentime.charAt(gentime.length - 1) === 'Z') isUTC = true; |
|
var end = gentime.length - 5, c = gentime.charAt(end); |
|
if (c === '+' || c === '-') { |
|
// get hours+minutes offset |
|
var hhoffset = parseInt(gentime.substr(end + 1, 2), 10); |
|
var mmoffset = parseInt(gentime.substr(end + 4, 2), 10); |
|
// calculate offset in milliseconds |
|
offset = hhoffset * 60 + mmoffset; |
|
offset *= 60000; |
|
// apply offset |
|
if (c === '+') offset *= -1; |
|
isUTC = true; |
|
} |
|
// check for second fraction |
|
if (gentime.charAt(14) === '.') fff = parseFloat(gentime.substr(14), 10) * 1000; |
|
if (isUTC) { |
|
date.setUTCFullYear(YYYY, MM, DD); |
|
date.setUTCHours(hh, mm, ss, fff); |
|
// apply offset |
|
date.setTime(+date + offset); |
|
} else { |
|
date.setFullYear(YYYY, MM, DD); |
|
date.setHours(hh, mm, ss, fff); |
|
} |
|
return date; |
|
}; |
|
/** |
|
* Converts a date to a UTCTime value. |
|
* |
|
* Note: GeneralizedTime has 4 digits for the year and is used for X.509 |
|
* dates past 2049. Converting to a GeneralizedTime hasn't been |
|
* implemented yet. |
|
* |
|
* @param date the date to convert. |
|
* |
|
* @return the UTCTime value. |
|
*/ $579f29a8775d6845$var$asn1.dateToUtcTime = function(date) { |
|
// TODO: validate; currently assumes proper format |
|
if (typeof date === 'string') return date; |
|
var rval = ''; |
|
// create format YYMMDDhhmmssZ |
|
var format = []; |
|
format.push(('' + date.getUTCFullYear()).substr(2)); |
|
format.push('' + (date.getUTCMonth() + 1)); |
|
format.push('' + date.getUTCDate()); |
|
format.push('' + date.getUTCHours()); |
|
format.push('' + date.getUTCMinutes()); |
|
format.push('' + date.getUTCSeconds()); |
|
// ensure 2 digits are used for each format entry |
|
for(var i = 0; i < format.length; ++i){ |
|
if (format[i].length < 2) rval += '0'; |
|
rval += format[i]; |
|
} |
|
rval += 'Z'; |
|
return rval; |
|
}; |
|
/** |
|
* Converts a date to a GeneralizedTime value. |
|
* |
|
* @param date the date to convert. |
|
* |
|
* @return the GeneralizedTime value as a string. |
|
*/ $579f29a8775d6845$var$asn1.dateToGeneralizedTime = function(date) { |
|
// TODO: validate; currently assumes proper format |
|
if (typeof date === 'string') return date; |
|
var rval = ''; |
|
// create format YYYYMMDDHHMMSSZ |
|
var format = []; |
|
format.push('' + date.getUTCFullYear()); |
|
format.push('' + (date.getUTCMonth() + 1)); |
|
format.push('' + date.getUTCDate()); |
|
format.push('' + date.getUTCHours()); |
|
format.push('' + date.getUTCMinutes()); |
|
format.push('' + date.getUTCSeconds()); |
|
// ensure 2 digits are used for each format entry |
|
for(var i = 0; i < format.length; ++i){ |
|
if (format[i].length < 2) rval += '0'; |
|
rval += format[i]; |
|
} |
|
rval += 'Z'; |
|
return rval; |
|
}; |
|
/** |
|
* Converts a javascript integer to a DER-encoded byte buffer to be used |
|
* as the value for an INTEGER type. |
|
* |
|
* @param x the integer. |
|
* |
|
* @return the byte buffer. |
|
*/ $579f29a8775d6845$var$asn1.integerToDer = function(x) { |
|
var rval = $iGlOy.util.createBuffer(); |
|
if (x >= -128 && x < 128) return rval.putSignedInt(x, 8); |
|
if (x >= -32768 && x < 32768) return rval.putSignedInt(x, 16); |
|
if (x >= -8388608 && x < 8388608) return rval.putSignedInt(x, 24); |
|
if (x >= -2147483648 && x < 2147483648) return rval.putSignedInt(x, 32); |
|
var error = new Error('Integer too large; max is 32-bits.'); |
|
error.integer = x; |
|
throw error; |
|
}; |
|
/** |
|
* Converts a DER-encoded byte buffer to a javascript integer. This is |
|
* typically used to decode the value of an INTEGER type. |
|
* |
|
* @param bytes the byte buffer. |
|
* |
|
* @return the integer. |
|
*/ $579f29a8775d6845$var$asn1.derToInteger = function(bytes) { |
|
// wrap in buffer if needed |
|
if (typeof bytes === 'string') bytes = $iGlOy.util.createBuffer(bytes); |
|
var n = bytes.length() * 8; |
|
if (n > 32) throw new Error('Integer too large; max is 32-bits.'); |
|
return bytes.getSignedInt(n); |
|
}; |
|
/** |
|
* Validates that the given ASN.1 object is at least a super set of the |
|
* given ASN.1 structure. Only tag classes and types are checked. An |
|
* optional map may also be provided to capture ASN.1 values while the |
|
* structure is checked. |
|
* |
|
* To capture an ASN.1 value, set an object in the validator's 'capture' |
|
* parameter to the key to use in the capture map. To capture the full |
|
* ASN.1 object, specify 'captureAsn1'. To capture BIT STRING bytes, including |
|
* the leading unused bits counter byte, specify 'captureBitStringContents'. |
|
* To capture BIT STRING bytes, without the leading unused bits counter byte, |
|
* specify 'captureBitStringValue'. |
|
* |
|
* Objects in the validator may set a field 'optional' to true to indicate |
|
* that it isn't necessary to pass validation. |
|
* |
|
* @param obj the ASN.1 object to validate. |
|
* @param v the ASN.1 structure validator. |
|
* @param capture an optional map to capture values in. |
|
* @param errors an optional array for storing validation errors. |
|
* |
|
* @return true on success, false on failure. |
|
*/ $579f29a8775d6845$var$asn1.validate = function(obj, v, capture, errors) { |
|
var rval = false; |
|
// ensure tag class and type are the same if specified |
|
if ((obj.tagClass === v.tagClass || typeof v.tagClass === 'undefined') && (obj.type === v.type || typeof v.type === 'undefined')) { |
|
// ensure constructed flag is the same if specified |
|
if (obj.constructed === v.constructed || typeof v.constructed === 'undefined') { |
|
rval = true; |
|
// handle sub values |
|
if (v.value && $iGlOy.util.isArray(v.value)) { |
|
var j = 0; |
|
for(var i = 0; rval && i < v.value.length; ++i){ |
|
rval = v.value[i].optional || false; |
|
if (obj.value[j]) { |
|
rval = $579f29a8775d6845$var$asn1.validate(obj.value[j], v.value[i], capture, errors); |
|
if (rval) ++j; |
|
else if (v.value[i].optional) rval = true; |
|
} |
|
if (!rval && errors) errors.push('[' + v.name + '] ' + 'Tag class "' + v.tagClass + '", type "' + v.type + '" expected value length "' + v.value.length + '", got "' + obj.value.length + '"'); |
|
} |
|
} |
|
if (rval && capture) { |
|
if (v.capture) capture[v.capture] = obj.value; |
|
if (v.captureAsn1) capture[v.captureAsn1] = obj; |
|
if (v.captureBitStringContents && 'bitStringContents' in obj) capture[v.captureBitStringContents] = obj.bitStringContents; |
|
if (v.captureBitStringValue && 'bitStringContents' in obj) { |
|
var value; |
|
if (obj.bitStringContents.length < 2) capture[v.captureBitStringValue] = ''; |
|
else { |
|
// FIXME: support unused bits with data shifting |
|
var unused = obj.bitStringContents.charCodeAt(0); |
|
if (unused !== 0) throw new Error('captureBitStringValue only supported for zero unused bits'); |
|
capture[v.captureBitStringValue] = obj.bitStringContents.slice(1); |
|
} |
|
} |
|
} |
|
} else if (errors) errors.push('[' + v.name + '] ' + 'Expected constructed "' + v.constructed + '", got "' + obj.constructed + '"'); |
|
} else if (errors) { |
|
if (obj.tagClass !== v.tagClass) errors.push('[' + v.name + '] ' + 'Expected tag class "' + v.tagClass + '", got "' + obj.tagClass + '"'); |
|
if (obj.type !== v.type) errors.push('[' + v.name + '] ' + 'Expected type "' + v.type + '", got "' + obj.type + '"'); |
|
} |
|
return rval; |
|
}; |
|
// regex for testing for non-latin characters |
|
var $579f29a8775d6845$var$_nonLatinRegex = /[^\\u0000-\\u00ff]/; |
|
/** |
|
* Pretty prints an ASN.1 object to a string. |
|
* |
|
* @param obj the object to write out. |
|
* @param level the level in the tree. |
|
* @param indentation the indentation to use. |
|
* |
|
* @return the string. |
|
*/ $579f29a8775d6845$var$asn1.prettyPrint = function(obj, level, indentation) { |
|
var rval = ''; |
|
// set default level and indentation |
|
level = level || 0; |
|
indentation = indentation || 2; |
|
// start new line for deep levels |
|
if (level > 0) rval += '\n'; |
|
// create indent |
|
var indent = ''; |
|
for(var i = 0; i < level * indentation; ++i)indent += ' '; |
|
// print class:type |
|
rval += indent + 'Tag: '; |
|
switch(obj.tagClass){ |
|
case $579f29a8775d6845$var$asn1.Class.UNIVERSAL: |
|
rval += 'Universal:'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Class.APPLICATION: |
|
rval += 'Application:'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Class.CONTEXT_SPECIFIC: |
|
rval += 'Context-Specific:'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Class.PRIVATE: |
|
rval += 'Private:'; |
|
break; |
|
} |
|
if (obj.tagClass === $579f29a8775d6845$var$asn1.Class.UNIVERSAL) { |
|
rval += obj.type; |
|
// known types |
|
switch(obj.type){ |
|
case $579f29a8775d6845$var$asn1.Type.NONE: |
|
rval += ' (None)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.BOOLEAN: |
|
rval += ' (Boolean)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.INTEGER: |
|
rval += ' (Integer)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.BITSTRING: |
|
rval += ' (Bit string)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.OCTETSTRING: |
|
rval += ' (Octet string)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.NULL: |
|
rval += ' (Null)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.OID: |
|
rval += ' (Object Identifier)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.ODESC: |
|
rval += ' (Object Descriptor)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.EXTERNAL: |
|
rval += ' (External or Instance of)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.REAL: |
|
rval += ' (Real)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.ENUMERATED: |
|
rval += ' (Enumerated)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.EMBEDDED: |
|
rval += ' (Embedded PDV)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.UTF8: |
|
rval += ' (UTF8)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.ROID: |
|
rval += ' (Relative Object Identifier)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.SEQUENCE: |
|
rval += ' (Sequence)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.SET: |
|
rval += ' (Set)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.PRINTABLESTRING: |
|
rval += ' (Printable String)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.IA5String: |
|
rval += ' (IA5String (ASCII))'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.UTCTIME: |
|
rval += ' (UTC time)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.GENERALIZEDTIME: |
|
rval += ' (Generalized time)'; |
|
break; |
|
case $579f29a8775d6845$var$asn1.Type.BMPSTRING: |
|
rval += ' (BMP String)'; |
|
break; |
|
} |
|
} else rval += obj.type; |
|
rval += '\n'; |
|
rval += indent + 'Constructed: ' + obj.constructed + '\n'; |
|
if (obj.composed) { |
|
var subvalues = 0; |
|
var sub = ''; |
|
for(var i = 0; i < obj.value.length; ++i)if (obj.value[i] !== undefined) { |
|
subvalues += 1; |
|
sub += $579f29a8775d6845$var$asn1.prettyPrint(obj.value[i], level + 1, indentation); |
|
if (i + 1 < obj.value.length) sub += ','; |
|
} |
|
rval += indent + 'Sub values: ' + subvalues + sub; |
|
} else { |
|
rval += indent + 'Value: '; |
|
if (obj.type === $579f29a8775d6845$var$asn1.Type.OID) { |
|
var oid = $579f29a8775d6845$var$asn1.derToOid(obj.value); |
|
rval += oid; |
|
if ($iGlOy.pki && $iGlOy.pki.oids) { |
|
if (oid in $iGlOy.pki.oids) rval += ' (' + $iGlOy.pki.oids[oid] + ') '; |
|
} |
|
} |
|
if (obj.type === $579f29a8775d6845$var$asn1.Type.INTEGER) try { |
|
rval += $579f29a8775d6845$var$asn1.derToInteger(obj.value); |
|
} catch (ex) { |
|
rval += '0x' + $iGlOy.util.bytesToHex(obj.value); |
|
} |
|
else if (obj.type === $579f29a8775d6845$var$asn1.Type.BITSTRING) { |
|
// TODO: shift bits as needed to display without padding |
|
if (obj.value.length > 1) // remove unused bits field |
|
rval += '0x' + $iGlOy.util.bytesToHex(obj.value.slice(1)); |
|
else rval += '(none)'; |
|
// show unused bit count |
|
if (obj.value.length > 0) { |
|
var unused = obj.value.charCodeAt(0); |
|
if (unused == 1) rval += ' (1 unused bit shown)'; |
|
else if (unused > 1) rval += ' (' + unused + ' unused bits shown)'; |
|
} |
|
} else if (obj.type === $579f29a8775d6845$var$asn1.Type.OCTETSTRING) { |
|
if (!$579f29a8775d6845$var$_nonLatinRegex.test(obj.value)) rval += '(' + obj.value + ') '; |
|
rval += '0x' + $iGlOy.util.bytesToHex(obj.value); |
|
} else if (obj.type === $579f29a8775d6845$var$asn1.Type.UTF8) rval += $iGlOy.util.decodeUtf8(obj.value); |
|
else if (obj.type === $579f29a8775d6845$var$asn1.Type.PRINTABLESTRING || obj.type === $579f29a8775d6845$var$asn1.Type.IA5String) rval += obj.value; |
|
else if ($579f29a8775d6845$var$_nonLatinRegex.test(obj.value)) rval += '0x' + $iGlOy.util.bytesToHex(obj.value); |
|
else if (obj.value.length === 0) rval += '[null]'; |
|
else rval += obj.value; |
|
} |
|
return rval; |
|
}; |
|
|
|
|
|
var $84d5ddf5dc7c5415$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
parcelRequire("ai0Z9"); |
|
|
|
/* HMAC API */ var $84d5ddf5dc7c5415$var$hmac = $84d5ddf5dc7c5415$exports = $iGlOy.hmac = $iGlOy.hmac || { |
|
}; |
|
/** |
|
* Creates an HMAC object that uses the given message digest object. |
|
* |
|
* @return an HMAC object. |
|
*/ $84d5ddf5dc7c5415$var$hmac.create = function() { |
|
// the hmac key to use |
|
var _key = null; |
|
// the message digest to use |
|
var _md = null; |
|
// the inner padding |
|
var _ipadding = null; |
|
// the outer padding |
|
var _opadding = null; |
|
// hmac context |
|
var ctx = { |
|
}; |
|
/** |
|
* Starts or restarts the HMAC with the given key and message digest. |
|
* |
|
* @param md the message digest to use, null to reuse the previous one, |
|
* a string to use builtin 'sha1', 'md5', 'sha256'. |
|
* @param key the key to use as a string, array of bytes, byte buffer, |
|
* or null to reuse the previous key. |
|
*/ ctx.start = function(md, key) { |
|
if (md !== null) { |
|
if (typeof md === 'string') { |
|
// create builtin message digest |
|
md = md.toLowerCase(); |
|
if (md in $iGlOy.md.algorithms) _md = $iGlOy.md.algorithms[md].create(); |
|
else throw new Error('Unknown hash algorithm "' + md + '"'); |
|
} else // store message digest |
|
_md = md; |
|
} |
|
if (key === null) // reuse previous key |
|
key = _key; |
|
else { |
|
if (typeof key === 'string') // convert string into byte buffer |
|
key = $iGlOy.util.createBuffer(key); |
|
else if ($iGlOy.util.isArray(key)) { |
|
// convert byte array into byte buffer |
|
var tmp = key; |
|
key = $iGlOy.util.createBuffer(); |
|
for(var i = 0; i < tmp.length; ++i)key.putByte(tmp[i]); |
|
} |
|
// if key is longer than blocksize, hash it |
|
var keylen = key.length(); |
|
if (keylen > _md.blockLength) { |
|
_md.start(); |
|
_md.update(key.bytes()); |
|
key = _md.digest(); |
|
} |
|
// mix key into inner and outer padding |
|
// ipadding = [0x36 * blocksize] ^ key |
|
// opadding = [0x5C * blocksize] ^ key |
|
_ipadding = $iGlOy.util.createBuffer(); |
|
_opadding = $iGlOy.util.createBuffer(); |
|
keylen = key.length(); |
|
for(var i = 0; i < keylen; ++i){ |
|
var tmp = key.at(i); |
|
_ipadding.putByte(54 ^ tmp); |
|
_opadding.putByte(92 ^ tmp); |
|
} |
|
// if key is shorter than blocksize, add additional padding |
|
if (keylen < _md.blockLength) { |
|
var tmp = _md.blockLength - keylen; |
|
for(var i = 0; i < tmp; ++i){ |
|
_ipadding.putByte(54); |
|
_opadding.putByte(92); |
|
} |
|
} |
|
_key = key; |
|
_ipadding = _ipadding.bytes(); |
|
_opadding = _opadding.bytes(); |
|
} |
|
// digest is done like so: hash(opadding | hash(ipadding | message)) |
|
// prepare to do inner hash |
|
// hash(ipadding | message) |
|
_md.start(); |
|
_md.update(_ipadding); |
|
}; |
|
/** |
|
* Updates the HMAC with the given message bytes. |
|
* |
|
* @param bytes the bytes to update with. |
|
*/ ctx.update = function(bytes) { |
|
_md.update(bytes); |
|
}; |
|
/** |
|
* Produces the Message Authentication Code (MAC). |
|
* |
|
* @return a byte buffer containing the digest value. |
|
*/ ctx.getMac = function() { |
|
// digest is done like so: hash(opadding | hash(ipadding | message)) |
|
// here we do the outer hashing |
|
var inner = _md.digest().bytes(); |
|
_md.start(); |
|
_md.update(_opadding); |
|
_md.update(inner); |
|
return _md.digest(); |
|
}; |
|
// alias for getMac |
|
ctx.digest = ctx.getMac; |
|
return ctx; |
|
}; |
|
|
|
|
|
var $a933e3938fe5f3ff$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
parcelRequire("ai0Z9"); |
|
|
|
var $a933e3938fe5f3ff$var$md5 = $a933e3938fe5f3ff$exports = $iGlOy.md5 = $iGlOy.md5 || { |
|
}; |
|
$iGlOy.md.md5 = $iGlOy.md.algorithms.md5 = $a933e3938fe5f3ff$var$md5; |
|
/** |
|
* Creates an MD5 message digest object. |
|
* |
|
* @return a message digest object. |
|
*/ $a933e3938fe5f3ff$var$md5.create = function() { |
|
// do initialization as necessary |
|
if (!$a933e3938fe5f3ff$var$_initialized) $a933e3938fe5f3ff$var$_init(); |
|
// MD5 state contains four 32-bit integers |
|
var _state = null; |
|
// input buffer |
|
var _input = $iGlOy.util.createBuffer(); |
|
// used for word storage |
|
var _w = new Array(16); |
|
// message digest object |
|
var md = { |
|
algorithm: 'md5', |
|
blockLength: 64, |
|
digestLength: 16, |
|
// 56-bit length of message so far (does not including padding) |
|
messageLength: 0, |
|
// true message length |
|
fullMessageLength: null, |
|
// size of message length in bytes |
|
messageLengthSize: 8 |
|
}; |
|
/** |
|
* Starts the digest. |
|
* |
|
* @return this digest object. |
|
*/ md.start = function() { |
|
// up to 56-bit message length for convenience |
|
md.messageLength = 0; |
|
// full message length (set md.messageLength64 for backwards-compatibility) |
|
md.fullMessageLength = md.messageLength64 = []; |
|
var int32s = md.messageLengthSize / 4; |
|
for(var i = 0; i < int32s; ++i)md.fullMessageLength.push(0); |
|
_input = $iGlOy.util.createBuffer(); |
|
_state = { |
|
h0: 1732584193, |
|
h1: 4023233417, |
|
h2: 2562383102, |
|
h3: 271733878 |
|
}; |
|
return md; |
|
}; |
|
// start digest automatically for first time |
|
md.start(); |
|
/** |
|
* Updates the digest with the given message input. The given input can |
|
* treated as raw input (no encoding will be applied) or an encoding of |
|
* 'utf8' maybe given to encode the input using UTF-8. |
|
* |
|
* @param msg the message input to update with. |
|
* @param encoding the encoding to use (default: 'raw', other: 'utf8'). |
|
* |
|
* @return this digest object. |
|
*/ md.update = function(msg, encoding) { |
|
if (encoding === 'utf8') msg = $iGlOy.util.encodeUtf8(msg); |
|
// update message length |
|
var len = msg.length; |
|
md.messageLength += len; |
|
len = [ |
|
len / 4294967296 >>> 0, |
|
len >>> 0 |
|
]; |
|
for(var i = md.fullMessageLength.length - 1; i >= 0; --i){ |
|
md.fullMessageLength[i] += len[1]; |
|
len[1] = len[0] + (md.fullMessageLength[i] / 4294967296 >>> 0); |
|
md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; |
|
len[0] = len[1] / 4294967296 >>> 0; |
|
} |
|
// add bytes to input buffer |
|
_input.putBytes(msg); |
|
// process bytes |
|
$a933e3938fe5f3ff$var$_update(_state, _w, _input); |
|
// compact input buffer every 2K or if empty |
|
if (_input.read > 2048 || _input.length() === 0) _input.compact(); |
|
return md; |
|
}; |
|
/** |
|
* Produces the digest. |
|
* |
|
* @return a byte buffer containing the digest value. |
|
*/ md.digest = function() { |
|
/* Note: Here we copy the remaining bytes in the input buffer and |
|
add the appropriate MD5 padding. Then we do the final update |
|
on a copy of the state so that if the user wants to get |
|
intermediate digests they can do so. */ /* Determine the number of bytes that must be added to the message |
|
to ensure its length is congruent to 448 mod 512. In other words, |
|
the data to be digested must be a multiple of 512 bits (or 128 bytes). |
|
This data includes the message, some padding, and the length of the |
|
message. Since the length of the message will be encoded as 8 bytes (64 |
|
bits), that means that the last segment of the data must have 56 bytes |
|
(448 bits) of message and padding. Therefore, the length of the message |
|
plus the padding must be congruent to 448 mod 512 because |
|
512 - 128 = 448. |
|
|
|
In order to fill up the message length it must be filled with |
|
padding that begins with 1 bit followed by all 0 bits. Padding |
|
must *always* be present, so if the message length is already |
|
congruent to 448 mod 512, then 512 padding bits must be added. */ var finalBlock = $iGlOy.util.createBuffer(); |
|
finalBlock.putBytes(_input.bytes()); |
|
// compute remaining size to be digested (include message length size) |
|
var remaining = md.fullMessageLength[md.fullMessageLength.length - 1] + md.messageLengthSize; |
|
// add padding for overflow blockSize - overflow |
|
// _padding starts with 1 byte with first bit is set (byte value 128), then |
|
// there may be up to (blockSize - 1) other pad bytes |
|
var overflow = remaining & md.blockLength - 1; |
|
finalBlock.putBytes($a933e3938fe5f3ff$var$_padding.substr(0, md.blockLength - overflow)); |
|
// serialize message length in bits in little-endian order; since length |
|
// is stored in bytes we multiply by 8 and add carry |
|
var bits, carry = 0; |
|
for(var i = md.fullMessageLength.length - 1; i >= 0; --i){ |
|
bits = md.fullMessageLength[i] * 8 + carry; |
|
carry = bits / 4294967296 >>> 0; |
|
finalBlock.putInt32Le(bits >>> 0); |
|
} |
|
var s2 = { |
|
h0: _state.h0, |
|
h1: _state.h1, |
|
h2: _state.h2, |
|
h3: _state.h3 |
|
}; |
|
$a933e3938fe5f3ff$var$_update(s2, _w, finalBlock); |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putInt32Le(s2.h0); |
|
rval.putInt32Le(s2.h1); |
|
rval.putInt32Le(s2.h2); |
|
rval.putInt32Le(s2.h3); |
|
return rval; |
|
}; |
|
return md; |
|
}; |
|
// padding, constant tables for calculating md5 |
|
var $a933e3938fe5f3ff$var$_padding = null; |
|
var $a933e3938fe5f3ff$var$_g = null; |
|
var $a933e3938fe5f3ff$var$_r = null; |
|
var $a933e3938fe5f3ff$var$_k = null; |
|
var $a933e3938fe5f3ff$var$_initialized = false; |
|
/** |
|
* Initializes the constant tables. |
|
*/ function $a933e3938fe5f3ff$var$_init() { |
|
// create padding |
|
$a933e3938fe5f3ff$var$_padding = String.fromCharCode(128); |
|
$a933e3938fe5f3ff$var$_padding += $iGlOy.util.fillString(String.fromCharCode(0), 64); |
|
// g values |
|
$a933e3938fe5f3ff$var$_g = [ |
|
0, |
|
1, |
|
2, |
|
3, |
|
4, |
|
5, |
|
6, |
|
7, |
|
8, |
|
9, |
|
10, |
|
11, |
|
12, |
|
13, |
|
14, |
|
15, |
|
1, |
|
6, |
|
11, |
|
0, |
|
5, |
|
10, |
|
15, |
|
4, |
|
9, |
|
14, |
|
3, |
|
8, |
|
13, |
|
2, |
|
7, |
|
12, |
|
5, |
|
8, |
|
11, |
|
14, |
|
1, |
|
4, |
|
7, |
|
10, |
|
13, |
|
0, |
|
3, |
|
6, |
|
9, |
|
12, |
|
15, |
|
2, |
|
0, |
|
7, |
|
14, |
|
5, |
|
12, |
|
3, |
|
10, |
|
1, |
|
8, |
|
15, |
|
6, |
|
13, |
|
4, |
|
11, |
|
2, |
|
9 |
|
]; |
|
// rounds table |
|
$a933e3938fe5f3ff$var$_r = [ |
|
7, |
|
12, |
|
17, |
|
22, |
|
7, |
|
12, |
|
17, |
|
22, |
|
7, |
|
12, |
|
17, |
|
22, |
|
7, |
|
12, |
|
17, |
|
22, |
|
5, |
|
9, |
|
14, |
|
20, |
|
5, |
|
9, |
|
14, |
|
20, |
|
5, |
|
9, |
|
14, |
|
20, |
|
5, |
|
9, |
|
14, |
|
20, |
|
4, |
|
11, |
|
16, |
|
23, |
|
4, |
|
11, |
|
16, |
|
23, |
|
4, |
|
11, |
|
16, |
|
23, |
|
4, |
|
11, |
|
16, |
|
23, |
|
6, |
|
10, |
|
15, |
|
21, |
|
6, |
|
10, |
|
15, |
|
21, |
|
6, |
|
10, |
|
15, |
|
21, |
|
6, |
|
10, |
|
15, |
|
21 |
|
]; |
|
// get the result of abs(sin(i + 1)) as a 32-bit integer |
|
$a933e3938fe5f3ff$var$_k = new Array(64); |
|
for(var i = 0; i < 64; ++i)$a933e3938fe5f3ff$var$_k[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 4294967296); |
|
// now initialized |
|
$a933e3938fe5f3ff$var$_initialized = true; |
|
} |
|
/** |
|
* Updates an MD5 state with the given byte buffer. |
|
* |
|
* @param s the MD5 state to update. |
|
* @param w the array to use to store words. |
|
* @param bytes the byte buffer to update with. |
|
*/ function $a933e3938fe5f3ff$var$_update(s, w, bytes) { |
|
// consume 512 bit (64 byte) chunks |
|
var t, a, b, c, d, f, r, i; |
|
var len = bytes.length(); |
|
while(len >= 64){ |
|
// initialize hash value for this chunk |
|
a = s.h0; |
|
b = s.h1; |
|
c = s.h2; |
|
d = s.h3; |
|
// round 1 |
|
for(i = 0; i < 16; ++i){ |
|
w[i] = bytes.getInt32Le(); |
|
f = d ^ b & (c ^ d); |
|
t = a + f + $a933e3938fe5f3ff$var$_k[i] + w[i]; |
|
r = $a933e3938fe5f3ff$var$_r[i]; |
|
a = d; |
|
d = c; |
|
c = b; |
|
b += t << r | t >>> 32 - r; |
|
} |
|
// round 2 |
|
for(; i < 32; ++i){ |
|
f = c ^ d & (b ^ c); |
|
t = a + f + $a933e3938fe5f3ff$var$_k[i] + w[$a933e3938fe5f3ff$var$_g[i]]; |
|
r = $a933e3938fe5f3ff$var$_r[i]; |
|
a = d; |
|
d = c; |
|
c = b; |
|
b += t << r | t >>> 32 - r; |
|
} |
|
// round 3 |
|
for(; i < 48; ++i){ |
|
f = b ^ c ^ d; |
|
t = a + f + $a933e3938fe5f3ff$var$_k[i] + w[$a933e3938fe5f3ff$var$_g[i]]; |
|
r = $a933e3938fe5f3ff$var$_r[i]; |
|
a = d; |
|
d = c; |
|
c = b; |
|
b += t << r | t >>> 32 - r; |
|
} |
|
// round 4 |
|
for(; i < 64; ++i){ |
|
f = c ^ (b | ~d); |
|
t = a + f + $a933e3938fe5f3ff$var$_k[i] + w[$a933e3938fe5f3ff$var$_g[i]]; |
|
r = $a933e3938fe5f3ff$var$_r[i]; |
|
a = d; |
|
d = c; |
|
c = b; |
|
b += t << r | t >>> 32 - r; |
|
} |
|
// update hash state |
|
s.h0 = s.h0 + a | 0; |
|
s.h1 = s.h1 + b | 0; |
|
s.h2 = s.h2 + c | 0; |
|
s.h3 = s.h3 + d | 0; |
|
len -= 64; |
|
} |
|
} |
|
|
|
|
|
var $6c81a009b991fd79$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
// shortcut for pem API |
|
var $6c81a009b991fd79$var$pem = $6c81a009b991fd79$exports = $iGlOy.pem = $iGlOy.pem || { |
|
}; |
|
/** |
|
* Encodes (serializes) the given PEM object. |
|
* |
|
* @param msg the PEM message object to encode. |
|
* @param options the options to use: |
|
* maxline the maximum characters per line for the body, (default: 64). |
|
* |
|
* @return the PEM-formatted string. |
|
*/ $6c81a009b991fd79$var$pem.encode = function(msg, options) { |
|
options = options || { |
|
}; |
|
var rval = '-----BEGIN ' + msg.type + '-----\r\n'; |
|
// encode special headers |
|
var header; |
|
if (msg.procType) { |
|
header = { |
|
name: 'Proc-Type', |
|
values: [ |
|
String(msg.procType.version), |
|
msg.procType.type |
|
] |
|
}; |
|
rval += $6c81a009b991fd79$var$foldHeader(header); |
|
} |
|
if (msg.contentDomain) { |
|
header = { |
|
name: 'Content-Domain', |
|
values: [ |
|
msg.contentDomain |
|
] |
|
}; |
|
rval += $6c81a009b991fd79$var$foldHeader(header); |
|
} |
|
if (msg.dekInfo) { |
|
header = { |
|
name: 'DEK-Info', |
|
values: [ |
|
msg.dekInfo.algorithm |
|
] |
|
}; |
|
if (msg.dekInfo.parameters) header.values.push(msg.dekInfo.parameters); |
|
rval += $6c81a009b991fd79$var$foldHeader(header); |
|
} |
|
if (msg.headers) // encode all other headers |
|
for(var i = 0; i < msg.headers.length; ++i)rval += $6c81a009b991fd79$var$foldHeader(msg.headers[i]); |
|
// terminate header |
|
if (msg.procType) rval += '\r\n'; |
|
// add body |
|
rval += $iGlOy.util.encode64(msg.body, options.maxline || 64) + '\r\n'; |
|
rval += '-----END ' + msg.type + '-----\r\n'; |
|
return rval; |
|
}; |
|
/** |
|
* Decodes (deserializes) all PEM messages found in the given string. |
|
* |
|
* @param str the PEM-formatted string to decode. |
|
* |
|
* @return the PEM message objects in an array. |
|
*/ $6c81a009b991fd79$var$pem.decode = function(str) { |
|
var rval = []; |
|
// split string into PEM messages (be lenient w/EOF on BEGIN line) |
|
var rMessage = /\s*-----BEGIN ([A-Z0-9- ]+)-----\r?\n?([\x21-\x7e\s]+?(?:\r?\n\r?\n))?([:A-Za-z0-9+\/=\s]+?)-----END \1-----/g; |
|
var rHeader = /([\x21-\x7e]+):\s*([\x21-\x7e\s^:]+)/; |
|
var rCRLF = /\r?\n/; |
|
var match; |
|
while(true){ |
|
match = rMessage.exec(str); |
|
if (!match) break; |
|
// accept "NEW CERTIFICATE REQUEST" as "CERTIFICATE REQUEST" |
|
// https://datatracker.ietf.org/doc/html/rfc7468#section-7 |
|
var type = match[1]; |
|
if (type === 'NEW CERTIFICATE REQUEST') type = 'CERTIFICATE REQUEST'; |
|
var msg = { |
|
type: type, |
|
procType: null, |
|
contentDomain: null, |
|
dekInfo: null, |
|
headers: [], |
|
body: $iGlOy.util.decode64(match[3]) |
|
}; |
|
rval.push(msg); |
|
// no headers |
|
if (!match[2]) continue; |
|
// parse headers |
|
var lines = match[2].split(rCRLF); |
|
var li = 0; |
|
while(match && li < lines.length){ |
|
// get line, trim any rhs whitespace |
|
var line = lines[li].replace(/\s+$/, ''); |
|
// RFC2822 unfold any following folded lines |
|
for(var nl = li + 1; nl < lines.length; ++nl){ |
|
var next = lines[nl]; |
|
if (!/\s/.test(next[0])) break; |
|
line += next; |
|
li = nl; |
|
} |
|
// parse header |
|
match = line.match(rHeader); |
|
if (match) { |
|
var header = { |
|
name: match[1], |
|
values: [] |
|
}; |
|
var values = match[2].split(','); |
|
for(var vi = 0; vi < values.length; ++vi)header.values.push($6c81a009b991fd79$var$ltrim(values[vi])); |
|
// Proc-Type must be the first header |
|
if (!msg.procType) { |
|
if (header.name !== 'Proc-Type') throw new Error("Invalid PEM formatted message. The first encapsulated header must be \"Proc-Type\"."); |
|
else if (header.values.length !== 2) throw new Error("Invalid PEM formatted message. The \"Proc-Type\" header must have two subfields."); |
|
msg.procType = { |
|
version: values[0], |
|
type: values[1] |
|
}; |
|
} else if (!msg.contentDomain && header.name === 'Content-Domain') // special-case Content-Domain |
|
msg.contentDomain = values[0] || ''; |
|
else if (!msg.dekInfo && header.name === 'DEK-Info') { |
|
// special-case DEK-Info |
|
if (header.values.length === 0) throw new Error("Invalid PEM formatted message. The \"DEK-Info\" header must have at least one subfield."); |
|
msg.dekInfo = { |
|
algorithm: values[0], |
|
parameters: values[1] || null |
|
}; |
|
} else msg.headers.push(header); |
|
} |
|
++li; |
|
} |
|
if (msg.procType === 'ENCRYPTED' && !msg.dekInfo) throw new Error("Invalid PEM formatted message. The \"DEK-Info\" header must be present if \"Proc-Type\" is \"ENCRYPTED\"."); |
|
} |
|
if (rval.length === 0) throw new Error('Invalid PEM formatted message.'); |
|
return rval; |
|
}; |
|
function $6c81a009b991fd79$var$foldHeader(header) { |
|
var rval = header.name + ': '; |
|
// ensure values with CRLF are folded |
|
var values = []; |
|
var insertSpace = function(match, $1) { |
|
return ' ' + $1; |
|
}; |
|
for(var i = 0; i < header.values.length; ++i)values.push(header.values[i].replace(/^(\S+\r\n)/, insertSpace)); |
|
rval += values.join(',') + '\r\n'; |
|
// do folding |
|
var length = 0; |
|
var candidate = -1; |
|
for(var i = 0; i < rval.length; ++i, ++length){ |
|
if (length > 65 && candidate !== -1) { |
|
var insert = rval[candidate]; |
|
if (insert === ',') { |
|
++candidate; |
|
rval = rval.substr(0, candidate) + '\r\n ' + rval.substr(candidate); |
|
} else rval = rval.substr(0, candidate) + '\r\n' + insert + rval.substr(candidate + 1); |
|
length = i - candidate - 1; |
|
candidate = -1; |
|
++i; |
|
} else if (rval[i] === ' ' || rval[i] === '\t' || rval[i] === ',') candidate = i; |
|
} |
|
return rval; |
|
} |
|
function $6c81a009b991fd79$var$ltrim(str) { |
|
return str.replace(/^\s+/, ''); |
|
} |
|
|
|
|
|
var $71c5302ef2ea3950$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
var $4ead143e6089ae29$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
var $ff4c3bd9116e15cc$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
|
|
/* DES API */ $ff4c3bd9116e15cc$exports = $iGlOy.des = $iGlOy.des || { |
|
}; |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* var cipher = forge.cipher.createCipher('DES-<mode>', key); |
|
* cipher.start({iv: iv}); |
|
* |
|
* Creates an DES cipher object to encrypt data using the given symmetric key. |
|
* The output will be stored in the 'output' member of the returned cipher. |
|
* |
|
* The key and iv may be given as binary-encoded strings of bytes or |
|
* byte buffers. |
|
* |
|
* @param key the symmetric key to use (64 or 192 bits). |
|
* @param iv the initialization vector to use. |
|
* @param output the buffer to write to, null to create one. |
|
* @param mode the cipher mode to use (default: 'CBC' if IV is |
|
* given, 'ECB' if null). |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.des.startEncrypting = function(key, iv, output, mode) { |
|
var cipher = $ff4c3bd9116e15cc$var$_createCipher({ |
|
key: key, |
|
output: output, |
|
decrypt: false, |
|
mode: mode || (iv === null ? 'ECB' : 'CBC') |
|
}); |
|
cipher.start(iv); |
|
return cipher; |
|
}; |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* var cipher = forge.cipher.createCipher('DES-<mode>', key); |
|
* |
|
* Creates an DES cipher object to encrypt data using the given symmetric key. |
|
* |
|
* The key may be given as a binary-encoded string of bytes or a byte buffer. |
|
* |
|
* @param key the symmetric key to use (64 or 192 bits). |
|
* @param mode the cipher mode to use (default: 'CBC'). |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.des.createEncryptionCipher = function(key, mode) { |
|
return $ff4c3bd9116e15cc$var$_createCipher({ |
|
key: key, |
|
output: null, |
|
decrypt: false, |
|
mode: mode |
|
}); |
|
}; |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* var decipher = forge.cipher.createDecipher('DES-<mode>', key); |
|
* decipher.start({iv: iv}); |
|
* |
|
* Creates an DES cipher object to decrypt data using the given symmetric key. |
|
* The output will be stored in the 'output' member of the returned cipher. |
|
* |
|
* The key and iv may be given as binary-encoded strings of bytes or |
|
* byte buffers. |
|
* |
|
* @param key the symmetric key to use (64 or 192 bits). |
|
* @param iv the initialization vector to use. |
|
* @param output the buffer to write to, null to create one. |
|
* @param mode the cipher mode to use (default: 'CBC' if IV is |
|
* given, 'ECB' if null). |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.des.startDecrypting = function(key, iv, output, mode) { |
|
var cipher = $ff4c3bd9116e15cc$var$_createCipher({ |
|
key: key, |
|
output: output, |
|
decrypt: true, |
|
mode: mode || (iv === null ? 'ECB' : 'CBC') |
|
}); |
|
cipher.start(iv); |
|
return cipher; |
|
}; |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* var decipher = forge.cipher.createDecipher('DES-<mode>', key); |
|
* |
|
* Creates an DES cipher object to decrypt data using the given symmetric key. |
|
* |
|
* The key may be given as a binary-encoded string of bytes or a byte buffer. |
|
* |
|
* @param key the symmetric key to use (64 or 192 bits). |
|
* @param mode the cipher mode to use (default: 'CBC'). |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.des.createDecryptionCipher = function(key, mode) { |
|
return $ff4c3bd9116e15cc$var$_createCipher({ |
|
key: key, |
|
output: null, |
|
decrypt: true, |
|
mode: mode |
|
}); |
|
}; |
|
/** |
|
* Creates a new DES cipher algorithm object. |
|
* |
|
* @param name the name of the algorithm. |
|
* @param mode the mode factory function. |
|
* |
|
* @return the DES algorithm object. |
|
*/ $iGlOy.des.Algorithm = function(name, mode) { |
|
var self = this; |
|
self.name = name; |
|
self.mode = new mode({ |
|
blockSize: 8, |
|
cipher: { |
|
encrypt: function(inBlock, outBlock) { |
|
return $ff4c3bd9116e15cc$var$_updateBlock(self._keys, inBlock, outBlock, false); |
|
}, |
|
decrypt: function(inBlock, outBlock) { |
|
return $ff4c3bd9116e15cc$var$_updateBlock(self._keys, inBlock, outBlock, true); |
|
} |
|
} |
|
}); |
|
self._init = false; |
|
}; |
|
/** |
|
* Initializes this DES algorithm by expanding its key. |
|
* |
|
* @param options the options to use. |
|
* key the key to use with this algorithm. |
|
* decrypt true if the algorithm should be initialized for decryption, |
|
* false for encryption. |
|
*/ $iGlOy.des.Algorithm.prototype.initialize = function(options) { |
|
if (this._init) return; |
|
var key = $iGlOy.util.createBuffer(options.key); |
|
if (this.name.indexOf('3DES') === 0) { |
|
if (key.length() !== 24) throw new Error('Invalid Triple-DES key size: ' + key.length() * 8); |
|
} |
|
// do key expansion to 16 or 48 subkeys (single or triple DES) |
|
this._keys = $ff4c3bd9116e15cc$var$_createKeys(key); |
|
this._init = true; |
|
}; |
|
/** Register DES algorithms **/ $ff4c3bd9116e15cc$var$registerAlgorithm('DES-ECB', $iGlOy.cipher.modes.ecb); |
|
$ff4c3bd9116e15cc$var$registerAlgorithm('DES-CBC', $iGlOy.cipher.modes.cbc); |
|
$ff4c3bd9116e15cc$var$registerAlgorithm('DES-CFB', $iGlOy.cipher.modes.cfb); |
|
$ff4c3bd9116e15cc$var$registerAlgorithm('DES-OFB', $iGlOy.cipher.modes.ofb); |
|
$ff4c3bd9116e15cc$var$registerAlgorithm('DES-CTR', $iGlOy.cipher.modes.ctr); |
|
$ff4c3bd9116e15cc$var$registerAlgorithm('3DES-ECB', $iGlOy.cipher.modes.ecb); |
|
$ff4c3bd9116e15cc$var$registerAlgorithm('3DES-CBC', $iGlOy.cipher.modes.cbc); |
|
$ff4c3bd9116e15cc$var$registerAlgorithm('3DES-CFB', $iGlOy.cipher.modes.cfb); |
|
$ff4c3bd9116e15cc$var$registerAlgorithm('3DES-OFB', $iGlOy.cipher.modes.ofb); |
|
$ff4c3bd9116e15cc$var$registerAlgorithm('3DES-CTR', $iGlOy.cipher.modes.ctr); |
|
function $ff4c3bd9116e15cc$var$registerAlgorithm(name, mode) { |
|
var factory = function() { |
|
return new $iGlOy.des.Algorithm(name, mode); |
|
}; |
|
$iGlOy.cipher.registerAlgorithm(name, factory); |
|
} |
|
/** DES implementation **/ var $ff4c3bd9116e15cc$var$spfunction1 = [ |
|
16843776, |
|
0, |
|
65536, |
|
16843780, |
|
16842756, |
|
66564, |
|
4, |
|
65536, |
|
1024, |
|
16843776, |
|
16843780, |
|
1024, |
|
16778244, |
|
16842756, |
|
16777216, |
|
4, |
|
1028, |
|
16778240, |
|
16778240, |
|
66560, |
|
66560, |
|
16842752, |
|
16842752, |
|
16778244, |
|
65540, |
|
16777220, |
|
16777220, |
|
65540, |
|
0, |
|
1028, |
|
66564, |
|
16777216, |
|
65536, |
|
16843780, |
|
4, |
|
16842752, |
|
16843776, |
|
16777216, |
|
16777216, |
|
1024, |
|
16842756, |
|
65536, |
|
66560, |
|
16777220, |
|
1024, |
|
4, |
|
16778244, |
|
66564, |
|
16843780, |
|
65540, |
|
16842752, |
|
16778244, |
|
16777220, |
|
1028, |
|
66564, |
|
16843776, |
|
1028, |
|
16778240, |
|
16778240, |
|
0, |
|
65540, |
|
66560, |
|
0, |
|
16842756 |
|
]; |
|
var $ff4c3bd9116e15cc$var$spfunction2 = [ |
|
-2146402272, |
|
-2147450880, |
|
32768, |
|
1081376, |
|
1048576, |
|
32, |
|
-2146435040, |
|
-2147450848, |
|
-2147483616, |
|
-2146402272, |
|
-2146402304, |
|
-2147483648, |
|
-2147450880, |
|
1048576, |
|
32, |
|
-2146435040, |
|
1081344, |
|
1048608, |
|
-2147450848, |
|
0, |
|
-2147483648, |
|
32768, |
|
1081376, |
|
-2146435072, |
|
1048608, |
|
-2147483616, |
|
0, |
|
1081344, |
|
32800, |
|
-2146402304, |
|
-2146435072, |
|
32800, |
|
0, |
|
1081376, |
|
-2146435040, |
|
1048576, |
|
-2147450848, |
|
-2146435072, |
|
-2146402304, |
|
32768, |
|
-2146435072, |
|
-2147450880, |
|
32, |
|
-2146402272, |
|
1081376, |
|
32, |
|
32768, |
|
-2147483648, |
|
32800, |
|
-2146402304, |
|
1048576, |
|
-2147483616, |
|
1048608, |
|
-2147450848, |
|
-2147483616, |
|
1048608, |
|
1081344, |
|
0, |
|
-2147450880, |
|
32800, |
|
-2147483648, |
|
-2146435040, |
|
-2146402272, |
|
1081344 |
|
]; |
|
var $ff4c3bd9116e15cc$var$spfunction3 = [ |
|
520, |
|
134349312, |
|
0, |
|
134348808, |
|
134218240, |
|
0, |
|
131592, |
|
134218240, |
|
131080, |
|
134217736, |
|
134217736, |
|
131072, |
|
134349320, |
|
131080, |
|
134348800, |
|
520, |
|
134217728, |
|
8, |
|
134349312, |
|
512, |
|
131584, |
|
134348800, |
|
134348808, |
|
131592, |
|
134218248, |
|
131584, |
|
131072, |
|
134218248, |
|
8, |
|
134349320, |
|
512, |
|
134217728, |
|
134349312, |
|
134217728, |
|
131080, |
|
520, |
|
131072, |
|
134349312, |
|
134218240, |
|
0, |
|
512, |
|
131080, |
|
134349320, |
|
134218240, |
|
134217736, |
|
512, |
|
0, |
|
134348808, |
|
134218248, |
|
131072, |
|
134217728, |
|
134349320, |
|
8, |
|
131592, |
|
131584, |
|
134217736, |
|
134348800, |
|
134218248, |
|
520, |
|
134348800, |
|
131592, |
|
8, |
|
134348808, |
|
131584 |
|
]; |
|
var $ff4c3bd9116e15cc$var$spfunction4 = [ |
|
8396801, |
|
8321, |
|
8321, |
|
128, |
|
8396928, |
|
8388737, |
|
8388609, |
|
8193, |
|
0, |
|
8396800, |
|
8396800, |
|
8396929, |
|
129, |
|
0, |
|
8388736, |
|
8388609, |
|
1, |
|
8192, |
|
8388608, |
|
8396801, |
|
128, |
|
8388608, |
|
8193, |
|
8320, |
|
8388737, |
|
1, |
|
8320, |
|
8388736, |
|
8192, |
|
8396928, |
|
8396929, |
|
129, |
|
8388736, |
|
8388609, |
|
8396800, |
|
8396929, |
|
129, |
|
0, |
|
0, |
|
8396800, |
|
8320, |
|
8388736, |
|
8388737, |
|
1, |
|
8396801, |
|
8321, |
|
8321, |
|
128, |
|
8396929, |
|
129, |
|
1, |
|
8192, |
|
8388609, |
|
8193, |
|
8396928, |
|
8388737, |
|
8193, |
|
8320, |
|
8388608, |
|
8396801, |
|
128, |
|
8388608, |
|
8192, |
|
8396928 |
|
]; |
|
var $ff4c3bd9116e15cc$var$spfunction5 = [ |
|
256, |
|
34078976, |
|
34078720, |
|
1107296512, |
|
524288, |
|
256, |
|
1073741824, |
|
34078720, |
|
1074266368, |
|
524288, |
|
33554688, |
|
1074266368, |
|
1107296512, |
|
1107820544, |
|
524544, |
|
1073741824, |
|
33554432, |
|
1074266112, |
|
1074266112, |
|
0, |
|
1073742080, |
|
1107820800, |
|
1107820800, |
|
33554688, |
|
1107820544, |
|
1073742080, |
|
0, |
|
1107296256, |
|
34078976, |
|
33554432, |
|
1107296256, |
|
524544, |
|
524288, |
|
1107296512, |
|
256, |
|
33554432, |
|
1073741824, |
|
34078720, |
|
1107296512, |
|
1074266368, |
|
33554688, |
|
1073741824, |
|
1107820544, |
|
34078976, |
|
1074266368, |
|
256, |
|
33554432, |
|
1107820544, |
|
1107820800, |
|
524544, |
|
1107296256, |
|
1107820800, |
|
34078720, |
|
0, |
|
1074266112, |
|
1107296256, |
|
524544, |
|
33554688, |
|
1073742080, |
|
524288, |
|
0, |
|
1074266112, |
|
34078976, |
|
1073742080 |
|
]; |
|
var $ff4c3bd9116e15cc$var$spfunction6 = [ |
|
536870928, |
|
541065216, |
|
16384, |
|
541081616, |
|
541065216, |
|
16, |
|
541081616, |
|
4194304, |
|
536887296, |
|
4210704, |
|
4194304, |
|
536870928, |
|
4194320, |
|
536887296, |
|
536870912, |
|
16400, |
|
0, |
|
4194320, |
|
536887312, |
|
16384, |
|
4210688, |
|
536887312, |
|
16, |
|
541065232, |
|
541065232, |
|
0, |
|
4210704, |
|
541081600, |
|
16400, |
|
4210688, |
|
541081600, |
|
536870912, |
|
536887296, |
|
16, |
|
541065232, |
|
4210688, |
|
541081616, |
|
4194304, |
|
16400, |
|
536870928, |
|
4194304, |
|
536887296, |
|
536870912, |
|
16400, |
|
536870928, |
|
541081616, |
|
4210688, |
|
541065216, |
|
4210704, |
|
541081600, |
|
0, |
|
541065232, |
|
16, |
|
16384, |
|
541065216, |
|
4210704, |
|
16384, |
|
4194320, |
|
536887312, |
|
0, |
|
541081600, |
|
536870912, |
|
4194320, |
|
536887312 |
|
]; |
|
var $ff4c3bd9116e15cc$var$spfunction7 = [ |
|
2097152, |
|
69206018, |
|
67110914, |
|
0, |
|
2048, |
|
67110914, |
|
2099202, |
|
69208064, |
|
69208066, |
|
2097152, |
|
0, |
|
67108866, |
|
2, |
|
67108864, |
|
69206018, |
|
2050, |
|
67110912, |
|
2099202, |
|
2097154, |
|
67110912, |
|
67108866, |
|
69206016, |
|
69208064, |
|
2097154, |
|
69206016, |
|
2048, |
|
2050, |
|
69208066, |
|
2099200, |
|
2, |
|
67108864, |
|
2099200, |
|
67108864, |
|
2099200, |
|
2097152, |
|
67110914, |
|
67110914, |
|
69206018, |
|
69206018, |
|
2, |
|
2097154, |
|
67108864, |
|
67110912, |
|
2097152, |
|
69208064, |
|
2050, |
|
2099202, |
|
69208064, |
|
2050, |
|
67108866, |
|
69208066, |
|
69206016, |
|
2099200, |
|
0, |
|
2, |
|
69208066, |
|
0, |
|
2099202, |
|
69206016, |
|
2048, |
|
67108866, |
|
67110912, |
|
2048, |
|
2097154 |
|
]; |
|
var $ff4c3bd9116e15cc$var$spfunction8 = [ |
|
268439616, |
|
4096, |
|
262144, |
|
268701760, |
|
268435456, |
|
268439616, |
|
64, |
|
268435456, |
|
262208, |
|
268697600, |
|
268701760, |
|
266240, |
|
268701696, |
|
266304, |
|
4096, |
|
64, |
|
268697600, |
|
268435520, |
|
268439552, |
|
4160, |
|
266240, |
|
262208, |
|
268697664, |
|
268701696, |
|
4160, |
|
0, |
|
0, |
|
268697664, |
|
268435520, |
|
268439552, |
|
266304, |
|
262144, |
|
266304, |
|
262144, |
|
268701696, |
|
4096, |
|
64, |
|
268697664, |
|
4096, |
|
266304, |
|
268439552, |
|
64, |
|
268435520, |
|
268697600, |
|
268697664, |
|
268435456, |
|
262144, |
|
268439616, |
|
0, |
|
268701760, |
|
262208, |
|
268435520, |
|
268697600, |
|
268439552, |
|
268439616, |
|
0, |
|
268701760, |
|
266240, |
|
266240, |
|
4160, |
|
4160, |
|
262208, |
|
268435456, |
|
268701696 |
|
]; |
|
/** |
|
* Create necessary sub keys. |
|
* |
|
* @param key the 64-bit or 192-bit key. |
|
* |
|
* @return the expanded keys. |
|
*/ function $ff4c3bd9116e15cc$var$_createKeys(key) { |
|
var pc2bytes0 = [ |
|
0, |
|
4, |
|
536870912, |
|
536870916, |
|
65536, |
|
65540, |
|
536936448, |
|
536936452, |
|
512, |
|
516, |
|
536871424, |
|
536871428, |
|
66048, |
|
66052, |
|
536936960, |
|
536936964 |
|
], pc2bytes1 = [ |
|
0, |
|
1, |
|
1048576, |
|
1048577, |
|
67108864, |
|
67108865, |
|
68157440, |
|
68157441, |
|
256, |
|
257, |
|
1048832, |
|
1048833, |
|
67109120, |
|
67109121, |
|
68157696, |
|
68157697 |
|
], pc2bytes2 = [ |
|
0, |
|
8, |
|
2048, |
|
2056, |
|
16777216, |
|
16777224, |
|
16779264, |
|
16779272, |
|
0, |
|
8, |
|
2048, |
|
2056, |
|
16777216, |
|
16777224, |
|
16779264, |
|
16779272 |
|
], pc2bytes3 = [ |
|
0, |
|
2097152, |
|
134217728, |
|
136314880, |
|
8192, |
|
2105344, |
|
134225920, |
|
136323072, |
|
131072, |
|
2228224, |
|
134348800, |
|
136445952, |
|
139264, |
|
2236416, |
|
134356992, |
|
136454144 |
|
], pc2bytes4 = [ |
|
0, |
|
262144, |
|
16, |
|
262160, |
|
0, |
|
262144, |
|
16, |
|
262160, |
|
4096, |
|
266240, |
|
4112, |
|
266256, |
|
4096, |
|
266240, |
|
4112, |
|
266256 |
|
], pc2bytes5 = [ |
|
0, |
|
1024, |
|
32, |
|
1056, |
|
0, |
|
1024, |
|
32, |
|
1056, |
|
33554432, |
|
33555456, |
|
33554464, |
|
33555488, |
|
33554432, |
|
33555456, |
|
33554464, |
|
33555488 |
|
], pc2bytes6 = [ |
|
0, |
|
268435456, |
|
524288, |
|
268959744, |
|
2, |
|
268435458, |
|
524290, |
|
268959746, |
|
0, |
|
268435456, |
|
524288, |
|
268959744, |
|
2, |
|
268435458, |
|
524290, |
|
268959746 |
|
], pc2bytes7 = [ |
|
0, |
|
65536, |
|
2048, |
|
67584, |
|
536870912, |
|
536936448, |
|
536872960, |
|
536938496, |
|
131072, |
|
196608, |
|
133120, |
|
198656, |
|
537001984, |
|
537067520, |
|
537004032, |
|
537069568 |
|
], pc2bytes8 = [ |
|
0, |
|
262144, |
|
0, |
|
262144, |
|
2, |
|
262146, |
|
2, |
|
262146, |
|
33554432, |
|
33816576, |
|
33554432, |
|
33816576, |
|
33554434, |
|
33816578, |
|
33554434, |
|
33816578 |
|
], pc2bytes9 = [ |
|
0, |
|
268435456, |
|
8, |
|
268435464, |
|
0, |
|
268435456, |
|
8, |
|
268435464, |
|
1024, |
|
268436480, |
|
1032, |
|
268436488, |
|
1024, |
|
268436480, |
|
1032, |
|
268436488 |
|
], pc2bytes10 = [ |
|
0, |
|
32, |
|
0, |
|
32, |
|
1048576, |
|
1048608, |
|
1048576, |
|
1048608, |
|
8192, |
|
8224, |
|
8192, |
|
8224, |
|
1056768, |
|
1056800, |
|
1056768, |
|
1056800 |
|
], pc2bytes11 = [ |
|
0, |
|
16777216, |
|
512, |
|
16777728, |
|
2097152, |
|
18874368, |
|
2097664, |
|
18874880, |
|
67108864, |
|
83886080, |
|
67109376, |
|
83886592, |
|
69206016, |
|
85983232, |
|
69206528, |
|
85983744 |
|
], pc2bytes12 = [ |
|
0, |
|
4096, |
|
134217728, |
|
134221824, |
|
524288, |
|
528384, |
|
134742016, |
|
134746112, |
|
16, |
|
4112, |
|
134217744, |
|
134221840, |
|
524304, |
|
528400, |
|
134742032, |
|
134746128 |
|
], pc2bytes13 = [ |
|
0, |
|
4, |
|
256, |
|
260, |
|
0, |
|
4, |
|
256, |
|
260, |
|
1, |
|
5, |
|
257, |
|
261, |
|
1, |
|
5, |
|
257, |
|
261 |
|
]; |
|
// how many iterations (1 for des, 3 for triple des) |
|
// changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys |
|
var iterations = key.length() > 8 ? 3 : 1; |
|
// stores the return keys |
|
var keys = []; |
|
// now define the left shifts which need to be done |
|
var shifts = [ |
|
0, |
|
0, |
|
1, |
|
1, |
|
1, |
|
1, |
|
1, |
|
1, |
|
0, |
|
1, |
|
1, |
|
1, |
|
1, |
|
1, |
|
1, |
|
0 |
|
]; |
|
var n = 0, tmp; |
|
for(var j = 0; j < iterations; j++){ |
|
var left = key.getInt32(); |
|
var right = key.getInt32(); |
|
tmp = (left >>> 4 ^ right) & 252645135; |
|
right ^= tmp; |
|
left ^= tmp << 4; |
|
tmp = (right >>> -16 ^ left) & 65535; |
|
left ^= tmp; |
|
right ^= tmp << -16; |
|
tmp = (left >>> 2 ^ right) & 858993459; |
|
right ^= tmp; |
|
left ^= tmp << 2; |
|
tmp = (right >>> -16 ^ left) & 65535; |
|
left ^= tmp; |
|
right ^= tmp << -16; |
|
tmp = (left >>> 1 ^ right) & 1431655765; |
|
right ^= tmp; |
|
left ^= tmp << 1; |
|
tmp = (right >>> 8 ^ left) & 16711935; |
|
left ^= tmp; |
|
right ^= tmp << 8; |
|
tmp = (left >>> 1 ^ right) & 1431655765; |
|
right ^= tmp; |
|
left ^= tmp << 1; |
|
// right needs to be shifted and OR'd with last four bits of left |
|
tmp = left << 8 | right >>> 20 & 240; |
|
// left needs to be put upside down |
|
left = right << 24 | right << 8 & 16711680 | right >>> 8 & 65280 | right >>> 24 & 240; |
|
right = tmp; |
|
// now go through and perform these shifts on the left and right keys |
|
for(var i = 0; i < shifts.length; ++i){ |
|
//shift the keys either one or two bits to the left |
|
if (shifts[i]) { |
|
left = left << 2 | left >>> 26; |
|
right = right << 2 | right >>> 26; |
|
} else { |
|
left = left << 1 | left >>> 27; |
|
right = right << 1 | right >>> 27; |
|
} |
|
left &= -15; |
|
right &= -15; |
|
// now apply PC-2, in such a way that E is easier when encrypting or |
|
// decrypting this conversion will look like PC-2 except only the last 6 |
|
// bits of each byte are used rather than 48 consecutive bits and the |
|
// order of lines will be according to how the S selection functions will |
|
// be applied: S2, S4, S6, S8, S1, S3, S5, S7 |
|
var lefttmp = pc2bytes0[left >>> 28] | pc2bytes1[left >>> 24 & 15] | pc2bytes2[left >>> 20 & 15] | pc2bytes3[left >>> 16 & 15] | pc2bytes4[left >>> 12 & 15] | pc2bytes5[left >>> 8 & 15] | pc2bytes6[left >>> 4 & 15]; |
|
var righttmp = pc2bytes7[right >>> 28] | pc2bytes8[right >>> 24 & 15] | pc2bytes9[right >>> 20 & 15] | pc2bytes10[right >>> 16 & 15] | pc2bytes11[right >>> 12 & 15] | pc2bytes12[right >>> 8 & 15] | pc2bytes13[right >>> 4 & 15]; |
|
tmp = (righttmp >>> 16 ^ lefttmp) & 65535; |
|
keys[n++] = lefttmp ^ tmp; |
|
keys[n++] = righttmp ^ tmp << 16; |
|
} |
|
} |
|
return keys; |
|
} |
|
/** |
|
* Updates a single block (1 byte) using DES. The update will either |
|
* encrypt or decrypt the block. |
|
* |
|
* @param keys the expanded keys. |
|
* @param input the input block (an array of 32-bit words). |
|
* @param output the updated output block. |
|
* @param decrypt true to decrypt the block, false to encrypt it. |
|
*/ function $ff4c3bd9116e15cc$var$_updateBlock(keys, input, output, decrypt) { |
|
// set up loops for single or triple DES |
|
var iterations = keys.length === 32 ? 3 : 9; |
|
var looping; |
|
if (iterations === 3) looping = decrypt ? [ |
|
30, |
|
-2, |
|
-2 |
|
] : [ |
|
0, |
|
32, |
|
2 |
|
]; |
|
else looping = decrypt ? [ |
|
94, |
|
62, |
|
-2, |
|
32, |
|
64, |
|
2, |
|
30, |
|
-2, |
|
-2 |
|
] : [ |
|
0, |
|
32, |
|
2, |
|
62, |
|
30, |
|
-2, |
|
64, |
|
96, |
|
2 |
|
]; |
|
var tmp; |
|
var left = input[0]; |
|
var right = input[1]; |
|
// first each 64 bit chunk of the message must be permuted according to IP |
|
tmp = (left >>> 4 ^ right) & 252645135; |
|
right ^= tmp; |
|
left ^= tmp << 4; |
|
tmp = (left >>> 16 ^ right) & 65535; |
|
right ^= tmp; |
|
left ^= tmp << 16; |
|
tmp = (right >>> 2 ^ left) & 858993459; |
|
left ^= tmp; |
|
right ^= tmp << 2; |
|
tmp = (right >>> 8 ^ left) & 16711935; |
|
left ^= tmp; |
|
right ^= tmp << 8; |
|
tmp = (left >>> 1 ^ right) & 1431655765; |
|
right ^= tmp; |
|
left ^= tmp << 1; |
|
// rotate left 1 bit |
|
left = left << 1 | left >>> 31; |
|
right = right << 1 | right >>> 31; |
|
for(var j = 0; j < iterations; j += 3){ |
|
var endloop = looping[j + 1]; |
|
var loopinc = looping[j + 2]; |
|
// now go through and perform the encryption or decryption |
|
for(var i = looping[j]; i != endloop; i += loopinc){ |
|
var right1 = right ^ keys[i]; |
|
var right2 = (right >>> 4 | right << 28) ^ keys[i + 1]; |
|
// passing these bytes through the S selection functions |
|
tmp = left; |
|
left = right; |
|
right = tmp ^ ($ff4c3bd9116e15cc$var$spfunction2[right1 >>> 24 & 63] | $ff4c3bd9116e15cc$var$spfunction4[right1 >>> 16 & 63] | $ff4c3bd9116e15cc$var$spfunction6[right1 >>> 8 & 63] | $ff4c3bd9116e15cc$var$spfunction8[right1 & 63] | $ff4c3bd9116e15cc$var$spfunction1[right2 >>> 24 & 63] | $ff4c3bd9116e15cc$var$spfunction3[right2 >>> 16 & 63] | $ff4c3bd9116e15cc$var$spfunction5[right2 >>> 8 & 63] | $ff4c3bd9116e15cc$var$spfunction7[right2 & 63]); |
|
} |
|
// unreverse left and right |
|
tmp = left; |
|
left = right; |
|
right = tmp; |
|
} |
|
// rotate right 1 bit |
|
left = left >>> 1 | left << 31; |
|
right = right >>> 1 | right << 31; |
|
// now perform IP-1, which is IP in the opposite direction |
|
tmp = (left >>> 1 ^ right) & 1431655765; |
|
right ^= tmp; |
|
left ^= tmp << 1; |
|
tmp = (right >>> 8 ^ left) & 16711935; |
|
left ^= tmp; |
|
right ^= tmp << 8; |
|
tmp = (right >>> 2 ^ left) & 858993459; |
|
left ^= tmp; |
|
right ^= tmp << 2; |
|
tmp = (left >>> 16 ^ right) & 65535; |
|
right ^= tmp; |
|
left ^= tmp << 16; |
|
tmp = (left >>> 4 ^ right) & 252645135; |
|
right ^= tmp; |
|
left ^= tmp << 4; |
|
output[0] = left; |
|
output[1] = right; |
|
} |
|
/** |
|
* Deprecated. Instead, use: |
|
* |
|
* forge.cipher.createCipher('DES-<mode>', key); |
|
* forge.cipher.createDecipher('DES-<mode>', key); |
|
* |
|
* Creates a deprecated DES cipher object. This object's mode will default to |
|
* CBC (cipher-block-chaining). |
|
* |
|
* The key may be given as a binary-encoded string of bytes or a byte buffer. |
|
* |
|
* @param options the options to use. |
|
* key the symmetric key to use (64 or 192 bits). |
|
* output the buffer to write to. |
|
* decrypt true for decryption, false for encryption. |
|
* mode the cipher mode to use (default: 'CBC'). |
|
* |
|
* @return the cipher. |
|
*/ function $ff4c3bd9116e15cc$var$_createCipher(options1) { |
|
options1 = options1 || { |
|
}; |
|
var mode = (options1.mode || 'CBC').toUpperCase(); |
|
var algorithm = 'DES-' + mode; |
|
var cipher; |
|
if (options1.decrypt) cipher = $iGlOy.cipher.createDecipher(algorithm, options1.key); |
|
else cipher = $iGlOy.cipher.createCipher(algorithm, options1.key); |
|
// backwards compatible start API |
|
var start = cipher.start; |
|
cipher.start = function(iv, options) { |
|
// backwards compatibility: support second arg as output buffer |
|
var output = null; |
|
if (options instanceof $iGlOy.util.ByteBuffer) { |
|
output = options; |
|
options = { |
|
}; |
|
} |
|
options = options || { |
|
}; |
|
options.output = output; |
|
options.iv = iv; |
|
start.call(cipher, options); |
|
}; |
|
return cipher; |
|
} |
|
|
|
|
|
parcelRequire("ai0Z9"); |
|
|
|
var $7436abf0cf29a7b7$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
parcelRequire("ai0Z9"); |
|
|
|
var $7436abf0cf29a7b7$var$pkcs5 = $iGlOy.pkcs5 = $iGlOy.pkcs5 || { |
|
}; |
|
var $7436abf0cf29a7b7$var$crypto; |
|
|
|
if ($iGlOy.util.isNodejs && !$iGlOy.options.usePureJavaScript) $7436abf0cf29a7b7$var$crypto = $8C1kk$crypto; |
|
/** |
|
* Derives a key from a password. |
|
* |
|
* @param p the password as a binary-encoded string of bytes. |
|
* @param s the salt as a binary-encoded string of bytes. |
|
* @param c the iteration count, a positive integer. |
|
* @param dkLen the intended length, in bytes, of the derived key, |
|
* (max: 2^32 - 1) * hash length of the PRF. |
|
* @param [md] the message digest (or algorithm identifier as a string) to use |
|
* in the PRF, defaults to SHA-1. |
|
* @param [callback(err, key)] presence triggers asynchronous version, called |
|
* once the operation completes. |
|
* |
|
* @return the derived key, as a binary-encoded string of bytes, for the |
|
* synchronous version (if no callback is specified). |
|
*/ $7436abf0cf29a7b7$exports = $iGlOy.pbkdf2 = $7436abf0cf29a7b7$var$pkcs5.pbkdf2 = function(p, s, c, dkLen, md, callback) { |
|
if (typeof md === 'function') { |
|
callback = md; |
|
md = null; |
|
} |
|
// use native implementation if possible and not disabled, note that |
|
// some node versions only support SHA-1, others allow digest to be changed |
|
if ($iGlOy.util.isNodejs && !$iGlOy.options.usePureJavaScript && $7436abf0cf29a7b7$var$crypto.pbkdf2 && (md === null || typeof md !== 'object') && ($7436abf0cf29a7b7$var$crypto.pbkdf2Sync.length > 4 || !md || md === 'sha1')) { |
|
if (typeof md !== 'string') // default prf to SHA-1 |
|
md = 'sha1'; |
|
p = Buffer.from(p, 'binary'); |
|
s = Buffer.from(s, 'binary'); |
|
if (!callback) { |
|
if ($7436abf0cf29a7b7$var$crypto.pbkdf2Sync.length === 4) return $7436abf0cf29a7b7$var$crypto.pbkdf2Sync(p, s, c, dkLen).toString('binary'); |
|
return $7436abf0cf29a7b7$var$crypto.pbkdf2Sync(p, s, c, dkLen, md).toString('binary'); |
|
} |
|
if ($7436abf0cf29a7b7$var$crypto.pbkdf2Sync.length === 4) return $7436abf0cf29a7b7$var$crypto.pbkdf2(p, s, c, dkLen, function(err, key) { |
|
if (err) return callback(err); |
|
callback(null, key.toString('binary')); |
|
}); |
|
return $7436abf0cf29a7b7$var$crypto.pbkdf2(p, s, c, dkLen, md, function(err, key) { |
|
if (err) return callback(err); |
|
callback(null, key.toString('binary')); |
|
}); |
|
} |
|
if (typeof md === 'undefined' || md === null) // default prf to SHA-1 |
|
md = 'sha1'; |
|
if (typeof md === 'string') { |
|
if (!(md in $iGlOy.md.algorithms)) throw new Error('Unknown hash algorithm: ' + md); |
|
md = $iGlOy.md[md].create(); |
|
} |
|
var hLen = md.digestLength; |
|
/* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and |
|
stop. */ if (dkLen > 4294967295 * hLen) { |
|
var err1 = new Error('Derived key is too long.'); |
|
if (callback) return callback(err1); |
|
throw err1; |
|
} |
|
/* 2. Let len be the number of hLen-octet blocks in the derived key, |
|
rounding up, and let r be the number of octets in the last |
|
block: |
|
|
|
len = CEIL(dkLen / hLen), |
|
r = dkLen - (len - 1) * hLen. */ var len = Math.ceil(dkLen / hLen); |
|
var r = dkLen - (len - 1) * hLen; |
|
/* 3. For each block of the derived key apply the function F defined |
|
below to the password P, the salt S, the iteration count c, and |
|
the block index to compute the block: |
|
|
|
T_1 = F(P, S, c, 1), |
|
T_2 = F(P, S, c, 2), |
|
... |
|
T_len = F(P, S, c, len), |
|
|
|
where the function F is defined as the exclusive-or sum of the |
|
first c iterates of the underlying pseudorandom function PRF |
|
applied to the password P and the concatenation of the salt S |
|
and the block index i: |
|
|
|
F(P, S, c, i) = u_1 XOR u_2 XOR ... XOR u_c |
|
|
|
where |
|
|
|
u_1 = PRF(P, S || INT(i)), |
|
u_2 = PRF(P, u_1), |
|
... |
|
u_c = PRF(P, u_{c-1}). |
|
|
|
Here, INT(i) is a four-octet encoding of the integer i, most |
|
significant octet first. */ var prf = $iGlOy.hmac.create(); |
|
prf.start(md, p); |
|
var dk = ''; |
|
var xor, u_c, u_c1; |
|
// sync version |
|
if (!callback) { |
|
for(var i = 1; i <= len; ++i){ |
|
// PRF(P, S || INT(i)) (first iteration) |
|
prf.start(null, null); |
|
prf.update(s); |
|
prf.update($iGlOy.util.int32ToBytes(i)); |
|
xor = u_c1 = prf.digest().getBytes(); |
|
// PRF(P, u_{c-1}) (other iterations) |
|
for(var j = 2; j <= c; ++j){ |
|
prf.start(null, null); |
|
prf.update(u_c1); |
|
u_c = prf.digest().getBytes(); |
|
// F(p, s, c, i) |
|
xor = $iGlOy.util.xorBytes(xor, u_c, hLen); |
|
u_c1 = u_c; |
|
} |
|
/* 4. Concatenate the blocks and extract the first dkLen octets to |
|
produce a derived key DK: |
|
|
|
DK = T_1 || T_2 || ... || T_len<0..r-1> */ dk += i < len ? xor : xor.substr(0, r); |
|
} |
|
/* 5. Output the derived key DK. */ return dk; |
|
} |
|
// async version |
|
var i = 1, j; |
|
function outer() { |
|
if (i > len) // done |
|
return callback(null, dk); |
|
// PRF(P, S || INT(i)) (first iteration) |
|
prf.start(null, null); |
|
prf.update(s); |
|
prf.update($iGlOy.util.int32ToBytes(i)); |
|
xor = u_c1 = prf.digest().getBytes(); |
|
// PRF(P, u_{c-1}) (other iterations) |
|
j = 2; |
|
inner(); |
|
} |
|
function inner() { |
|
if (j <= c) { |
|
prf.start(null, null); |
|
prf.update(u_c1); |
|
u_c = prf.digest().getBytes(); |
|
// F(p, s, c, i) |
|
xor = $iGlOy.util.xorBytes(xor, u_c, hLen); |
|
u_c1 = u_c; |
|
++j; |
|
return $iGlOy.util.setImmediate(inner); |
|
} |
|
/* 4. Concatenate the blocks and extract the first dkLen octets to |
|
produce a derived key DK: |
|
|
|
DK = T_1 || T_2 || ... || T_len<0..r-1> */ dk += i < len ? xor : xor.substr(0, r); |
|
++i; |
|
outer(); |
|
} |
|
outer(); |
|
}; |
|
|
|
|
|
|
|
var $b9b57fce3e6d85ef$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
var $e523b90a804c5bd3$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
parcelRequire("ai0Z9"); |
|
|
|
var $e523b90a804c5bd3$var$sha256 = $e523b90a804c5bd3$exports = $iGlOy.sha256 = $iGlOy.sha256 || { |
|
}; |
|
$iGlOy.md.sha256 = $iGlOy.md.algorithms.sha256 = $e523b90a804c5bd3$var$sha256; |
|
/** |
|
* Creates a SHA-256 message digest object. |
|
* |
|
* @return a message digest object. |
|
*/ $e523b90a804c5bd3$var$sha256.create = function() { |
|
// do initialization as necessary |
|
if (!$e523b90a804c5bd3$var$_initialized) $e523b90a804c5bd3$var$_init(); |
|
// SHA-256 state contains eight 32-bit integers |
|
var _state = null; |
|
// input buffer |
|
var _input = $iGlOy.util.createBuffer(); |
|
// used for word storage |
|
var _w = new Array(64); |
|
// message digest object |
|
var md = { |
|
algorithm: 'sha256', |
|
blockLength: 64, |
|
digestLength: 32, |
|
// 56-bit length of message so far (does not including padding) |
|
messageLength: 0, |
|
// true message length |
|
fullMessageLength: null, |
|
// size of message length in bytes |
|
messageLengthSize: 8 |
|
}; |
|
/** |
|
* Starts the digest. |
|
* |
|
* @return this digest object. |
|
*/ md.start = function() { |
|
// up to 56-bit message length for convenience |
|
md.messageLength = 0; |
|
// full message length (set md.messageLength64 for backwards-compatibility) |
|
md.fullMessageLength = md.messageLength64 = []; |
|
var int32s = md.messageLengthSize / 4; |
|
for(var i = 0; i < int32s; ++i)md.fullMessageLength.push(0); |
|
_input = $iGlOy.util.createBuffer(); |
|
_state = { |
|
h0: 1779033703, |
|
h1: 3144134277, |
|
h2: 1013904242, |
|
h3: 2773480762, |
|
h4: 1359893119, |
|
h5: 2600822924, |
|
h6: 528734635, |
|
h7: 1541459225 |
|
}; |
|
return md; |
|
}; |
|
// start digest automatically for first time |
|
md.start(); |
|
/** |
|
* Updates the digest with the given message input. The given input can |
|
* treated as raw input (no encoding will be applied) or an encoding of |
|
* 'utf8' maybe given to encode the input using UTF-8. |
|
* |
|
* @param msg the message input to update with. |
|
* @param encoding the encoding to use (default: 'raw', other: 'utf8'). |
|
* |
|
* @return this digest object. |
|
*/ md.update = function(msg, encoding) { |
|
if (encoding === 'utf8') msg = $iGlOy.util.encodeUtf8(msg); |
|
// update message length |
|
var len = msg.length; |
|
md.messageLength += len; |
|
len = [ |
|
len / 4294967296 >>> 0, |
|
len >>> 0 |
|
]; |
|
for(var i = md.fullMessageLength.length - 1; i >= 0; --i){ |
|
md.fullMessageLength[i] += len[1]; |
|
len[1] = len[0] + (md.fullMessageLength[i] / 4294967296 >>> 0); |
|
md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; |
|
len[0] = len[1] / 4294967296 >>> 0; |
|
} |
|
// add bytes to input buffer |
|
_input.putBytes(msg); |
|
// process bytes |
|
$e523b90a804c5bd3$var$_update(_state, _w, _input); |
|
// compact input buffer every 2K or if empty |
|
if (_input.read > 2048 || _input.length() === 0) _input.compact(); |
|
return md; |
|
}; |
|
/** |
|
* Produces the digest. |
|
* |
|
* @return a byte buffer containing the digest value. |
|
*/ md.digest = function() { |
|
/* Note: Here we copy the remaining bytes in the input buffer and |
|
add the appropriate SHA-256 padding. Then we do the final update |
|
on a copy of the state so that if the user wants to get |
|
intermediate digests they can do so. */ /* Determine the number of bytes that must be added to the message |
|
to ensure its length is congruent to 448 mod 512. In other words, |
|
the data to be digested must be a multiple of 512 bits (or 128 bytes). |
|
This data includes the message, some padding, and the length of the |
|
message. Since the length of the message will be encoded as 8 bytes (64 |
|
bits), that means that the last segment of the data must have 56 bytes |
|
(448 bits) of message and padding. Therefore, the length of the message |
|
plus the padding must be congruent to 448 mod 512 because |
|
512 - 128 = 448. |
|
|
|
In order to fill up the message length it must be filled with |
|
padding that begins with 1 bit followed by all 0 bits. Padding |
|
must *always* be present, so if the message length is already |
|
congruent to 448 mod 512, then 512 padding bits must be added. */ var finalBlock = $iGlOy.util.createBuffer(); |
|
finalBlock.putBytes(_input.bytes()); |
|
// compute remaining size to be digested (include message length size) |
|
var remaining = md.fullMessageLength[md.fullMessageLength.length - 1] + md.messageLengthSize; |
|
// add padding for overflow blockSize - overflow |
|
// _padding starts with 1 byte with first bit is set (byte value 128), then |
|
// there may be up to (blockSize - 1) other pad bytes |
|
var overflow = remaining & md.blockLength - 1; |
|
finalBlock.putBytes($e523b90a804c5bd3$var$_padding.substr(0, md.blockLength - overflow)); |
|
// serialize message length in bits in big-endian order; since length |
|
// is stored in bytes we multiply by 8 and add carry from next int |
|
var next, carry; |
|
var bits = md.fullMessageLength[0] * 8; |
|
for(var i = 0; i < md.fullMessageLength.length - 1; ++i){ |
|
next = md.fullMessageLength[i + 1] * 8; |
|
carry = next / 4294967296 >>> 0; |
|
bits += carry; |
|
finalBlock.putInt32(bits >>> 0); |
|
bits = next >>> 0; |
|
} |
|
finalBlock.putInt32(bits); |
|
var s2 = { |
|
h0: _state.h0, |
|
h1: _state.h1, |
|
h2: _state.h2, |
|
h3: _state.h3, |
|
h4: _state.h4, |
|
h5: _state.h5, |
|
h6: _state.h6, |
|
h7: _state.h7 |
|
}; |
|
$e523b90a804c5bd3$var$_update(s2, _w, finalBlock); |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putInt32(s2.h0); |
|
rval.putInt32(s2.h1); |
|
rval.putInt32(s2.h2); |
|
rval.putInt32(s2.h3); |
|
rval.putInt32(s2.h4); |
|
rval.putInt32(s2.h5); |
|
rval.putInt32(s2.h6); |
|
rval.putInt32(s2.h7); |
|
return rval; |
|
}; |
|
return md; |
|
}; |
|
// sha-256 padding bytes not initialized yet |
|
var $e523b90a804c5bd3$var$_padding = null; |
|
var $e523b90a804c5bd3$var$_initialized = false; |
|
// table of constants |
|
var $e523b90a804c5bd3$var$_k = null; |
|
/** |
|
* Initializes the constant tables. |
|
*/ function $e523b90a804c5bd3$var$_init() { |
|
// create padding |
|
$e523b90a804c5bd3$var$_padding = String.fromCharCode(128); |
|
$e523b90a804c5bd3$var$_padding += $iGlOy.util.fillString(String.fromCharCode(0), 64); |
|
// create K table for SHA-256 |
|
$e523b90a804c5bd3$var$_k = [ |
|
1116352408, |
|
1899447441, |
|
3049323471, |
|
3921009573, |
|
961987163, |
|
1508970993, |
|
2453635748, |
|
2870763221, |
|
3624381080, |
|
310598401, |
|
607225278, |
|
1426881987, |
|
1925078388, |
|
2162078206, |
|
2614888103, |
|
3248222580, |
|
3835390401, |
|
4022224774, |
|
264347078, |
|
604807628, |
|
770255983, |
|
1249150122, |
|
1555081692, |
|
1996064986, |
|
2554220882, |
|
2821834349, |
|
2952996808, |
|
3210313671, |
|
3336571891, |
|
3584528711, |
|
113926993, |
|
338241895, |
|
666307205, |
|
773529912, |
|
1294757372, |
|
1396182291, |
|
1695183700, |
|
1986661051, |
|
2177026350, |
|
2456956037, |
|
2730485921, |
|
2820302411, |
|
3259730800, |
|
3345764771, |
|
3516065817, |
|
3600352804, |
|
4094571909, |
|
275423344, |
|
430227734, |
|
506948616, |
|
659060556, |
|
883997877, |
|
958139571, |
|
1322822218, |
|
1537002063, |
|
1747873779, |
|
1955562222, |
|
2024104815, |
|
2227730452, |
|
2361852424, |
|
2428436474, |
|
2756734187, |
|
3204031479, |
|
3329325298 |
|
]; |
|
// now initialized |
|
$e523b90a804c5bd3$var$_initialized = true; |
|
} |
|
/** |
|
* Updates a SHA-256 state with the given byte buffer. |
|
* |
|
* @param s the SHA-256 state to update. |
|
* @param w the array to use to store words. |
|
* @param bytes the byte buffer to update with. |
|
*/ function $e523b90a804c5bd3$var$_update(s, w, bytes) { |
|
// consume 512 bit (64 byte) chunks |
|
var t1, t2, s0, s1, ch, maj, i, a, b, c, d, e, f, g, h; |
|
var len = bytes.length(); |
|
while(len >= 64){ |
|
// the w array will be populated with sixteen 32-bit big-endian words |
|
// and then extended into 64 32-bit words according to SHA-256 |
|
for(i = 0; i < 16; ++i)w[i] = bytes.getInt32(); |
|
for(; i < 64; ++i){ |
|
// XOR word 2 words ago rot right 17, rot right 19, shft right 10 |
|
t1 = w[i - 2]; |
|
t1 = (t1 >>> 17 | t1 << 15) ^ (t1 >>> 19 | t1 << 13) ^ t1 >>> 10; |
|
// XOR word 15 words ago rot right 7, rot right 18, shft right 3 |
|
t2 = w[i - 15]; |
|
t2 = (t2 >>> 7 | t2 << 25) ^ (t2 >>> 18 | t2 << 14) ^ t2 >>> 3; |
|
// sum(t1, word 7 ago, t2, word 16 ago) modulo 2^32 |
|
w[i] = t1 + w[i - 7] + t2 + w[i - 16] | 0; |
|
} |
|
// initialize hash value for this chunk |
|
a = s.h0; |
|
b = s.h1; |
|
c = s.h2; |
|
d = s.h3; |
|
e = s.h4; |
|
f = s.h5; |
|
g = s.h6; |
|
h = s.h7; |
|
// round function |
|
for(i = 0; i < 64; ++i){ |
|
// Sum1(e) |
|
s1 = (e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7); |
|
// Ch(e, f, g) (optimized the same way as SHA-1) |
|
ch = g ^ e & (f ^ g); |
|
// Sum0(a) |
|
s0 = (a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10); |
|
// Maj(a, b, c) (optimized the same way as SHA-1) |
|
maj = a & b | c & (a ^ b); |
|
// main algorithm |
|
t1 = h + s1 + ch + $e523b90a804c5bd3$var$_k[i] + w[i]; |
|
t2 = s0 + maj; |
|
h = g; |
|
g = f; |
|
f = e; |
|
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug |
|
// can't truncate with `| 0` |
|
e = d + t1 >>> 0; |
|
d = c; |
|
c = b; |
|
b = a; |
|
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug |
|
// can't truncate with `| 0` |
|
a = t1 + t2 >>> 0; |
|
} |
|
// update hash state |
|
s.h0 = s.h0 + a | 0; |
|
s.h1 = s.h1 + b | 0; |
|
s.h2 = s.h2 + c | 0; |
|
s.h3 = s.h3 + d | 0; |
|
s.h4 = s.h4 + e | 0; |
|
s.h5 = s.h5 + f | 0; |
|
s.h6 = s.h6 + g | 0; |
|
s.h7 = s.h7 + h | 0; |
|
len -= 64; |
|
} |
|
} |
|
|
|
|
|
var $c761b0edb959b99a$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
var $c761b0edb959b99a$var$_crypto = null; |
|
|
|
if ($iGlOy.util.isNodejs && !$iGlOy.options.usePureJavaScript && !process.versions['node-webkit']) $c761b0edb959b99a$var$_crypto = $8C1kk$crypto; |
|
/* PRNG API */ var $c761b0edb959b99a$var$prng = $c761b0edb959b99a$exports = $iGlOy.prng = $iGlOy.prng || { |
|
}; |
|
/** |
|
* Creates a new PRNG context. |
|
* |
|
* A PRNG plugin must be passed in that will provide: |
|
* |
|
* 1. A function that initializes the key and seed of a PRNG context. It |
|
* will be given a 16 byte key and a 16 byte seed. Any key expansion |
|
* or transformation of the seed from a byte string into an array of |
|
* integers (or similar) should be performed. |
|
* 2. The cryptographic function used by the generator. It takes a key and |
|
* a seed. |
|
* 3. A seed increment function. It takes the seed and returns seed + 1. |
|
* 4. An api to create a message digest. |
|
* |
|
* For an example, see random.js. |
|
* |
|
* @param plugin the PRNG plugin to use. |
|
*/ $c761b0edb959b99a$var$prng.create = function(plugin) { |
|
var ctx = { |
|
plugin: plugin, |
|
key: null, |
|
seed: null, |
|
time: null, |
|
// number of reseeds so far |
|
reseeds: 0, |
|
// amount of data generated so far |
|
generated: 0, |
|
// no initial key bytes |
|
keyBytes: '' |
|
}; |
|
// create 32 entropy pools (each is a message digest) |
|
var md1 = plugin.md; |
|
var pools = new Array(32); |
|
for(var i1 = 0; i1 < 32; ++i1)pools[i1] = md1.create(); |
|
ctx.pools = pools; |
|
// entropy pools are written to cyclically, starting at index 0 |
|
ctx.pool = 0; |
|
/** |
|
* Generates random bytes. The bytes may be generated synchronously or |
|
* asynchronously. Web workers must use the asynchronous interface or |
|
* else the behavior is undefined. |
|
* |
|
* @param count the number of random bytes to generate. |
|
* @param [callback(err, bytes)] called once the operation completes. |
|
* |
|
* @return count random bytes as a string. |
|
*/ ctx.generate = function(count, callback) { |
|
// do synchronously |
|
if (!callback) return ctx.generateSync(count); |
|
// simple generator using counter-based CBC |
|
var cipher = ctx.plugin.cipher; |
|
var increment = ctx.plugin.increment; |
|
var formatKey = ctx.plugin.formatKey; |
|
var formatSeed = ctx.plugin.formatSeed; |
|
var b = $iGlOy.util.createBuffer(); |
|
// paranoid deviation from Fortuna: |
|
// reset key for every request to protect previously |
|
// generated random bytes should the key be discovered; |
|
// there is no 100ms based reseeding because of this |
|
// forced reseed for every `generate` call |
|
ctx.key = null; |
|
generate(); |
|
function generate(err) { |
|
if (err) return callback(err); |
|
// sufficient bytes generated |
|
if (b.length() >= count) return callback(null, b.getBytes(count)); |
|
// if amount of data generated is greater than 1 MiB, trigger reseed |
|
if (ctx.generated > 1048575) ctx.key = null; |
|
if (ctx.key === null) // prevent stack overflow |
|
return $iGlOy.util.nextTick(function() { |
|
_reseed(generate); |
|
}); |
|
// generate the random bytes |
|
var bytes = cipher(ctx.key, ctx.seed); |
|
ctx.generated += bytes.length; |
|
b.putBytes(bytes); |
|
// generate bytes for a new key and seed |
|
ctx.key = formatKey(cipher(ctx.key, increment(ctx.seed))); |
|
ctx.seed = formatSeed(cipher(ctx.key, ctx.seed)); |
|
$iGlOy.util.setImmediate(generate); |
|
} |
|
}; |
|
/** |
|
* Generates random bytes synchronously. |
|
* |
|
* @param count the number of random bytes to generate. |
|
* |
|
* @return count random bytes as a string. |
|
*/ ctx.generateSync = function(count) { |
|
// simple generator using counter-based CBC |
|
var cipher = ctx.plugin.cipher; |
|
var increment = ctx.plugin.increment; |
|
var formatKey = ctx.plugin.formatKey; |
|
var formatSeed = ctx.plugin.formatSeed; |
|
// paranoid deviation from Fortuna: |
|
// reset key for every request to protect previously |
|
// generated random bytes should the key be discovered; |
|
// there is no 100ms based reseeding because of this |
|
// forced reseed for every `generateSync` call |
|
ctx.key = null; |
|
var b = $iGlOy.util.createBuffer(); |
|
while(b.length() < count){ |
|
// if amount of data generated is greater than 1 MiB, trigger reseed |
|
if (ctx.generated > 1048575) ctx.key = null; |
|
if (ctx.key === null) _reseedSync(); |
|
// generate the random bytes |
|
var bytes = cipher(ctx.key, ctx.seed); |
|
ctx.generated += bytes.length; |
|
b.putBytes(bytes); |
|
// generate bytes for a new key and seed |
|
ctx.key = formatKey(cipher(ctx.key, increment(ctx.seed))); |
|
ctx.seed = formatSeed(cipher(ctx.key, ctx.seed)); |
|
} |
|
return b.getBytes(count); |
|
}; |
|
/** |
|
* Private function that asynchronously reseeds a generator. |
|
* |
|
* @param callback(err) called once the operation completes. |
|
*/ function _reseed(callback) { |
|
if (ctx.pools[0].messageLength >= 32) { |
|
_seed(); |
|
return callback(); |
|
} |
|
// not enough seed data... |
|
var needed = 32 - ctx.pools[0].messageLength << 5; |
|
ctx.seedFile(needed, function(err, bytes) { |
|
if (err) return callback(err); |
|
ctx.collect(bytes); |
|
_seed(); |
|
callback(); |
|
}); |
|
} |
|
/** |
|
* Private function that synchronously reseeds a generator. |
|
*/ function _reseedSync() { |
|
if (ctx.pools[0].messageLength >= 32) return _seed(); |
|
// not enough seed data... |
|
var needed = 32 - ctx.pools[0].messageLength << 5; |
|
ctx.collect(ctx.seedFileSync(needed)); |
|
_seed(); |
|
} |
|
/** |
|
* Private function that seeds a generator once enough bytes are available. |
|
*/ function _seed() { |
|
// update reseed count |
|
ctx.reseeds = ctx.reseeds === 4294967295 ? 0 : ctx.reseeds + 1; |
|
// goal is to update `key` via: |
|
// key = hash(key + s) |
|
// where 's' is all collected entropy from selected pools, then... |
|
// create a plugin-based message digest |
|
var md = ctx.plugin.md.create(); |
|
// consume current key bytes |
|
md.update(ctx.keyBytes); |
|
// digest the entropy of pools whose index k meet the |
|
// condition 'n mod 2^k == 0' where n is the number of reseeds |
|
var _2powK = 1; |
|
for(var k = 0; k < 32; ++k){ |
|
if (ctx.reseeds % _2powK === 0) { |
|
md.update(ctx.pools[k].digest().getBytes()); |
|
ctx.pools[k].start(); |
|
} |
|
_2powK = _2powK << 1; |
|
} |
|
// get digest for key bytes |
|
ctx.keyBytes = md.digest().getBytes(); |
|
// paranoid deviation from Fortuna: |
|
// update `seed` via `seed = hash(key)` |
|
// instead of initializing to zero once and only |
|
// ever incrementing it |
|
md.start(); |
|
md.update(ctx.keyBytes); |
|
var seedBytes = md.digest().getBytes(); |
|
// update state |
|
ctx.key = ctx.plugin.formatKey(ctx.keyBytes); |
|
ctx.seed = ctx.plugin.formatSeed(seedBytes); |
|
ctx.generated = 0; |
|
} |
|
/** |
|
* The built-in default seedFile. This seedFile is used when entropy |
|
* is needed immediately. |
|
* |
|
* @param needed the number of bytes that are needed. |
|
* |
|
* @return the random bytes. |
|
*/ function defaultSeedFile(needed) { |
|
// use window.crypto.getRandomValues strong source of entropy if available |
|
var getRandomValues = null; |
|
var globalScope = $iGlOy.util.globalScope; |
|
var _crypto = globalScope.crypto || globalScope.msCrypto; |
|
if (_crypto && _crypto.getRandomValues) getRandomValues = function(arr) { |
|
return _crypto.getRandomValues(arr); |
|
}; |
|
var b = $iGlOy.util.createBuffer(); |
|
if (getRandomValues) while(b.length() < needed){ |
|
// max byte length is 65536 before QuotaExceededError is thrown |
|
// http://www.w3.org/TR/WebCryptoAPI/#RandomSource-method-getRandomValues |
|
var count = Math.max(1, Math.min(needed - b.length(), 65536) / 4); |
|
var entropy = new Uint32Array(Math.floor(count)); |
|
try { |
|
getRandomValues(entropy); |
|
for(var i = 0; i < entropy.length; ++i)b.putInt32(entropy[i]); |
|
} catch (e) { |
|
/* only ignore QuotaExceededError */ if (!(typeof QuotaExceededError !== 'undefined' && e instanceof QuotaExceededError)) throw e; |
|
} |
|
} |
|
// be sad and add some weak random data |
|
if (b.length() < needed) { |
|
/* Draws from Park-Miller "minimal standard" 31 bit PRNG, |
|
implemented with David G. Carta's optimization: with 32 bit math |
|
and without division (Public Domain). */ var hi, lo, next; |
|
var seed = Math.floor(Math.random() * 65536); |
|
while(b.length() < needed){ |
|
lo = 16807 * (seed & 65535); |
|
hi = 16807 * (seed >> 16); |
|
lo += (hi & 32767) << 16; |
|
lo += hi >> 15; |
|
lo = (lo & 2147483647) + (lo >> 31); |
|
seed = lo & 4294967295; |
|
// consume lower 3 bytes of seed |
|
for(var i = 0; i < 3; ++i){ |
|
// throw in more pseudo random |
|
next = seed >>> (i << 3); |
|
next ^= Math.floor(Math.random() * 256); |
|
b.putByte(next & 255); |
|
} |
|
} |
|
} |
|
return b.getBytes(needed); |
|
} |
|
// initialize seed file APIs |
|
if ($c761b0edb959b99a$var$_crypto) { |
|
// use nodejs async API |
|
ctx.seedFile = function(needed, callback) { |
|
$c761b0edb959b99a$var$_crypto.randomBytes(needed, function(err, bytes) { |
|
if (err) return callback(err); |
|
callback(null, bytes.toString()); |
|
}); |
|
}; |
|
// use nodejs sync API |
|
ctx.seedFileSync = function(needed) { |
|
return $c761b0edb959b99a$var$_crypto.randomBytes(needed).toString(); |
|
}; |
|
} else { |
|
ctx.seedFile = function(needed, callback) { |
|
try { |
|
callback(null, defaultSeedFile(needed)); |
|
} catch (e) { |
|
callback(e); |
|
} |
|
}; |
|
ctx.seedFileSync = defaultSeedFile; |
|
} |
|
/** |
|
* Adds entropy to a prng ctx's accumulator. |
|
* |
|
* @param bytes the bytes of entropy as a string. |
|
*/ ctx.collect = function(bytes) { |
|
// iterate over pools distributing entropy cyclically |
|
var count = bytes.length; |
|
for(var i = 0; i < count; ++i){ |
|
ctx.pools[ctx.pool].update(bytes.substr(i, 1)); |
|
ctx.pool = ctx.pool === 31 ? 0 : ctx.pool + 1; |
|
} |
|
}; |
|
/** |
|
* Collects an integer of n bits. |
|
* |
|
* @param i the integer entropy. |
|
* @param n the number of bits in the integer. |
|
*/ ctx.collectInt = function(i, n) { |
|
var bytes = ''; |
|
for(var x = 0; x < n; x += 8)bytes += String.fromCharCode(i >> x & 255); |
|
ctx.collect(bytes); |
|
}; |
|
/** |
|
* Registers a Web Worker to receive immediate entropy from the main thread. |
|
* This method is required until Web Workers can access the native crypto |
|
* API. This method should be called twice for each created worker, once in |
|
* the main thread, and once in the worker itself. |
|
* |
|
* @param worker the worker to register. |
|
*/ ctx.registerWorker = function(worker) { |
|
// worker receives random bytes |
|
if (worker === self) ctx.seedFile = function(needed, callback) { |
|
function listener(e) { |
|
var data = e.data; |
|
if (data.forge && data.forge.prng) { |
|
self.removeEventListener('message', listener); |
|
callback(data.forge.prng.err, data.forge.prng.bytes); |
|
} |
|
} |
|
self.addEventListener('message', listener); |
|
self.postMessage({ |
|
forge: { |
|
prng: { |
|
needed: needed |
|
} |
|
} |
|
}); |
|
}; |
|
else { |
|
// main thread sends random bytes upon request |
|
var listener1 = function(e) { |
|
var data = e.data; |
|
if (data.forge && data.forge.prng) ctx.seedFile(data.forge.prng.needed, function(err, bytes) { |
|
worker.postMessage({ |
|
forge: { |
|
prng: { |
|
err: err, |
|
bytes: bytes |
|
} |
|
} |
|
}); |
|
}); |
|
}; |
|
// TODO: do we need to remove the event listener when the worker dies? |
|
worker.addEventListener('message', listener1); |
|
} |
|
}; |
|
return ctx; |
|
}; |
|
|
|
|
|
|
|
(function() { |
|
// forge.random already defined |
|
if ($iGlOy.random && $iGlOy.random.getBytes) { |
|
$b9b57fce3e6d85ef$exports = $iGlOy.random; |
|
return; |
|
} |
|
(function(jQuery) { |
|
// the default prng plugin, uses AES-128 |
|
var prng_aes = { |
|
}; |
|
var _prng_aes_output = new Array(4); |
|
var _prng_aes_buffer = $iGlOy.util.createBuffer(); |
|
prng_aes.formatKey = function(key) { |
|
// convert the key into 32-bit integers |
|
var tmp = $iGlOy.util.createBuffer(key); |
|
key = new Array(4); |
|
key[0] = tmp.getInt32(); |
|
key[1] = tmp.getInt32(); |
|
key[2] = tmp.getInt32(); |
|
key[3] = tmp.getInt32(); |
|
// return the expanded key |
|
return $iGlOy.aes._expandKey(key, false); |
|
}; |
|
prng_aes.formatSeed = function(seed) { |
|
// convert seed into 32-bit integers |
|
var tmp = $iGlOy.util.createBuffer(seed); |
|
seed = new Array(4); |
|
seed[0] = tmp.getInt32(); |
|
seed[1] = tmp.getInt32(); |
|
seed[2] = tmp.getInt32(); |
|
seed[3] = tmp.getInt32(); |
|
return seed; |
|
}; |
|
prng_aes.cipher = function(key, seed) { |
|
$iGlOy.aes._updateBlock(key, seed, _prng_aes_output, false); |
|
_prng_aes_buffer.putInt32(_prng_aes_output[0]); |
|
_prng_aes_buffer.putInt32(_prng_aes_output[1]); |
|
_prng_aes_buffer.putInt32(_prng_aes_output[2]); |
|
_prng_aes_buffer.putInt32(_prng_aes_output[3]); |
|
return _prng_aes_buffer.getBytes(); |
|
}; |
|
prng_aes.increment = function(seed) { |
|
// FIXME: do we care about carry or signed issues? |
|
++seed[3]; |
|
return seed; |
|
}; |
|
prng_aes.md = $iGlOy.md.sha256; |
|
/** |
|
* Creates a new PRNG. |
|
*/ function spawnPrng() { |
|
var ctx = $iGlOy.prng.create(prng_aes); |
|
/** |
|
* Gets random bytes. If a native secure crypto API is unavailable, this |
|
* method tries to make the bytes more unpredictable by drawing from data that |
|
* can be collected from the user of the browser, eg: mouse movement. |
|
* |
|
* If a callback is given, this method will be called asynchronously. |
|
* |
|
* @param count the number of random bytes to get. |
|
* @param [callback(err, bytes)] called once the operation completes. |
|
* |
|
* @return the random bytes in a string. |
|
*/ ctx.getBytes = function(count, callback) { |
|
return ctx.generate(count, callback); |
|
}; |
|
/** |
|
* Gets random bytes asynchronously. If a native secure crypto API is |
|
* unavailable, this method tries to make the bytes more unpredictable by |
|
* drawing from data that can be collected from the user of the browser, |
|
* eg: mouse movement. |
|
* |
|
* @param count the number of random bytes to get. |
|
* |
|
* @return the random bytes in a string. |
|
*/ ctx.getBytesSync = function(count) { |
|
return ctx.generate(count); |
|
}; |
|
return ctx; |
|
} |
|
// create default prng context |
|
var _ctx = spawnPrng(); |
|
// add other sources of entropy only if window.crypto.getRandomValues is not |
|
// available -- otherwise this source will be automatically used by the prng |
|
var getRandomValues = null; |
|
var globalScope = $iGlOy.util.globalScope; |
|
var _crypto = globalScope.crypto || globalScope.msCrypto; |
|
if (_crypto && _crypto.getRandomValues) getRandomValues = function(arr) { |
|
return _crypto.getRandomValues(arr); |
|
}; |
|
if ($iGlOy.options.usePureJavaScript || !$iGlOy.util.isNodejs && !getRandomValues) { |
|
typeof window === 'undefined' || window.document; |
|
// get load time entropy |
|
_ctx.collectInt(+new Date(), 32); |
|
// add some entropy from navigator object |
|
if (typeof navigator !== 'undefined') { |
|
var _navBytes = ''; |
|
for(var key1 in navigator)try { |
|
if (typeof navigator[key1] == 'string') _navBytes += navigator[key1]; |
|
} catch (e) { |
|
/* Some navigator keys might not be accessible, e.g. the geolocation |
|
attribute throws an exception if touched in Mozilla chrome:// |
|
context. |
|
|
|
Silently ignore this and just don't use this as a source of |
|
entropy. */ } |
|
_ctx.collect(_navBytes); |
|
_navBytes = null; |
|
} |
|
// add mouse and keyboard collectors if jquery is available |
|
if (jQuery) { |
|
// set up mouse entropy capture |
|
jQuery().mousemove(function(e) { |
|
// add mouse coords |
|
_ctx.collectInt(e.clientX, 16); |
|
_ctx.collectInt(e.clientY, 16); |
|
}); |
|
// set up keyboard entropy capture |
|
jQuery().keypress(function(e) { |
|
_ctx.collectInt(e.charCode, 8); |
|
}); |
|
} |
|
} |
|
/* Random API */ if (!$iGlOy.random) $iGlOy.random = _ctx; |
|
else // extend forge.random with _ctx |
|
for(var key1 in _ctx)$iGlOy.random[key1] = _ctx[key1]; |
|
// expose spawn PRNG |
|
$iGlOy.random.createInstance = spawnPrng; |
|
$b9b57fce3e6d85ef$exports = $iGlOy.random; |
|
})(typeof jQuery !== 'undefined' ? jQuery : null); |
|
})(); |
|
|
|
|
|
var $e745366ef6f504e1$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
var $e745366ef6f504e1$var$piTable = [ |
|
217, |
|
120, |
|
249, |
|
196, |
|
25, |
|
221, |
|
181, |
|
237, |
|
40, |
|
233, |
|
253, |
|
121, |
|
74, |
|
160, |
|
216, |
|
157, |
|
198, |
|
126, |
|
55, |
|
131, |
|
43, |
|
118, |
|
83, |
|
142, |
|
98, |
|
76, |
|
100, |
|
136, |
|
68, |
|
139, |
|
251, |
|
162, |
|
23, |
|
154, |
|
89, |
|
245, |
|
135, |
|
179, |
|
79, |
|
19, |
|
97, |
|
69, |
|
109, |
|
141, |
|
9, |
|
129, |
|
125, |
|
50, |
|
189, |
|
143, |
|
64, |
|
235, |
|
134, |
|
183, |
|
123, |
|
11, |
|
240, |
|
149, |
|
33, |
|
34, |
|
92, |
|
107, |
|
78, |
|
130, |
|
84, |
|
214, |
|
101, |
|
147, |
|
206, |
|
96, |
|
178, |
|
28, |
|
115, |
|
86, |
|
192, |
|
20, |
|
167, |
|
140, |
|
241, |
|
220, |
|
18, |
|
117, |
|
202, |
|
31, |
|
59, |
|
190, |
|
228, |
|
209, |
|
66, |
|
61, |
|
212, |
|
48, |
|
163, |
|
60, |
|
182, |
|
38, |
|
111, |
|
191, |
|
14, |
|
218, |
|
70, |
|
105, |
|
7, |
|
87, |
|
39, |
|
242, |
|
29, |
|
155, |
|
188, |
|
148, |
|
67, |
|
3, |
|
248, |
|
17, |
|
199, |
|
246, |
|
144, |
|
239, |
|
62, |
|
231, |
|
6, |
|
195, |
|
213, |
|
47, |
|
200, |
|
102, |
|
30, |
|
215, |
|
8, |
|
232, |
|
234, |
|
222, |
|
128, |
|
82, |
|
238, |
|
247, |
|
132, |
|
170, |
|
114, |
|
172, |
|
53, |
|
77, |
|
106, |
|
42, |
|
150, |
|
26, |
|
210, |
|
113, |
|
90, |
|
21, |
|
73, |
|
116, |
|
75, |
|
159, |
|
208, |
|
94, |
|
4, |
|
24, |
|
164, |
|
236, |
|
194, |
|
224, |
|
65, |
|
110, |
|
15, |
|
81, |
|
203, |
|
204, |
|
36, |
|
145, |
|
175, |
|
80, |
|
161, |
|
244, |
|
112, |
|
57, |
|
153, |
|
124, |
|
58, |
|
133, |
|
35, |
|
184, |
|
180, |
|
122, |
|
252, |
|
2, |
|
54, |
|
91, |
|
37, |
|
85, |
|
151, |
|
49, |
|
45, |
|
93, |
|
250, |
|
152, |
|
227, |
|
138, |
|
146, |
|
174, |
|
5, |
|
223, |
|
41, |
|
16, |
|
103, |
|
108, |
|
186, |
|
201, |
|
211, |
|
0, |
|
230, |
|
207, |
|
225, |
|
158, |
|
168, |
|
44, |
|
99, |
|
22, |
|
1, |
|
63, |
|
88, |
|
226, |
|
137, |
|
169, |
|
13, |
|
56, |
|
52, |
|
27, |
|
171, |
|
51, |
|
255, |
|
176, |
|
187, |
|
72, |
|
12, |
|
95, |
|
185, |
|
177, |
|
205, |
|
46, |
|
197, |
|
243, |
|
219, |
|
71, |
|
229, |
|
165, |
|
156, |
|
119, |
|
10, |
|
166, |
|
32, |
|
104, |
|
254, |
|
127, |
|
193, |
|
173 |
|
]; |
|
var $e745366ef6f504e1$var$s = [ |
|
1, |
|
2, |
|
3, |
|
5 |
|
]; |
|
/** |
|
* Rotate a word left by given number of bits. |
|
* |
|
* Bits that are shifted out on the left are put back in on the right |
|
* hand side. |
|
* |
|
* @param word The word to shift left. |
|
* @param bits The number of bits to shift by. |
|
* @return The rotated word. |
|
*/ var $e745366ef6f504e1$var$rol = function(word, bits) { |
|
return word << bits & 65535 | (word & 65535) >> 16 - bits; |
|
}; |
|
/** |
|
* Rotate a word right by given number of bits. |
|
* |
|
* Bits that are shifted out on the right are put back in on the left |
|
* hand side. |
|
* |
|
* @param word The word to shift right. |
|
* @param bits The number of bits to shift by. |
|
* @return The rotated word. |
|
*/ var $e745366ef6f504e1$var$ror = function(word, bits) { |
|
return (word & 65535) >> bits | word << 16 - bits & 65535; |
|
}; |
|
/* RC2 API */ $e745366ef6f504e1$exports = $iGlOy.rc2 = $iGlOy.rc2 || { |
|
}; |
|
/** |
|
* Perform RC2 key expansion as per RFC #2268, section 2. |
|
* |
|
* @param key variable-length user key (between 1 and 128 bytes) |
|
* @param effKeyBits number of effective key bits (default: 128) |
|
* @return the expanded RC2 key (ByteBuffer of 128 bytes) |
|
*/ $iGlOy.rc2.expandKey = function(key, effKeyBits) { |
|
if (typeof key === 'string') key = $iGlOy.util.createBuffer(key); |
|
effKeyBits = effKeyBits || 128; |
|
/* introduce variables that match the names used in RFC #2268 */ var L = key; |
|
var T = key.length(); |
|
var T1 = effKeyBits; |
|
var T8 = Math.ceil(T1 / 8); |
|
var TM = 255 >> (T1 & 7); |
|
var i; |
|
for(i = T; i < 128; i++)L.putByte($e745366ef6f504e1$var$piTable[L.at(i - 1) + L.at(i - T) & 255]); |
|
L.setAt(128 - T8, $e745366ef6f504e1$var$piTable[L.at(128 - T8) & TM]); |
|
for(i = 127 - T8; i >= 0; i--)L.setAt(i, $e745366ef6f504e1$var$piTable[L.at(i + 1) ^ L.at(i + T8)]); |
|
return L; |
|
}; |
|
/** |
|
* Creates a RC2 cipher object. |
|
* |
|
* @param key the symmetric key to use (as base for key generation). |
|
* @param bits the number of effective key bits. |
|
* @param encrypt false for decryption, true for encryption. |
|
* |
|
* @return the cipher. |
|
*/ var $e745366ef6f504e1$var$createCipher = function(key, bits, encrypt) { |
|
var _finish = false, _input = null, _output = null, _iv = null; |
|
var mixRound, mashRound; |
|
var i, j, K = []; |
|
/* Expand key and fill into K[] Array */ key = $iGlOy.rc2.expandKey(key, bits); |
|
for(i = 0; i < 64; i++)K.push(key.getInt16Le()); |
|
if (encrypt) { |
|
/** |
|
* Perform one mixing round "in place". |
|
* |
|
* @param R Array of four words to perform mixing on. |
|
*/ mixRound = function(R) { |
|
for(i = 0; i < 4; i++){ |
|
R[i] += K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) + (~R[(i + 3) % 4] & R[(i + 1) % 4]); |
|
R[i] = $e745366ef6f504e1$var$rol(R[i], $e745366ef6f504e1$var$s[i]); |
|
j++; |
|
} |
|
}; |
|
/** |
|
* Perform one mashing round "in place". |
|
* |
|
* @param R Array of four words to perform mashing on. |
|
*/ mashRound = function(R) { |
|
for(i = 0; i < 4; i++)R[i] += K[R[(i + 3) % 4] & 63]; |
|
}; |
|
} else { |
|
/** |
|
* Perform one r-mixing round "in place". |
|
* |
|
* @param R Array of four words to perform mixing on. |
|
*/ mixRound = function(R) { |
|
for(i = 3; i >= 0; i--){ |
|
R[i] = $e745366ef6f504e1$var$ror(R[i], $e745366ef6f504e1$var$s[i]); |
|
R[i] -= K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) + (~R[(i + 3) % 4] & R[(i + 1) % 4]); |
|
j--; |
|
} |
|
}; |
|
/** |
|
* Perform one r-mashing round "in place". |
|
* |
|
* @param R Array of four words to perform mashing on. |
|
*/ mashRound = function(R) { |
|
for(i = 3; i >= 0; i--)R[i] -= K[R[(i + 3) % 4] & 63]; |
|
}; |
|
} |
|
/** |
|
* Run the specified cipher execution plan. |
|
* |
|
* This function takes four words from the input buffer, applies the IV on |
|
* it (if requested) and runs the provided execution plan. |
|
* |
|
* The plan must be put together in form of a array of arrays. Where the |
|
* outer one is simply a list of steps to perform and the inner one needs |
|
* to have two elements: the first one telling how many rounds to perform, |
|
* the second one telling what to do (i.e. the function to call). |
|
* |
|
* @param {Array} plan The plan to execute. |
|
*/ var runPlan = function(plan) { |
|
var R = []; |
|
/* Get data from input buffer and fill the four words into R */ for(i = 0; i < 4; i++){ |
|
var val = _input.getInt16Le(); |
|
if (_iv !== null) { |
|
if (encrypt) /* We're encrypting, apply the IV first. */ val ^= _iv.getInt16Le(); |
|
else /* We're decryption, keep cipher text for next block. */ _iv.putInt16Le(val); |
|
} |
|
R.push(val & 65535); |
|
} |
|
/* Reset global "j" variable as per spec. */ j = encrypt ? 0 : 63; |
|
/* Run execution plan. */ for(var ptr = 0; ptr < plan.length; ptr++)for(var ctr = 0; ctr < plan[ptr][0]; ctr++)plan[ptr][1](R); |
|
/* Write back result to output buffer. */ for(i = 0; i < 4; i++){ |
|
if (_iv !== null) { |
|
if (encrypt) /* We're encrypting in CBC-mode, feed back encrypted bytes into |
|
IV buffer to carry it forward to next block. */ _iv.putInt16Le(R[i]); |
|
else R[i] ^= _iv.getInt16Le(); |
|
} |
|
_output.putInt16Le(R[i]); |
|
} |
|
}; |
|
/* Create cipher object */ var cipher = null; |
|
cipher = { |
|
/** |
|
* Starts or restarts the encryption or decryption process, whichever |
|
* was previously configured. |
|
* |
|
* To use the cipher in CBC mode, iv may be given either as a string |
|
* of bytes, or as a byte buffer. For ECB mode, give null as iv. |
|
* |
|
* @param iv the initialization vector to use, null for ECB mode. |
|
* @param output the output the buffer to write to, null to create one. |
|
*/ start: function(iv, output) { |
|
if (iv) /* CBC mode */ { |
|
if (typeof iv === 'string') iv = $iGlOy.util.createBuffer(iv); |
|
} |
|
_finish = false; |
|
_input = $iGlOy.util.createBuffer(); |
|
_output = output || new $iGlOy.util.createBuffer(); |
|
_iv = iv; |
|
cipher.output = _output; |
|
}, |
|
/** |
|
* Updates the next block. |
|
* |
|
* @param input the buffer to read from. |
|
*/ update: function(input) { |
|
if (!_finish) // not finishing, so fill the input buffer with more input |
|
_input.putBuffer(input); |
|
while(_input.length() >= 8)runPlan([ |
|
[ |
|
5, |
|
mixRound |
|
], |
|
[ |
|
1, |
|
mashRound |
|
], |
|
[ |
|
6, |
|
mixRound |
|
], |
|
[ |
|
1, |
|
mashRound |
|
], |
|
[ |
|
5, |
|
mixRound |
|
] |
|
]); |
|
}, |
|
/** |
|
* Finishes encrypting or decrypting. |
|
* |
|
* @param pad a padding function to use, null for PKCS#7 padding, |
|
* signature(blockSize, buffer, decrypt). |
|
* |
|
* @return true if successful, false on error. |
|
*/ finish: function(pad) { |
|
var rval = true; |
|
if (encrypt) { |
|
if (pad) rval = pad(8, _input, !encrypt); |
|
else { |
|
// add PKCS#7 padding to block (each pad byte is the |
|
// value of the number of pad bytes) |
|
var padding = _input.length() === 8 ? 8 : 8 - _input.length(); |
|
_input.fillWithByte(padding, padding); |
|
} |
|
} |
|
if (rval) { |
|
// do final update |
|
_finish = true; |
|
cipher.update(); |
|
} |
|
if (!encrypt) { |
|
// check for error: input data not a multiple of block size |
|
rval = _input.length() === 0; |
|
if (rval) { |
|
if (pad) rval = pad(8, _output, !encrypt); |
|
else { |
|
// ensure padding byte count is valid |
|
var len = _output.length(); |
|
var count = _output.at(len - 1); |
|
if (count > len) rval = false; |
|
else // trim off padding bytes |
|
_output.truncate(count); |
|
} |
|
} |
|
} |
|
return rval; |
|
} |
|
}; |
|
return cipher; |
|
}; |
|
/** |
|
* Creates an RC2 cipher object to encrypt data in ECB or CBC mode using the |
|
* given symmetric key. The output will be stored in the 'output' member |
|
* of the returned cipher. |
|
* |
|
* The key and iv may be given as a string of bytes or a byte buffer. |
|
* The cipher is initialized to use 128 effective key bits. |
|
* |
|
* @param key the symmetric key to use. |
|
* @param iv the initialization vector to use. |
|
* @param output the buffer to write to, null to create one. |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.rc2.startEncrypting = function(key, iv, output) { |
|
var cipher = $iGlOy.rc2.createEncryptionCipher(key, 128); |
|
cipher.start(iv, output); |
|
return cipher; |
|
}; |
|
/** |
|
* Creates an RC2 cipher object to encrypt data in ECB or CBC mode using the |
|
* given symmetric key. |
|
* |
|
* The key may be given as a string of bytes or a byte buffer. |
|
* |
|
* To start encrypting call start() on the cipher with an iv and optional |
|
* output buffer. |
|
* |
|
* @param key the symmetric key to use. |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.rc2.createEncryptionCipher = function(key, bits) { |
|
return $e745366ef6f504e1$var$createCipher(key, bits, true); |
|
}; |
|
/** |
|
* Creates an RC2 cipher object to decrypt data in ECB or CBC mode using the |
|
* given symmetric key. The output will be stored in the 'output' member |
|
* of the returned cipher. |
|
* |
|
* The key and iv may be given as a string of bytes or a byte buffer. |
|
* The cipher is initialized to use 128 effective key bits. |
|
* |
|
* @param key the symmetric key to use. |
|
* @param iv the initialization vector to use. |
|
* @param output the buffer to write to, null to create one. |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.rc2.startDecrypting = function(key, iv, output) { |
|
var cipher = $iGlOy.rc2.createDecryptionCipher(key, 128); |
|
cipher.start(iv, output); |
|
return cipher; |
|
}; |
|
/** |
|
* Creates an RC2 cipher object to decrypt data in ECB or CBC mode using the |
|
* given symmetric key. |
|
* |
|
* The key may be given as a string of bytes or a byte buffer. |
|
* |
|
* To start decrypting call start() on the cipher with an iv and optional |
|
* output buffer. |
|
* |
|
* @param key the symmetric key to use. |
|
* |
|
* @return the cipher. |
|
*/ $iGlOy.rc2.createDecryptionCipher = function(key, bits) { |
|
return $e745366ef6f504e1$var$createCipher(key, bits, false); |
|
}; |
|
|
|
|
|
var $8ab3548bea1beb81$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
var $1831e702d86f54be$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
$1831e702d86f54be$exports = $iGlOy.jsbn = $iGlOy.jsbn || { |
|
}; |
|
// Bits per digit |
|
var $1831e702d86f54be$var$dbits; |
|
// JavaScript engine analysis |
|
var $1831e702d86f54be$var$canary = 244837814094590; |
|
var $1831e702d86f54be$var$j_lm = ($1831e702d86f54be$var$canary & 16777215) == 15715070; |
|
// (public) Constructor |
|
function $1831e702d86f54be$var$BigInteger(a, b, c) { |
|
this.data = []; |
|
if (a != null) { |
|
if ("number" == typeof a) this.fromNumber(a, b, c); |
|
else if (b == null && "string" != typeof a) this.fromString(a, 256); |
|
else this.fromString(a, b); |
|
} |
|
} |
|
$iGlOy.jsbn.BigInteger = $1831e702d86f54be$var$BigInteger; |
|
// return new, unset BigInteger |
|
function $1831e702d86f54be$var$nbi() { |
|
return new $1831e702d86f54be$var$BigInteger(null); |
|
} |
|
// am: Compute w_j += (x*this_i), propagate carries, |
|
// c is initial carry, returns final carry. |
|
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue |
|
// We need to select the fastest one that works in this environment. |
|
// am1: use a single mult and divide to get the high bits, |
|
// max digit bits should be 26 because |
|
// max internal value = 2*dvalue^2-2*dvalue (< 2^53) |
|
function $1831e702d86f54be$var$am1(i, x, w, j, c, n) { |
|
while(--n >= 0){ |
|
var v = x * this.data[i++] + w.data[j] + c; |
|
c = Math.floor(v / 67108864); |
|
w.data[j++] = v & 67108863; |
|
} |
|
return c; |
|
} |
|
// am2 avoids a big mult-and-extract completely. |
|
// Max digit bits should be <= 30 because we do bitwise ops |
|
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) |
|
function $1831e702d86f54be$var$am2(i, x, w, j, c, n) { |
|
var xl = x & 32767, xh = x >> 15; |
|
while(--n >= 0){ |
|
var l = this.data[i] & 32767; |
|
var h = this.data[i++] >> 15; |
|
var m = xh * l + h * xl; |
|
l = xl * l + ((m & 32767) << 15) + w.data[j] + (c & 1073741823); |
|
c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30); |
|
w.data[j++] = l & 1073741823; |
|
} |
|
return c; |
|
} |
|
// Alternately, set max digit bits to 28 since some |
|
// browsers slow down when dealing with 32-bit numbers. |
|
function $1831e702d86f54be$var$am3(i, x, w, j, c, n) { |
|
var xl = x & 16383, xh = x >> 14; |
|
while(--n >= 0){ |
|
var l = this.data[i] & 16383; |
|
var h = this.data[i++] >> 14; |
|
var m = xh * l + h * xl; |
|
l = xl * l + ((m & 16383) << 14) + w.data[j] + c; |
|
c = (l >> 28) + (m >> 14) + xh * h; |
|
w.data[j++] = l & 268435455; |
|
} |
|
return c; |
|
} |
|
// node.js (no browser) |
|
if (typeof navigator === 'undefined') { |
|
$1831e702d86f54be$var$BigInteger.prototype.am = $1831e702d86f54be$var$am3; |
|
$1831e702d86f54be$var$dbits = 28; |
|
} else if ($1831e702d86f54be$var$j_lm && navigator.appName == "Microsoft Internet Explorer") { |
|
$1831e702d86f54be$var$BigInteger.prototype.am = $1831e702d86f54be$var$am2; |
|
$1831e702d86f54be$var$dbits = 30; |
|
} else if ($1831e702d86f54be$var$j_lm && navigator.appName != "Netscape") { |
|
$1831e702d86f54be$var$BigInteger.prototype.am = $1831e702d86f54be$var$am1; |
|
$1831e702d86f54be$var$dbits = 26; |
|
} else { |
|
$1831e702d86f54be$var$BigInteger.prototype.am = $1831e702d86f54be$var$am3; |
|
$1831e702d86f54be$var$dbits = 28; |
|
} |
|
$1831e702d86f54be$var$BigInteger.prototype.DB = $1831e702d86f54be$var$dbits; |
|
$1831e702d86f54be$var$BigInteger.prototype.DM = (1 << $1831e702d86f54be$var$dbits) - 1; |
|
$1831e702d86f54be$var$BigInteger.prototype.DV = 1 << $1831e702d86f54be$var$dbits; |
|
var $1831e702d86f54be$var$BI_FP = 52; |
|
$1831e702d86f54be$var$BigInteger.prototype.FV = Math.pow(2, $1831e702d86f54be$var$BI_FP); |
|
$1831e702d86f54be$var$BigInteger.prototype.F1 = $1831e702d86f54be$var$BI_FP - $1831e702d86f54be$var$dbits; |
|
$1831e702d86f54be$var$BigInteger.prototype.F2 = 2 * $1831e702d86f54be$var$dbits - $1831e702d86f54be$var$BI_FP; |
|
// Digit conversions |
|
var $1831e702d86f54be$var$BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; |
|
var $1831e702d86f54be$var$BI_RC = new Array(); |
|
var $1831e702d86f54be$var$rr, $1831e702d86f54be$var$vv; |
|
$1831e702d86f54be$var$rr = "0".charCodeAt(0); |
|
for($1831e702d86f54be$var$vv = 0; $1831e702d86f54be$var$vv <= 9; ++$1831e702d86f54be$var$vv)$1831e702d86f54be$var$BI_RC[$1831e702d86f54be$var$rr++] = $1831e702d86f54be$var$vv; |
|
$1831e702d86f54be$var$rr = "a".charCodeAt(0); |
|
for($1831e702d86f54be$var$vv = 10; $1831e702d86f54be$var$vv < 36; ++$1831e702d86f54be$var$vv)$1831e702d86f54be$var$BI_RC[$1831e702d86f54be$var$rr++] = $1831e702d86f54be$var$vv; |
|
$1831e702d86f54be$var$rr = "A".charCodeAt(0); |
|
for($1831e702d86f54be$var$vv = 10; $1831e702d86f54be$var$vv < 36; ++$1831e702d86f54be$var$vv)$1831e702d86f54be$var$BI_RC[$1831e702d86f54be$var$rr++] = $1831e702d86f54be$var$vv; |
|
function $1831e702d86f54be$var$int2char(n) { |
|
return $1831e702d86f54be$var$BI_RM.charAt(n); |
|
} |
|
function $1831e702d86f54be$var$intAt(s, i) { |
|
var c = $1831e702d86f54be$var$BI_RC[s.charCodeAt(i)]; |
|
return c == null ? -1 : c; |
|
} |
|
// (protected) copy this to r |
|
function $1831e702d86f54be$var$bnpCopyTo(r) { |
|
for(var i = this.t - 1; i >= 0; --i)r.data[i] = this.data[i]; |
|
r.t = this.t; |
|
r.s = this.s; |
|
} |
|
// (protected) set from integer value x, -DV <= x < DV |
|
function $1831e702d86f54be$var$bnpFromInt(x) { |
|
this.t = 1; |
|
this.s = x < 0 ? -1 : 0; |
|
if (x > 0) this.data[0] = x; |
|
else if (x < -1) this.data[0] = x + this.DV; |
|
else this.t = 0; |
|
} |
|
// return bigint initialized to value |
|
function $1831e702d86f54be$var$nbv(i) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
r.fromInt(i); |
|
return r; |
|
} |
|
// (protected) set from string and radix |
|
function $1831e702d86f54be$var$bnpFromString(s, b) { |
|
var k; |
|
if (b == 16) k = 4; |
|
else if (b == 8) k = 3; |
|
else if (b == 256) k = 8; // byte array |
|
else if (b == 2) k = 1; |
|
else if (b == 32) k = 5; |
|
else if (b == 4) k = 2; |
|
else { |
|
this.fromRadix(s, b); |
|
return; |
|
} |
|
this.t = 0; |
|
this.s = 0; |
|
var i = s.length, mi = false, sh = 0; |
|
while(--i >= 0){ |
|
var x = k == 8 ? s[i] & 255 : $1831e702d86f54be$var$intAt(s, i); |
|
if (x < 0) { |
|
if (s.charAt(i) == "-") mi = true; |
|
continue; |
|
} |
|
mi = false; |
|
if (sh == 0) this.data[this.t++] = x; |
|
else if (sh + k > this.DB) { |
|
this.data[this.t - 1] |= (x & (1 << this.DB - sh) - 1) << sh; |
|
this.data[this.t++] = x >> this.DB - sh; |
|
} else this.data[this.t - 1] |= x << sh; |
|
sh += k; |
|
if (sh >= this.DB) sh -= this.DB; |
|
} |
|
if (k == 8 && (s[0] & 128) != 0) { |
|
this.s = -1; |
|
if (sh > 0) this.data[this.t - 1] |= (1 << this.DB - sh) - 1 << sh; |
|
} |
|
this.clamp(); |
|
if (mi) $1831e702d86f54be$var$BigInteger.ZERO.subTo(this, this); |
|
} |
|
// (protected) clamp off excess high words |
|
function $1831e702d86f54be$var$bnpClamp() { |
|
var c = this.s & this.DM; |
|
while(this.t > 0 && this.data[this.t - 1] == c)--this.t; |
|
} |
|
// (public) return string representation in given radix |
|
function $1831e702d86f54be$var$bnToString(b) { |
|
if (this.s < 0) return "-" + this.negate().toString(b); |
|
var k; |
|
if (b == 16) k = 4; |
|
else if (b == 8) k = 3; |
|
else if (b == 2) k = 1; |
|
else if (b == 32) k = 5; |
|
else if (b == 4) k = 2; |
|
else return this.toRadix(b); |
|
var km = (1 << k) - 1, d, m = false, r = "", i = this.t; |
|
var p = this.DB - i * this.DB % k; |
|
if (i-- > 0) { |
|
if (p < this.DB && (d = this.data[i] >> p) > 0) { |
|
m = true; |
|
r = $1831e702d86f54be$var$int2char(d); |
|
} |
|
while(i >= 0){ |
|
if (p < k) { |
|
d = (this.data[i] & (1 << p) - 1) << k - p; |
|
d |= this.data[--i] >> (p += this.DB - k); |
|
} else { |
|
d = this.data[i] >> (p -= k) & km; |
|
if (p <= 0) { |
|
p += this.DB; |
|
--i; |
|
} |
|
} |
|
if (d > 0) m = true; |
|
if (m) r += $1831e702d86f54be$var$int2char(d); |
|
} |
|
} |
|
return m ? r : "0"; |
|
} |
|
// (public) -this |
|
function $1831e702d86f54be$var$bnNegate() { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
$1831e702d86f54be$var$BigInteger.ZERO.subTo(this, r); |
|
return r; |
|
} |
|
// (public) |this| |
|
function $1831e702d86f54be$var$bnAbs() { |
|
return this.s < 0 ? this.negate() : this; |
|
} |
|
// (public) return + if this > a, - if this < a, 0 if equal |
|
function $1831e702d86f54be$var$bnCompareTo(a) { |
|
var r = this.s - a.s; |
|
if (r != 0) return r; |
|
var i = this.t; |
|
r = i - a.t; |
|
if (r != 0) return this.s < 0 ? -r : r; |
|
while(--i >= 0)if ((r = this.data[i] - a.data[i]) != 0) return r; |
|
return 0; |
|
} |
|
// returns bit length of the integer x |
|
function $1831e702d86f54be$var$nbits(x) { |
|
var r = 1, t; |
|
if ((t = x >>> 16) != 0) { |
|
x = t; |
|
r += 16; |
|
} |
|
if ((t = x >> 8) != 0) { |
|
x = t; |
|
r += 8; |
|
} |
|
if ((t = x >> 4) != 0) { |
|
x = t; |
|
r += 4; |
|
} |
|
if ((t = x >> 2) != 0) { |
|
x = t; |
|
r += 2; |
|
} |
|
if ((t = x >> 1) != 0) { |
|
x = t; |
|
r += 1; |
|
} |
|
return r; |
|
} |
|
// (public) return the number of bits in "this" |
|
function $1831e702d86f54be$var$bnBitLength() { |
|
if (this.t <= 0) return 0; |
|
return this.DB * (this.t - 1) + $1831e702d86f54be$var$nbits(this.data[this.t - 1] ^ this.s & this.DM); |
|
} |
|
// (protected) r = this << n*DB |
|
function $1831e702d86f54be$var$bnpDLShiftTo(n, r) { |
|
var i; |
|
for(i = this.t - 1; i >= 0; --i)r.data[i + n] = this.data[i]; |
|
for(i = n - 1; i >= 0; --i)r.data[i] = 0; |
|
r.t = this.t + n; |
|
r.s = this.s; |
|
} |
|
// (protected) r = this >> n*DB |
|
function $1831e702d86f54be$var$bnpDRShiftTo(n, r) { |
|
for(var i = n; i < this.t; ++i)r.data[i - n] = this.data[i]; |
|
r.t = Math.max(this.t - n, 0); |
|
r.s = this.s; |
|
} |
|
// (protected) r = this << n |
|
function $1831e702d86f54be$var$bnpLShiftTo(n, r) { |
|
var bs = n % this.DB; |
|
var cbs = this.DB - bs; |
|
var bm = (1 << cbs) - 1; |
|
var ds = Math.floor(n / this.DB), c = this.s << bs & this.DM, i; |
|
for(i = this.t - 1; i >= 0; --i){ |
|
r.data[i + ds + 1] = this.data[i] >> cbs | c; |
|
c = (this.data[i] & bm) << bs; |
|
} |
|
for(i = ds - 1; i >= 0; --i)r.data[i] = 0; |
|
r.data[ds] = c; |
|
r.t = this.t + ds + 1; |
|
r.s = this.s; |
|
r.clamp(); |
|
} |
|
// (protected) r = this >> n |
|
function $1831e702d86f54be$var$bnpRShiftTo(n, r) { |
|
r.s = this.s; |
|
var ds = Math.floor(n / this.DB); |
|
if (ds >= this.t) { |
|
r.t = 0; |
|
return; |
|
} |
|
var bs = n % this.DB; |
|
var cbs = this.DB - bs; |
|
var bm = (1 << bs) - 1; |
|
r.data[0] = this.data[ds] >> bs; |
|
for(var i = ds + 1; i < this.t; ++i){ |
|
r.data[i - ds - 1] |= (this.data[i] & bm) << cbs; |
|
r.data[i - ds] = this.data[i] >> bs; |
|
} |
|
if (bs > 0) r.data[this.t - ds - 1] |= (this.s & bm) << cbs; |
|
r.t = this.t - ds; |
|
r.clamp(); |
|
} |
|
// (protected) r = this - a |
|
function $1831e702d86f54be$var$bnpSubTo(a, r) { |
|
var i = 0, c = 0, m = Math.min(a.t, this.t); |
|
while(i < m){ |
|
c += this.data[i] - a.data[i]; |
|
r.data[i++] = c & this.DM; |
|
c >>= this.DB; |
|
} |
|
if (a.t < this.t) { |
|
c -= a.s; |
|
while(i < this.t){ |
|
c += this.data[i]; |
|
r.data[i++] = c & this.DM; |
|
c >>= this.DB; |
|
} |
|
c += this.s; |
|
} else { |
|
c += this.s; |
|
while(i < a.t){ |
|
c -= a.data[i]; |
|
r.data[i++] = c & this.DM; |
|
c >>= this.DB; |
|
} |
|
c -= a.s; |
|
} |
|
r.s = c < 0 ? -1 : 0; |
|
if (c < -1) r.data[i++] = this.DV + c; |
|
else if (c > 0) r.data[i++] = c; |
|
r.t = i; |
|
r.clamp(); |
|
} |
|
// (protected) r = this * a, r != this,a (HAC 14.12) |
|
// "this" should be the larger one if appropriate. |
|
function $1831e702d86f54be$var$bnpMultiplyTo(a, r) { |
|
var x = this.abs(), y = a.abs(); |
|
var i = x.t; |
|
r.t = i + y.t; |
|
while(--i >= 0)r.data[i] = 0; |
|
for(i = 0; i < y.t; ++i)r.data[i + x.t] = x.am(0, y.data[i], r, i, 0, x.t); |
|
r.s = 0; |
|
r.clamp(); |
|
if (this.s != a.s) $1831e702d86f54be$var$BigInteger.ZERO.subTo(r, r); |
|
} |
|
// (protected) r = this^2, r != this (HAC 14.16) |
|
function $1831e702d86f54be$var$bnpSquareTo(r) { |
|
var x = this.abs(); |
|
var i = r.t = 2 * x.t; |
|
while(--i >= 0)r.data[i] = 0; |
|
for(i = 0; i < x.t - 1; ++i){ |
|
var c = x.am(i, x.data[i], r, 2 * i, 0, 1); |
|
if ((r.data[i + x.t] += x.am(i + 1, 2 * x.data[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) { |
|
r.data[i + x.t] -= x.DV; |
|
r.data[i + x.t + 1] = 1; |
|
} |
|
} |
|
if (r.t > 0) r.data[r.t - 1] += x.am(i, x.data[i], r, 2 * i, 0, 1); |
|
r.s = 0; |
|
r.clamp(); |
|
} |
|
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) |
|
// r != q, this != m. q or r may be null. |
|
function $1831e702d86f54be$var$bnpDivRemTo(m, q, r) { |
|
var pm = m.abs(); |
|
if (pm.t <= 0) return; |
|
var pt = this.abs(); |
|
if (pt.t < pm.t) { |
|
if (q != null) q.fromInt(0); |
|
if (r != null) this.copyTo(r); |
|
return; |
|
} |
|
if (r == null) r = $1831e702d86f54be$var$nbi(); |
|
var y = $1831e702d86f54be$var$nbi(), ts = this.s, ms = m.s; |
|
var nsh = this.DB - $1831e702d86f54be$var$nbits(pm.data[pm.t - 1]); // normalize modulus |
|
if (nsh > 0) { |
|
pm.lShiftTo(nsh, y); |
|
pt.lShiftTo(nsh, r); |
|
} else { |
|
pm.copyTo(y); |
|
pt.copyTo(r); |
|
} |
|
var ys = y.t; |
|
var y0 = y.data[ys - 1]; |
|
if (y0 == 0) return; |
|
var yt = y0 * (1 << this.F1) + (ys > 1 ? y.data[ys - 2] >> this.F2 : 0); |
|
var d1 = this.FV / yt, d2 = (1 << this.F1) / yt, e = 1 << this.F2; |
|
var i = r.t, j = i - ys, t = q == null ? $1831e702d86f54be$var$nbi() : q; |
|
y.dlShiftTo(j, t); |
|
if (r.compareTo(t) >= 0) { |
|
r.data[r.t++] = 1; |
|
r.subTo(t, r); |
|
} |
|
$1831e702d86f54be$var$BigInteger.ONE.dlShiftTo(ys, t); |
|
t.subTo(y, y); // "negative" y so we can replace sub with am later |
|
while(y.t < ys)y.data[y.t++] = 0; |
|
while(--j >= 0){ |
|
// Estimate quotient digit |
|
var qd = r.data[--i] == y0 ? this.DM : Math.floor(r.data[i] * d1 + (r.data[i - 1] + e) * d2); |
|
if ((r.data[i] += y.am(0, qd, r, j, 0, ys)) < qd) { |
|
y.dlShiftTo(j, t); |
|
r.subTo(t, r); |
|
while(r.data[i] < --qd)r.subTo(t, r); |
|
} |
|
} |
|
if (q != null) { |
|
r.drShiftTo(ys, q); |
|
if (ts != ms) $1831e702d86f54be$var$BigInteger.ZERO.subTo(q, q); |
|
} |
|
r.t = ys; |
|
r.clamp(); |
|
if (nsh > 0) r.rShiftTo(nsh, r); // Denormalize remainder |
|
if (ts < 0) $1831e702d86f54be$var$BigInteger.ZERO.subTo(r, r); |
|
} |
|
// (public) this mod a |
|
function $1831e702d86f54be$var$bnMod(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.abs().divRemTo(a, null, r); |
|
if (this.s < 0 && r.compareTo($1831e702d86f54be$var$BigInteger.ZERO) > 0) a.subTo(r, r); |
|
return r; |
|
} |
|
// Modular reduction using "classic" algorithm |
|
function $1831e702d86f54be$var$Classic(m) { |
|
this.m = m; |
|
} |
|
function $1831e702d86f54be$var$cConvert(x) { |
|
if (x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); |
|
else return x; |
|
} |
|
function $1831e702d86f54be$var$cRevert(x) { |
|
return x; |
|
} |
|
function $1831e702d86f54be$var$cReduce(x) { |
|
x.divRemTo(this.m, null, x); |
|
} |
|
function $1831e702d86f54be$var$cMulTo(x, y, r) { |
|
x.multiplyTo(y, r); |
|
this.reduce(r); |
|
} |
|
function $1831e702d86f54be$var$cSqrTo(x, r) { |
|
x.squareTo(r); |
|
this.reduce(r); |
|
} |
|
$1831e702d86f54be$var$Classic.prototype.convert = $1831e702d86f54be$var$cConvert; |
|
$1831e702d86f54be$var$Classic.prototype.revert = $1831e702d86f54be$var$cRevert; |
|
$1831e702d86f54be$var$Classic.prototype.reduce = $1831e702d86f54be$var$cReduce; |
|
$1831e702d86f54be$var$Classic.prototype.mulTo = $1831e702d86f54be$var$cMulTo; |
|
$1831e702d86f54be$var$Classic.prototype.sqrTo = $1831e702d86f54be$var$cSqrTo; |
|
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction |
|
// justification: |
|
// xy == 1 (mod m) |
|
// xy = 1+km |
|
// xy(2-xy) = (1+km)(1-km) |
|
// x[y(2-xy)] = 1-k^2m^2 |
|
// x[y(2-xy)] == 1 (mod m^2) |
|
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 |
|
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. |
|
// JS multiply "overflows" differently from C/C++, so care is needed here. |
|
function $1831e702d86f54be$var$bnpInvDigit() { |
|
if (this.t < 1) return 0; |
|
var x = this.data[0]; |
|
if ((x & 1) == 0) return 0; |
|
var y = x & 3; // y == 1/x mod 2^2 |
|
y = y * (2 - (x & 15) * y) & 15; // y == 1/x mod 2^4 |
|
y = y * (2 - (x & 255) * y) & 255; // y == 1/x mod 2^8 |
|
y = y * (2 - ((x & 65535) * y & 65535)) & 65535; // y == 1/x mod 2^16 |
|
// last step - calculate inverse mod DV directly; |
|
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints |
|
y = y * (2 - x * y % this.DV) % this.DV; // y == 1/x mod 2^dbits |
|
// we really want the negative inverse, and -DV < y < DV |
|
return y > 0 ? this.DV - y : -y; |
|
} |
|
// Montgomery reduction |
|
function $1831e702d86f54be$var$Montgomery(m) { |
|
this.m = m; |
|
this.mp = m.invDigit(); |
|
this.mpl = this.mp & 32767; |
|
this.mph = this.mp >> 15; |
|
this.um = (1 << m.DB - 15) - 1; |
|
this.mt2 = 2 * m.t; |
|
} |
|
// xR mod m |
|
function $1831e702d86f54be$var$montConvert(x) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
x.abs().dlShiftTo(this.m.t, r); |
|
r.divRemTo(this.m, null, r); |
|
if (x.s < 0 && r.compareTo($1831e702d86f54be$var$BigInteger.ZERO) > 0) this.m.subTo(r, r); |
|
return r; |
|
} |
|
// x/R mod m |
|
function $1831e702d86f54be$var$montRevert(x) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
x.copyTo(r); |
|
this.reduce(r); |
|
return r; |
|
} |
|
// x = x/R mod m (HAC 14.32) |
|
function $1831e702d86f54be$var$montReduce(x) { |
|
while(x.t <= this.mt2)x.data[x.t++] = 0; |
|
for(var i = 0; i < this.m.t; ++i){ |
|
// faster way of calculating u0 = x.data[i]*mp mod DV |
|
var j = x.data[i] & 32767; |
|
var u0 = j * this.mpl + ((j * this.mph + (x.data[i] >> 15) * this.mpl & this.um) << 15) & x.DM; |
|
// use am to combine the multiply-shift-add into one call |
|
j = i + this.m.t; |
|
x.data[j] += this.m.am(0, u0, x, i, 0, this.m.t); |
|
// propagate carry |
|
while(x.data[j] >= x.DV){ |
|
x.data[j] -= x.DV; |
|
x.data[++j]++; |
|
} |
|
} |
|
x.clamp(); |
|
x.drShiftTo(this.m.t, x); |
|
if (x.compareTo(this.m) >= 0) x.subTo(this.m, x); |
|
} |
|
// r = "x^2/R mod m"; x != r |
|
function $1831e702d86f54be$var$montSqrTo(x, r) { |
|
x.squareTo(r); |
|
this.reduce(r); |
|
} |
|
// r = "xy/R mod m"; x,y != r |
|
function $1831e702d86f54be$var$montMulTo(x, y, r) { |
|
x.multiplyTo(y, r); |
|
this.reduce(r); |
|
} |
|
$1831e702d86f54be$var$Montgomery.prototype.convert = $1831e702d86f54be$var$montConvert; |
|
$1831e702d86f54be$var$Montgomery.prototype.revert = $1831e702d86f54be$var$montRevert; |
|
$1831e702d86f54be$var$Montgomery.prototype.reduce = $1831e702d86f54be$var$montReduce; |
|
$1831e702d86f54be$var$Montgomery.prototype.mulTo = $1831e702d86f54be$var$montMulTo; |
|
$1831e702d86f54be$var$Montgomery.prototype.sqrTo = $1831e702d86f54be$var$montSqrTo; |
|
// (protected) true iff this is even |
|
function $1831e702d86f54be$var$bnpIsEven() { |
|
return (this.t > 0 ? this.data[0] & 1 : this.s) == 0; |
|
} |
|
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) |
|
function $1831e702d86f54be$var$bnpExp(e, z) { |
|
if (e > 4294967295 || e < 1) return $1831e702d86f54be$var$BigInteger.ONE; |
|
var r = $1831e702d86f54be$var$nbi(), r2 = $1831e702d86f54be$var$nbi(), g = z.convert(this), i = $1831e702d86f54be$var$nbits(e) - 1; |
|
g.copyTo(r); |
|
while(--i >= 0){ |
|
z.sqrTo(r, r2); |
|
if ((e & 1 << i) > 0) z.mulTo(r2, g, r); |
|
else { |
|
var t = r; |
|
r = r2; |
|
r2 = t; |
|
} |
|
} |
|
return z.revert(r); |
|
} |
|
// (public) this^e % m, 0 <= e < 2^32 |
|
function $1831e702d86f54be$var$bnModPowInt(e, m) { |
|
var z; |
|
if (e < 256 || m.isEven()) z = new $1831e702d86f54be$var$Classic(m); |
|
else z = new $1831e702d86f54be$var$Montgomery(m); |
|
return this.exp(e, z); |
|
} |
|
// protected |
|
$1831e702d86f54be$var$BigInteger.prototype.copyTo = $1831e702d86f54be$var$bnpCopyTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.fromInt = $1831e702d86f54be$var$bnpFromInt; |
|
$1831e702d86f54be$var$BigInteger.prototype.fromString = $1831e702d86f54be$var$bnpFromString; |
|
$1831e702d86f54be$var$BigInteger.prototype.clamp = $1831e702d86f54be$var$bnpClamp; |
|
$1831e702d86f54be$var$BigInteger.prototype.dlShiftTo = $1831e702d86f54be$var$bnpDLShiftTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.drShiftTo = $1831e702d86f54be$var$bnpDRShiftTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.lShiftTo = $1831e702d86f54be$var$bnpLShiftTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.rShiftTo = $1831e702d86f54be$var$bnpRShiftTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.subTo = $1831e702d86f54be$var$bnpSubTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.multiplyTo = $1831e702d86f54be$var$bnpMultiplyTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.squareTo = $1831e702d86f54be$var$bnpSquareTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.divRemTo = $1831e702d86f54be$var$bnpDivRemTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.invDigit = $1831e702d86f54be$var$bnpInvDigit; |
|
$1831e702d86f54be$var$BigInteger.prototype.isEven = $1831e702d86f54be$var$bnpIsEven; |
|
$1831e702d86f54be$var$BigInteger.prototype.exp = $1831e702d86f54be$var$bnpExp; |
|
// public |
|
$1831e702d86f54be$var$BigInteger.prototype.toString = $1831e702d86f54be$var$bnToString; |
|
$1831e702d86f54be$var$BigInteger.prototype.negate = $1831e702d86f54be$var$bnNegate; |
|
$1831e702d86f54be$var$BigInteger.prototype.abs = $1831e702d86f54be$var$bnAbs; |
|
$1831e702d86f54be$var$BigInteger.prototype.compareTo = $1831e702d86f54be$var$bnCompareTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.bitLength = $1831e702d86f54be$var$bnBitLength; |
|
$1831e702d86f54be$var$BigInteger.prototype.mod = $1831e702d86f54be$var$bnMod; |
|
$1831e702d86f54be$var$BigInteger.prototype.modPowInt = $1831e702d86f54be$var$bnModPowInt; |
|
// "constants" |
|
$1831e702d86f54be$var$BigInteger.ZERO = $1831e702d86f54be$var$nbv(0); |
|
$1831e702d86f54be$var$BigInteger.ONE = $1831e702d86f54be$var$nbv(1); |
|
// jsbn2 lib |
|
//Copyright (c) 2005-2009 Tom Wu |
|
//All Rights Reserved. |
|
//See "LICENSE" for details (See jsbn.js for LICENSE). |
|
//Extended JavaScript BN functions, required for RSA private ops. |
|
//Version 1.1: new BigInteger("0", 10) returns "proper" zero |
|
//(public) |
|
function $1831e702d86f54be$var$bnClone() { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.copyTo(r); |
|
return r; |
|
} |
|
//(public) return value as integer |
|
function $1831e702d86f54be$var$bnIntValue() { |
|
if (this.s < 0) { |
|
if (this.t == 1) return this.data[0] - this.DV; |
|
else if (this.t == 0) return -1; |
|
} else if (this.t == 1) return this.data[0]; |
|
else if (this.t == 0) return 0; |
|
// assumes 16 < DB < 32 |
|
return (this.data[1] & (1 << 32 - this.DB) - 1) << this.DB | this.data[0]; |
|
} |
|
//(public) return value as byte |
|
function $1831e702d86f54be$var$bnByteValue() { |
|
return this.t == 0 ? this.s : this.data[0] << 24 >> 24; |
|
} |
|
//(public) return value as short (assumes DB>=16) |
|
function $1831e702d86f54be$var$bnShortValue() { |
|
return this.t == 0 ? this.s : this.data[0] << 16 >> 16; |
|
} |
|
//(protected) return x s.t. r^x < DV |
|
function $1831e702d86f54be$var$bnpChunkSize(r) { |
|
return Math.floor(Math.LN2 * this.DB / Math.log(r)); |
|
} |
|
//(public) 0 if this == 0, 1 if this > 0 |
|
function $1831e702d86f54be$var$bnSigNum() { |
|
if (this.s < 0) return -1; |
|
else if (this.t <= 0 || this.t == 1 && this.data[0] <= 0) return 0; |
|
else return 1; |
|
} |
|
//(protected) convert to radix string |
|
function $1831e702d86f54be$var$bnpToRadix(b) { |
|
if (b == null) b = 10; |
|
if (this.signum() == 0 || b < 2 || b > 36) return "0"; |
|
var cs = this.chunkSize(b); |
|
var a = Math.pow(b, cs); |
|
var d = $1831e702d86f54be$var$nbv(a), y = $1831e702d86f54be$var$nbi(), z = $1831e702d86f54be$var$nbi(), r = ""; |
|
this.divRemTo(d, y, z); |
|
while(y.signum() > 0){ |
|
r = (a + z.intValue()).toString(b).substr(1) + r; |
|
y.divRemTo(d, y, z); |
|
} |
|
return z.intValue().toString(b) + r; |
|
} |
|
//(protected) convert from radix string |
|
function $1831e702d86f54be$var$bnpFromRadix(s, b) { |
|
this.fromInt(0); |
|
if (b == null) b = 10; |
|
var cs = this.chunkSize(b); |
|
var d = Math.pow(b, cs), mi = false, j = 0, w = 0; |
|
for(var i = 0; i < s.length; ++i){ |
|
var x = $1831e702d86f54be$var$intAt(s, i); |
|
if (x < 0) { |
|
if (s.charAt(i) == "-" && this.signum() == 0) mi = true; |
|
continue; |
|
} |
|
w = b * w + x; |
|
if (++j >= cs) { |
|
this.dMultiply(d); |
|
this.dAddOffset(w, 0); |
|
j = 0; |
|
w = 0; |
|
} |
|
} |
|
if (j > 0) { |
|
this.dMultiply(Math.pow(b, j)); |
|
this.dAddOffset(w, 0); |
|
} |
|
if (mi) $1831e702d86f54be$var$BigInteger.ZERO.subTo(this, this); |
|
} |
|
//(protected) alternate constructor |
|
function $1831e702d86f54be$var$bnpFromNumber(a, b, c) { |
|
if ("number" == typeof b) { |
|
// new BigInteger(int,int,RNG) |
|
if (a < 2) this.fromInt(1); |
|
else { |
|
this.fromNumber(a, c); |
|
if (!this.testBit(a - 1)) this.bitwiseTo($1831e702d86f54be$var$BigInteger.ONE.shiftLeft(a - 1), $1831e702d86f54be$var$op_or, this); |
|
if (this.isEven()) this.dAddOffset(1, 0); // force odd |
|
while(!this.isProbablePrime(b)){ |
|
this.dAddOffset(2, 0); |
|
if (this.bitLength() > a) this.subTo($1831e702d86f54be$var$BigInteger.ONE.shiftLeft(a - 1), this); |
|
} |
|
} |
|
} else { |
|
// new BigInteger(int,RNG) |
|
var x = new Array(), t = a & 7; |
|
x.length = (a >> 3) + 1; |
|
b.nextBytes(x); |
|
if (t > 0) x[0] &= (1 << t) - 1; |
|
else x[0] = 0; |
|
this.fromString(x, 256); |
|
} |
|
} |
|
//(public) convert to bigendian byte array |
|
function $1831e702d86f54be$var$bnToByteArray() { |
|
var i = this.t, r = new Array(); |
|
r[0] = this.s; |
|
var p = this.DB - i * this.DB % 8, d, k = 0; |
|
if (i-- > 0) { |
|
if (p < this.DB && (d = this.data[i] >> p) != (this.s & this.DM) >> p) r[k++] = d | this.s << this.DB - p; |
|
while(i >= 0){ |
|
if (p < 8) { |
|
d = (this.data[i] & (1 << p) - 1) << 8 - p; |
|
d |= this.data[--i] >> (p += this.DB - 8); |
|
} else { |
|
d = this.data[i] >> (p -= 8) & 255; |
|
if (p <= 0) { |
|
p += this.DB; |
|
--i; |
|
} |
|
} |
|
if ((d & 128) != 0) d |= -256; |
|
if (k == 0 && (this.s & 128) != (d & 128)) ++k; |
|
if (k > 0 || d != this.s) r[k++] = d; |
|
} |
|
} |
|
return r; |
|
} |
|
function $1831e702d86f54be$var$bnEquals(a) { |
|
return this.compareTo(a) == 0; |
|
} |
|
function $1831e702d86f54be$var$bnMin(a) { |
|
return this.compareTo(a) < 0 ? this : a; |
|
} |
|
function $1831e702d86f54be$var$bnMax(a) { |
|
return this.compareTo(a) > 0 ? this : a; |
|
} |
|
//(protected) r = this op a (bitwise) |
|
function $1831e702d86f54be$var$bnpBitwiseTo(a, op, r) { |
|
var i, f, m = Math.min(a.t, this.t); |
|
for(i = 0; i < m; ++i)r.data[i] = op(this.data[i], a.data[i]); |
|
if (a.t < this.t) { |
|
f = a.s & this.DM; |
|
for(i = m; i < this.t; ++i)r.data[i] = op(this.data[i], f); |
|
r.t = this.t; |
|
} else { |
|
f = this.s & this.DM; |
|
for(i = m; i < a.t; ++i)r.data[i] = op(f, a.data[i]); |
|
r.t = a.t; |
|
} |
|
r.s = op(this.s, a.s); |
|
r.clamp(); |
|
} |
|
//(public) this & a |
|
function $1831e702d86f54be$var$op_and(x, y) { |
|
return x & y; |
|
} |
|
function $1831e702d86f54be$var$bnAnd(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.bitwiseTo(a, $1831e702d86f54be$var$op_and, r); |
|
return r; |
|
} |
|
//(public) this | a |
|
function $1831e702d86f54be$var$op_or(x, y) { |
|
return x | y; |
|
} |
|
function $1831e702d86f54be$var$bnOr(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.bitwiseTo(a, $1831e702d86f54be$var$op_or, r); |
|
return r; |
|
} |
|
//(public) this ^ a |
|
function $1831e702d86f54be$var$op_xor(x, y) { |
|
return x ^ y; |
|
} |
|
function $1831e702d86f54be$var$bnXor(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.bitwiseTo(a, $1831e702d86f54be$var$op_xor, r); |
|
return r; |
|
} |
|
//(public) this & ~a |
|
function $1831e702d86f54be$var$op_andnot(x, y) { |
|
return x & ~y; |
|
} |
|
function $1831e702d86f54be$var$bnAndNot(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.bitwiseTo(a, $1831e702d86f54be$var$op_andnot, r); |
|
return r; |
|
} |
|
//(public) ~this |
|
function $1831e702d86f54be$var$bnNot() { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
for(var i = 0; i < this.t; ++i)r.data[i] = this.DM & ~this.data[i]; |
|
r.t = this.t; |
|
r.s = ~this.s; |
|
return r; |
|
} |
|
//(public) this << n |
|
function $1831e702d86f54be$var$bnShiftLeft(n) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
if (n < 0) this.rShiftTo(-n, r); |
|
else this.lShiftTo(n, r); |
|
return r; |
|
} |
|
//(public) this >> n |
|
function $1831e702d86f54be$var$bnShiftRight(n) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
if (n < 0) this.lShiftTo(-n, r); |
|
else this.rShiftTo(n, r); |
|
return r; |
|
} |
|
//return index of lowest 1-bit in x, x < 2^31 |
|
function $1831e702d86f54be$var$lbit(x) { |
|
if (x == 0) return -1; |
|
var r = 0; |
|
if ((x & 65535) == 0) { |
|
x >>= 16; |
|
r += 16; |
|
} |
|
if ((x & 255) == 0) { |
|
x >>= 8; |
|
r += 8; |
|
} |
|
if ((x & 15) == 0) { |
|
x >>= 4; |
|
r += 4; |
|
} |
|
if ((x & 3) == 0) { |
|
x >>= 2; |
|
r += 2; |
|
} |
|
if ((x & 1) == 0) ++r; |
|
return r; |
|
} |
|
//(public) returns index of lowest 1-bit (or -1 if none) |
|
function $1831e702d86f54be$var$bnGetLowestSetBit() { |
|
for(var i = 0; i < this.t; ++i)if (this.data[i] != 0) return i * this.DB + $1831e702d86f54be$var$lbit(this.data[i]); |
|
if (this.s < 0) return this.t * this.DB; |
|
return -1; |
|
} |
|
//return number of 1 bits in x |
|
function $1831e702d86f54be$var$cbit(x) { |
|
var r = 0; |
|
while(x != 0){ |
|
x &= x - 1; |
|
++r; |
|
} |
|
return r; |
|
} |
|
//(public) return number of set bits |
|
function $1831e702d86f54be$var$bnBitCount() { |
|
var r = 0, x = this.s & this.DM; |
|
for(var i = 0; i < this.t; ++i)r += $1831e702d86f54be$var$cbit(this.data[i] ^ x); |
|
return r; |
|
} |
|
//(public) true iff nth bit is set |
|
function $1831e702d86f54be$var$bnTestBit(n) { |
|
var j = Math.floor(n / this.DB); |
|
if (j >= this.t) return this.s != 0; |
|
return (this.data[j] & 1 << n % this.DB) != 0; |
|
} |
|
//(protected) this op (1<<n) |
|
function $1831e702d86f54be$var$bnpChangeBit(n, op) { |
|
var r = $1831e702d86f54be$var$BigInteger.ONE.shiftLeft(n); |
|
this.bitwiseTo(r, op, r); |
|
return r; |
|
} |
|
//(public) this | (1<<n) |
|
function $1831e702d86f54be$var$bnSetBit(n) { |
|
return this.changeBit(n, $1831e702d86f54be$var$op_or); |
|
} |
|
//(public) this & ~(1<<n) |
|
function $1831e702d86f54be$var$bnClearBit(n) { |
|
return this.changeBit(n, $1831e702d86f54be$var$op_andnot); |
|
} |
|
//(public) this ^ (1<<n) |
|
function $1831e702d86f54be$var$bnFlipBit(n) { |
|
return this.changeBit(n, $1831e702d86f54be$var$op_xor); |
|
} |
|
//(protected) r = this + a |
|
function $1831e702d86f54be$var$bnpAddTo(a, r) { |
|
var i = 0, c = 0, m = Math.min(a.t, this.t); |
|
while(i < m){ |
|
c += this.data[i] + a.data[i]; |
|
r.data[i++] = c & this.DM; |
|
c >>= this.DB; |
|
} |
|
if (a.t < this.t) { |
|
c += a.s; |
|
while(i < this.t){ |
|
c += this.data[i]; |
|
r.data[i++] = c & this.DM; |
|
c >>= this.DB; |
|
} |
|
c += this.s; |
|
} else { |
|
c += this.s; |
|
while(i < a.t){ |
|
c += a.data[i]; |
|
r.data[i++] = c & this.DM; |
|
c >>= this.DB; |
|
} |
|
c += a.s; |
|
} |
|
r.s = c < 0 ? -1 : 0; |
|
if (c > 0) r.data[i++] = c; |
|
else if (c < -1) r.data[i++] = this.DV + c; |
|
r.t = i; |
|
r.clamp(); |
|
} |
|
//(public) this + a |
|
function $1831e702d86f54be$var$bnAdd(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.addTo(a, r); |
|
return r; |
|
} |
|
//(public) this - a |
|
function $1831e702d86f54be$var$bnSubtract(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.subTo(a, r); |
|
return r; |
|
} |
|
//(public) this * a |
|
function $1831e702d86f54be$var$bnMultiply(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.multiplyTo(a, r); |
|
return r; |
|
} |
|
//(public) this / a |
|
function $1831e702d86f54be$var$bnDivide(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.divRemTo(a, r, null); |
|
return r; |
|
} |
|
//(public) this % a |
|
function $1831e702d86f54be$var$bnRemainder(a) { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
this.divRemTo(a, null, r); |
|
return r; |
|
} |
|
//(public) [this/a,this%a] |
|
function $1831e702d86f54be$var$bnDivideAndRemainder(a) { |
|
var q = $1831e702d86f54be$var$nbi(), r = $1831e702d86f54be$var$nbi(); |
|
this.divRemTo(a, q, r); |
|
return new Array(q, r); |
|
} |
|
//(protected) this *= n, this >= 0, 1 < n < DV |
|
function $1831e702d86f54be$var$bnpDMultiply(n) { |
|
this.data[this.t] = this.am(0, n - 1, this, 0, 0, this.t); |
|
++this.t; |
|
this.clamp(); |
|
} |
|
//(protected) this += n << w words, this >= 0 |
|
function $1831e702d86f54be$var$bnpDAddOffset(n, w) { |
|
if (n == 0) return; |
|
while(this.t <= w)this.data[this.t++] = 0; |
|
this.data[w] += n; |
|
while(this.data[w] >= this.DV){ |
|
this.data[w] -= this.DV; |
|
if (++w >= this.t) this.data[this.t++] = 0; |
|
++this.data[w]; |
|
} |
|
} |
|
//A "null" reducer |
|
function $1831e702d86f54be$var$NullExp() { |
|
} |
|
function $1831e702d86f54be$var$nNop(x) { |
|
return x; |
|
} |
|
function $1831e702d86f54be$var$nMulTo(x, y, r) { |
|
x.multiplyTo(y, r); |
|
} |
|
function $1831e702d86f54be$var$nSqrTo(x, r) { |
|
x.squareTo(r); |
|
} |
|
$1831e702d86f54be$var$NullExp.prototype.convert = $1831e702d86f54be$var$nNop; |
|
$1831e702d86f54be$var$NullExp.prototype.revert = $1831e702d86f54be$var$nNop; |
|
$1831e702d86f54be$var$NullExp.prototype.mulTo = $1831e702d86f54be$var$nMulTo; |
|
$1831e702d86f54be$var$NullExp.prototype.sqrTo = $1831e702d86f54be$var$nSqrTo; |
|
//(public) this^e |
|
function $1831e702d86f54be$var$bnPow(e) { |
|
return this.exp(e, new $1831e702d86f54be$var$NullExp()); |
|
} |
|
//(protected) r = lower n words of "this * a", a.t <= n |
|
//"this" should be the larger one if appropriate. |
|
function $1831e702d86f54be$var$bnpMultiplyLowerTo(a, n, r) { |
|
var i = Math.min(this.t + a.t, n); |
|
r.s = 0; // assumes a,this >= 0 |
|
r.t = i; |
|
while(i > 0)r.data[--i] = 0; |
|
var j; |
|
for(j = r.t - this.t; i < j; ++i)r.data[i + this.t] = this.am(0, a.data[i], r, i, 0, this.t); |
|
for(j = Math.min(a.t, n); i < j; ++i)this.am(0, a.data[i], r, i, 0, n - i); |
|
r.clamp(); |
|
} |
|
//(protected) r = "this * a" without lower n words, n > 0 |
|
//"this" should be the larger one if appropriate. |
|
function $1831e702d86f54be$var$bnpMultiplyUpperTo(a, n, r) { |
|
--n; |
|
var i = r.t = this.t + a.t - n; |
|
r.s = 0; // assumes a,this >= 0 |
|
while(--i >= 0)r.data[i] = 0; |
|
for(i = Math.max(n - this.t, 0); i < a.t; ++i)r.data[this.t + i - n] = this.am(n - i, a.data[i], r, 0, 0, this.t + i - n); |
|
r.clamp(); |
|
r.drShiftTo(1, r); |
|
} |
|
//Barrett modular reduction |
|
function $1831e702d86f54be$var$Barrett(m) { |
|
// setup Barrett |
|
this.r2 = $1831e702d86f54be$var$nbi(); |
|
this.q3 = $1831e702d86f54be$var$nbi(); |
|
$1831e702d86f54be$var$BigInteger.ONE.dlShiftTo(2 * m.t, this.r2); |
|
this.mu = this.r2.divide(m); |
|
this.m = m; |
|
} |
|
function $1831e702d86f54be$var$barrettConvert(x) { |
|
if (x.s < 0 || x.t > 2 * this.m.t) return x.mod(this.m); |
|
else if (x.compareTo(this.m) < 0) return x; |
|
else { |
|
var r = $1831e702d86f54be$var$nbi(); |
|
x.copyTo(r); |
|
this.reduce(r); |
|
return r; |
|
} |
|
} |
|
function $1831e702d86f54be$var$barrettRevert(x) { |
|
return x; |
|
} |
|
//x = x mod m (HAC 14.42) |
|
function $1831e702d86f54be$var$barrettReduce(x) { |
|
x.drShiftTo(this.m.t - 1, this.r2); |
|
if (x.t > this.m.t + 1) { |
|
x.t = this.m.t + 1; |
|
x.clamp(); |
|
} |
|
this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3); |
|
this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2); |
|
while(x.compareTo(this.r2) < 0)x.dAddOffset(1, this.m.t + 1); |
|
x.subTo(this.r2, x); |
|
while(x.compareTo(this.m) >= 0)x.subTo(this.m, x); |
|
} |
|
//r = x^2 mod m; x != r |
|
function $1831e702d86f54be$var$barrettSqrTo(x, r) { |
|
x.squareTo(r); |
|
this.reduce(r); |
|
} |
|
//r = x*y mod m; x,y != r |
|
function $1831e702d86f54be$var$barrettMulTo(x, y, r) { |
|
x.multiplyTo(y, r); |
|
this.reduce(r); |
|
} |
|
$1831e702d86f54be$var$Barrett.prototype.convert = $1831e702d86f54be$var$barrettConvert; |
|
$1831e702d86f54be$var$Barrett.prototype.revert = $1831e702d86f54be$var$barrettRevert; |
|
$1831e702d86f54be$var$Barrett.prototype.reduce = $1831e702d86f54be$var$barrettReduce; |
|
$1831e702d86f54be$var$Barrett.prototype.mulTo = $1831e702d86f54be$var$barrettMulTo; |
|
$1831e702d86f54be$var$Barrett.prototype.sqrTo = $1831e702d86f54be$var$barrettSqrTo; |
|
//(public) this^e % m (HAC 14.85) |
|
function $1831e702d86f54be$var$bnModPow(e, m) { |
|
var i = e.bitLength(), k, r = $1831e702d86f54be$var$nbv(1), z; |
|
if (i <= 0) return r; |
|
else if (i < 18) k = 1; |
|
else if (i < 48) k = 3; |
|
else if (i < 144) k = 4; |
|
else if (i < 768) k = 5; |
|
else k = 6; |
|
if (i < 8) z = new $1831e702d86f54be$var$Classic(m); |
|
else if (m.isEven()) z = new $1831e702d86f54be$var$Barrett(m); |
|
else z = new $1831e702d86f54be$var$Montgomery(m); |
|
// precomputation |
|
var g = new Array(), n = 3, k1 = k - 1, km = (1 << k) - 1; |
|
g[1] = z.convert(this); |
|
if (k > 1) { |
|
var g2 = $1831e702d86f54be$var$nbi(); |
|
z.sqrTo(g[1], g2); |
|
while(n <= km){ |
|
g[n] = $1831e702d86f54be$var$nbi(); |
|
z.mulTo(g2, g[n - 2], g[n]); |
|
n += 2; |
|
} |
|
} |
|
var j = e.t - 1, w, is1 = true, r2 = $1831e702d86f54be$var$nbi(), t; |
|
i = $1831e702d86f54be$var$nbits(e.data[j]) - 1; |
|
while(j >= 0){ |
|
if (i >= k1) w = e.data[j] >> i - k1 & km; |
|
else { |
|
w = (e.data[j] & (1 << i + 1) - 1) << k1 - i; |
|
if (j > 0) w |= e.data[j - 1] >> this.DB + i - k1; |
|
} |
|
n = k; |
|
while((w & 1) == 0){ |
|
w >>= 1; |
|
--n; |
|
} |
|
if ((i -= n) < 0) { |
|
i += this.DB; |
|
--j; |
|
} |
|
if (is1) { |
|
g[w].copyTo(r); |
|
is1 = false; |
|
} else { |
|
while(n > 1){ |
|
z.sqrTo(r, r2); |
|
z.sqrTo(r2, r); |
|
n -= 2; |
|
} |
|
if (n > 0) z.sqrTo(r, r2); |
|
else { |
|
t = r; |
|
r = r2; |
|
r2 = t; |
|
} |
|
z.mulTo(r2, g[w], r); |
|
} |
|
while(j >= 0 && (e.data[j] & 1 << i) == 0){ |
|
z.sqrTo(r, r2); |
|
t = r; |
|
r = r2; |
|
r2 = t; |
|
if (--i < 0) { |
|
i = this.DB - 1; |
|
--j; |
|
} |
|
} |
|
} |
|
return z.revert(r); |
|
} |
|
//(public) gcd(this,a) (HAC 14.54) |
|
function $1831e702d86f54be$var$bnGCD(a) { |
|
var x = this.s < 0 ? this.negate() : this.clone(); |
|
var y = a.s < 0 ? a.negate() : a.clone(); |
|
if (x.compareTo(y) < 0) { |
|
var t = x; |
|
x = y; |
|
y = t; |
|
} |
|
var i = x.getLowestSetBit(), g = y.getLowestSetBit(); |
|
if (g < 0) return x; |
|
if (i < g) g = i; |
|
if (g > 0) { |
|
x.rShiftTo(g, x); |
|
y.rShiftTo(g, y); |
|
} |
|
while(x.signum() > 0){ |
|
if ((i = x.getLowestSetBit()) > 0) x.rShiftTo(i, x); |
|
if ((i = y.getLowestSetBit()) > 0) y.rShiftTo(i, y); |
|
if (x.compareTo(y) >= 0) { |
|
x.subTo(y, x); |
|
x.rShiftTo(1, x); |
|
} else { |
|
y.subTo(x, y); |
|
y.rShiftTo(1, y); |
|
} |
|
} |
|
if (g > 0) y.lShiftTo(g, y); |
|
return y; |
|
} |
|
//(protected) this % n, n < 2^26 |
|
function $1831e702d86f54be$var$bnpModInt(n) { |
|
if (n <= 0) return 0; |
|
var d = this.DV % n, r = this.s < 0 ? n - 1 : 0; |
|
if (this.t > 0) { |
|
if (d == 0) r = this.data[0] % n; |
|
else for(var i = this.t - 1; i >= 0; --i)r = (d * r + this.data[i]) % n; |
|
} |
|
return r; |
|
} |
|
//(public) 1/this % m (HAC 14.61) |
|
function $1831e702d86f54be$var$bnModInverse(m) { |
|
var ac = m.isEven(); |
|
if (this.isEven() && ac || m.signum() == 0) return $1831e702d86f54be$var$BigInteger.ZERO; |
|
var u = m.clone(), v = this.clone(); |
|
var a = $1831e702d86f54be$var$nbv(1), b = $1831e702d86f54be$var$nbv(0), c = $1831e702d86f54be$var$nbv(0), d = $1831e702d86f54be$var$nbv(1); |
|
while(u.signum() != 0){ |
|
while(u.isEven()){ |
|
u.rShiftTo(1, u); |
|
if (ac) { |
|
if (!a.isEven() || !b.isEven()) { |
|
a.addTo(this, a); |
|
b.subTo(m, b); |
|
} |
|
a.rShiftTo(1, a); |
|
} else if (!b.isEven()) b.subTo(m, b); |
|
b.rShiftTo(1, b); |
|
} |
|
while(v.isEven()){ |
|
v.rShiftTo(1, v); |
|
if (ac) { |
|
if (!c.isEven() || !d.isEven()) { |
|
c.addTo(this, c); |
|
d.subTo(m, d); |
|
} |
|
c.rShiftTo(1, c); |
|
} else if (!d.isEven()) d.subTo(m, d); |
|
d.rShiftTo(1, d); |
|
} |
|
if (u.compareTo(v) >= 0) { |
|
u.subTo(v, u); |
|
if (ac) a.subTo(c, a); |
|
b.subTo(d, b); |
|
} else { |
|
v.subTo(u, v); |
|
if (ac) c.subTo(a, c); |
|
d.subTo(b, d); |
|
} |
|
} |
|
if (v.compareTo($1831e702d86f54be$var$BigInteger.ONE) != 0) return $1831e702d86f54be$var$BigInteger.ZERO; |
|
if (d.compareTo(m) >= 0) return d.subtract(m); |
|
if (d.signum() < 0) d.addTo(m, d); |
|
else return d; |
|
if (d.signum() < 0) return d.add(m); |
|
else return d; |
|
} |
|
var $1831e702d86f54be$var$lowprimes = [ |
|
2, |
|
3, |
|
5, |
|
7, |
|
11, |
|
13, |
|
17, |
|
19, |
|
23, |
|
29, |
|
31, |
|
37, |
|
41, |
|
43, |
|
47, |
|
53, |
|
59, |
|
61, |
|
67, |
|
71, |
|
73, |
|
79, |
|
83, |
|
89, |
|
97, |
|
101, |
|
103, |
|
107, |
|
109, |
|
113, |
|
127, |
|
131, |
|
137, |
|
139, |
|
149, |
|
151, |
|
157, |
|
163, |
|
167, |
|
173, |
|
179, |
|
181, |
|
191, |
|
193, |
|
197, |
|
199, |
|
211, |
|
223, |
|
227, |
|
229, |
|
233, |
|
239, |
|
241, |
|
251, |
|
257, |
|
263, |
|
269, |
|
271, |
|
277, |
|
281, |
|
283, |
|
293, |
|
307, |
|
311, |
|
313, |
|
317, |
|
331, |
|
337, |
|
347, |
|
349, |
|
353, |
|
359, |
|
367, |
|
373, |
|
379, |
|
383, |
|
389, |
|
397, |
|
401, |
|
409, |
|
419, |
|
421, |
|
431, |
|
433, |
|
439, |
|
443, |
|
449, |
|
457, |
|
461, |
|
463, |
|
467, |
|
479, |
|
487, |
|
491, |
|
499, |
|
503, |
|
509 |
|
]; |
|
var $1831e702d86f54be$var$lplim = 67108864 / $1831e702d86f54be$var$lowprimes[$1831e702d86f54be$var$lowprimes.length - 1]; |
|
//(public) test primality with certainty >= 1-.5^t |
|
function $1831e702d86f54be$var$bnIsProbablePrime(t) { |
|
var i, x = this.abs(); |
|
if (x.t == 1 && x.data[0] <= $1831e702d86f54be$var$lowprimes[$1831e702d86f54be$var$lowprimes.length - 1]) { |
|
for(i = 0; i < $1831e702d86f54be$var$lowprimes.length; ++i)if (x.data[0] == $1831e702d86f54be$var$lowprimes[i]) return true; |
|
return false; |
|
} |
|
if (x.isEven()) return false; |
|
i = 1; |
|
while(i < $1831e702d86f54be$var$lowprimes.length){ |
|
var m = $1831e702d86f54be$var$lowprimes[i], j = i + 1; |
|
while(j < $1831e702d86f54be$var$lowprimes.length && m < $1831e702d86f54be$var$lplim)m *= $1831e702d86f54be$var$lowprimes[j++]; |
|
m = x.modInt(m); |
|
while(i < j)if (m % $1831e702d86f54be$var$lowprimes[i++] == 0) return false; |
|
} |
|
return x.millerRabin(t); |
|
} |
|
//(protected) true if probably prime (HAC 4.24, Miller-Rabin) |
|
function $1831e702d86f54be$var$bnpMillerRabin(t) { |
|
var n1 = this.subtract($1831e702d86f54be$var$BigInteger.ONE); |
|
var k = n1.getLowestSetBit(); |
|
if (k <= 0) return false; |
|
var r = n1.shiftRight(k); |
|
var prng = $1831e702d86f54be$var$bnGetPrng(); |
|
var a; |
|
for(var i = 0; i < t; ++i){ |
|
// select witness 'a' at random from between 1 and n1 |
|
do a = new $1831e702d86f54be$var$BigInteger(this.bitLength(), prng); |
|
while (a.compareTo($1831e702d86f54be$var$BigInteger.ONE) <= 0 || a.compareTo(n1) >= 0) |
|
var y = a.modPow(r, this); |
|
if (y.compareTo($1831e702d86f54be$var$BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { |
|
var j = 1; |
|
while((j++) < k && y.compareTo(n1) != 0){ |
|
y = y.modPowInt(2, this); |
|
if (y.compareTo($1831e702d86f54be$var$BigInteger.ONE) == 0) return false; |
|
} |
|
if (y.compareTo(n1) != 0) return false; |
|
} |
|
} |
|
return true; |
|
} |
|
// get pseudo random number generator |
|
function $1831e702d86f54be$var$bnGetPrng() { |
|
// create prng with api that matches BigInteger secure random |
|
return { |
|
// x is an array to fill with bytes |
|
nextBytes: function(x) { |
|
for(var i = 0; i < x.length; ++i)x[i] = Math.floor(Math.random() * 256); |
|
} |
|
}; |
|
} |
|
//protected |
|
$1831e702d86f54be$var$BigInteger.prototype.chunkSize = $1831e702d86f54be$var$bnpChunkSize; |
|
$1831e702d86f54be$var$BigInteger.prototype.toRadix = $1831e702d86f54be$var$bnpToRadix; |
|
$1831e702d86f54be$var$BigInteger.prototype.fromRadix = $1831e702d86f54be$var$bnpFromRadix; |
|
$1831e702d86f54be$var$BigInteger.prototype.fromNumber = $1831e702d86f54be$var$bnpFromNumber; |
|
$1831e702d86f54be$var$BigInteger.prototype.bitwiseTo = $1831e702d86f54be$var$bnpBitwiseTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.changeBit = $1831e702d86f54be$var$bnpChangeBit; |
|
$1831e702d86f54be$var$BigInteger.prototype.addTo = $1831e702d86f54be$var$bnpAddTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.dMultiply = $1831e702d86f54be$var$bnpDMultiply; |
|
$1831e702d86f54be$var$BigInteger.prototype.dAddOffset = $1831e702d86f54be$var$bnpDAddOffset; |
|
$1831e702d86f54be$var$BigInteger.prototype.multiplyLowerTo = $1831e702d86f54be$var$bnpMultiplyLowerTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.multiplyUpperTo = $1831e702d86f54be$var$bnpMultiplyUpperTo; |
|
$1831e702d86f54be$var$BigInteger.prototype.modInt = $1831e702d86f54be$var$bnpModInt; |
|
$1831e702d86f54be$var$BigInteger.prototype.millerRabin = $1831e702d86f54be$var$bnpMillerRabin; |
|
//public |
|
$1831e702d86f54be$var$BigInteger.prototype.clone = $1831e702d86f54be$var$bnClone; |
|
$1831e702d86f54be$var$BigInteger.prototype.intValue = $1831e702d86f54be$var$bnIntValue; |
|
$1831e702d86f54be$var$BigInteger.prototype.byteValue = $1831e702d86f54be$var$bnByteValue; |
|
$1831e702d86f54be$var$BigInteger.prototype.shortValue = $1831e702d86f54be$var$bnShortValue; |
|
$1831e702d86f54be$var$BigInteger.prototype.signum = $1831e702d86f54be$var$bnSigNum; |
|
$1831e702d86f54be$var$BigInteger.prototype.toByteArray = $1831e702d86f54be$var$bnToByteArray; |
|
$1831e702d86f54be$var$BigInteger.prototype.equals = $1831e702d86f54be$var$bnEquals; |
|
$1831e702d86f54be$var$BigInteger.prototype.min = $1831e702d86f54be$var$bnMin; |
|
$1831e702d86f54be$var$BigInteger.prototype.max = $1831e702d86f54be$var$bnMax; |
|
$1831e702d86f54be$var$BigInteger.prototype.and = $1831e702d86f54be$var$bnAnd; |
|
$1831e702d86f54be$var$BigInteger.prototype.or = $1831e702d86f54be$var$bnOr; |
|
$1831e702d86f54be$var$BigInteger.prototype.xor = $1831e702d86f54be$var$bnXor; |
|
$1831e702d86f54be$var$BigInteger.prototype.andNot = $1831e702d86f54be$var$bnAndNot; |
|
$1831e702d86f54be$var$BigInteger.prototype.not = $1831e702d86f54be$var$bnNot; |
|
$1831e702d86f54be$var$BigInteger.prototype.shiftLeft = $1831e702d86f54be$var$bnShiftLeft; |
|
$1831e702d86f54be$var$BigInteger.prototype.shiftRight = $1831e702d86f54be$var$bnShiftRight; |
|
$1831e702d86f54be$var$BigInteger.prototype.getLowestSetBit = $1831e702d86f54be$var$bnGetLowestSetBit; |
|
$1831e702d86f54be$var$BigInteger.prototype.bitCount = $1831e702d86f54be$var$bnBitCount; |
|
$1831e702d86f54be$var$BigInteger.prototype.testBit = $1831e702d86f54be$var$bnTestBit; |
|
$1831e702d86f54be$var$BigInteger.prototype.setBit = $1831e702d86f54be$var$bnSetBit; |
|
$1831e702d86f54be$var$BigInteger.prototype.clearBit = $1831e702d86f54be$var$bnClearBit; |
|
$1831e702d86f54be$var$BigInteger.prototype.flipBit = $1831e702d86f54be$var$bnFlipBit; |
|
$1831e702d86f54be$var$BigInteger.prototype.add = $1831e702d86f54be$var$bnAdd; |
|
$1831e702d86f54be$var$BigInteger.prototype.subtract = $1831e702d86f54be$var$bnSubtract; |
|
$1831e702d86f54be$var$BigInteger.prototype.multiply = $1831e702d86f54be$var$bnMultiply; |
|
$1831e702d86f54be$var$BigInteger.prototype.divide = $1831e702d86f54be$var$bnDivide; |
|
$1831e702d86f54be$var$BigInteger.prototype.remainder = $1831e702d86f54be$var$bnRemainder; |
|
$1831e702d86f54be$var$BigInteger.prototype.divideAndRemainder = $1831e702d86f54be$var$bnDivideAndRemainder; |
|
$1831e702d86f54be$var$BigInteger.prototype.modPow = $1831e702d86f54be$var$bnModPow; |
|
$1831e702d86f54be$var$BigInteger.prototype.modInverse = $1831e702d86f54be$var$bnModInverse; |
|
$1831e702d86f54be$var$BigInteger.prototype.pow = $1831e702d86f54be$var$bnPow; |
|
$1831e702d86f54be$var$BigInteger.prototype.gcd = $1831e702d86f54be$var$bnGCD; |
|
$1831e702d86f54be$var$BigInteger.prototype.isProbablePrime = $1831e702d86f54be$var$bnIsProbablePrime; //BigInteger interfaces not implemented in jsbn: |
|
//BigInteger(int signum, byte[] magnitude) |
|
//double doubleValue() |
|
//float floatValue() |
|
//int hashCode() |
|
//long longValue() |
|
//static BigInteger valueOf(long val) |
|
|
|
|
|
|
|
var $564ac6480d83471d$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
var $7dc60e406dad2a14$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
parcelRequire("ai0Z9"); |
|
|
|
var $7dc60e406dad2a14$var$sha1 = $7dc60e406dad2a14$exports = $iGlOy.sha1 = $iGlOy.sha1 || { |
|
}; |
|
$iGlOy.md.sha1 = $iGlOy.md.algorithms.sha1 = $7dc60e406dad2a14$var$sha1; |
|
/** |
|
* Creates a SHA-1 message digest object. |
|
* |
|
* @return a message digest object. |
|
*/ $7dc60e406dad2a14$var$sha1.create = function() { |
|
// do initialization as necessary |
|
if (!$7dc60e406dad2a14$var$_initialized) $7dc60e406dad2a14$var$_init(); |
|
// SHA-1 state contains five 32-bit integers |
|
var _state = null; |
|
// input buffer |
|
var _input = $iGlOy.util.createBuffer(); |
|
// used for word storage |
|
var _w = new Array(80); |
|
// message digest object |
|
var md = { |
|
algorithm: 'sha1', |
|
blockLength: 64, |
|
digestLength: 20, |
|
// 56-bit length of message so far (does not including padding) |
|
messageLength: 0, |
|
// true message length |
|
fullMessageLength: null, |
|
// size of message length in bytes |
|
messageLengthSize: 8 |
|
}; |
|
/** |
|
* Starts the digest. |
|
* |
|
* @return this digest object. |
|
*/ md.start = function() { |
|
// up to 56-bit message length for convenience |
|
md.messageLength = 0; |
|
// full message length (set md.messageLength64 for backwards-compatibility) |
|
md.fullMessageLength = md.messageLength64 = []; |
|
var int32s = md.messageLengthSize / 4; |
|
for(var i = 0; i < int32s; ++i)md.fullMessageLength.push(0); |
|
_input = $iGlOy.util.createBuffer(); |
|
_state = { |
|
h0: 1732584193, |
|
h1: 4023233417, |
|
h2: 2562383102, |
|
h3: 271733878, |
|
h4: 3285377520 |
|
}; |
|
return md; |
|
}; |
|
// start digest automatically for first time |
|
md.start(); |
|
/** |
|
* Updates the digest with the given message input. The given input can |
|
* treated as raw input (no encoding will be applied) or an encoding of |
|
* 'utf8' maybe given to encode the input using UTF-8. |
|
* |
|
* @param msg the message input to update with. |
|
* @param encoding the encoding to use (default: 'raw', other: 'utf8'). |
|
* |
|
* @return this digest object. |
|
*/ md.update = function(msg, encoding) { |
|
if (encoding === 'utf8') msg = $iGlOy.util.encodeUtf8(msg); |
|
// update message length |
|
var len = msg.length; |
|
md.messageLength += len; |
|
len = [ |
|
len / 4294967296 >>> 0, |
|
len >>> 0 |
|
]; |
|
for(var i = md.fullMessageLength.length - 1; i >= 0; --i){ |
|
md.fullMessageLength[i] += len[1]; |
|
len[1] = len[0] + (md.fullMessageLength[i] / 4294967296 >>> 0); |
|
md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; |
|
len[0] = len[1] / 4294967296 >>> 0; |
|
} |
|
// add bytes to input buffer |
|
_input.putBytes(msg); |
|
// process bytes |
|
$7dc60e406dad2a14$var$_update(_state, _w, _input); |
|
// compact input buffer every 2K or if empty |
|
if (_input.read > 2048 || _input.length() === 0) _input.compact(); |
|
return md; |
|
}; |
|
/** |
|
* Produces the digest. |
|
* |
|
* @return a byte buffer containing the digest value. |
|
*/ md.digest = function() { |
|
/* Note: Here we copy the remaining bytes in the input buffer and |
|
add the appropriate SHA-1 padding. Then we do the final update |
|
on a copy of the state so that if the user wants to get |
|
intermediate digests they can do so. */ /* Determine the number of bytes that must be added to the message |
|
to ensure its length is congruent to 448 mod 512. In other words, |
|
the data to be digested must be a multiple of 512 bits (or 128 bytes). |
|
This data includes the message, some padding, and the length of the |
|
message. Since the length of the message will be encoded as 8 bytes (64 |
|
bits), that means that the last segment of the data must have 56 bytes |
|
(448 bits) of message and padding. Therefore, the length of the message |
|
plus the padding must be congruent to 448 mod 512 because |
|
512 - 128 = 448. |
|
|
|
In order to fill up the message length it must be filled with |
|
padding that begins with 1 bit followed by all 0 bits. Padding |
|
must *always* be present, so if the message length is already |
|
congruent to 448 mod 512, then 512 padding bits must be added. */ var finalBlock = $iGlOy.util.createBuffer(); |
|
finalBlock.putBytes(_input.bytes()); |
|
// compute remaining size to be digested (include message length size) |
|
var remaining = md.fullMessageLength[md.fullMessageLength.length - 1] + md.messageLengthSize; |
|
// add padding for overflow blockSize - overflow |
|
// _padding starts with 1 byte with first bit is set (byte value 128), then |
|
// there may be up to (blockSize - 1) other pad bytes |
|
var overflow = remaining & md.blockLength - 1; |
|
finalBlock.putBytes($7dc60e406dad2a14$var$_padding.substr(0, md.blockLength - overflow)); |
|
// serialize message length in bits in big-endian order; since length |
|
// is stored in bytes we multiply by 8 and add carry from next int |
|
var next, carry; |
|
var bits = md.fullMessageLength[0] * 8; |
|
for(var i = 0; i < md.fullMessageLength.length - 1; ++i){ |
|
next = md.fullMessageLength[i + 1] * 8; |
|
carry = next / 4294967296 >>> 0; |
|
bits += carry; |
|
finalBlock.putInt32(bits >>> 0); |
|
bits = next >>> 0; |
|
} |
|
finalBlock.putInt32(bits); |
|
var s2 = { |
|
h0: _state.h0, |
|
h1: _state.h1, |
|
h2: _state.h2, |
|
h3: _state.h3, |
|
h4: _state.h4 |
|
}; |
|
$7dc60e406dad2a14$var$_update(s2, _w, finalBlock); |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putInt32(s2.h0); |
|
rval.putInt32(s2.h1); |
|
rval.putInt32(s2.h2); |
|
rval.putInt32(s2.h3); |
|
rval.putInt32(s2.h4); |
|
return rval; |
|
}; |
|
return md; |
|
}; |
|
// sha-1 padding bytes not initialized yet |
|
var $7dc60e406dad2a14$var$_padding = null; |
|
var $7dc60e406dad2a14$var$_initialized = false; |
|
/** |
|
* Initializes the constant tables. |
|
*/ function $7dc60e406dad2a14$var$_init() { |
|
// create padding |
|
$7dc60e406dad2a14$var$_padding = String.fromCharCode(128); |
|
$7dc60e406dad2a14$var$_padding += $iGlOy.util.fillString(String.fromCharCode(0), 64); |
|
// now initialized |
|
$7dc60e406dad2a14$var$_initialized = true; |
|
} |
|
/** |
|
* Updates a SHA-1 state with the given byte buffer. |
|
* |
|
* @param s the SHA-1 state to update. |
|
* @param w the array to use to store words. |
|
* @param bytes the byte buffer to update with. |
|
*/ function $7dc60e406dad2a14$var$_update(s, w, bytes) { |
|
// consume 512 bit (64 byte) chunks |
|
var t, a, b, c, d, e, f, i; |
|
var len = bytes.length(); |
|
while(len >= 64){ |
|
// the w array will be populated with sixteen 32-bit big-endian words |
|
// and then extended into 80 32-bit words according to SHA-1 algorithm |
|
// and for 32-79 using Max Locktyukhin's optimization |
|
// initialize hash value for this chunk |
|
a = s.h0; |
|
b = s.h1; |
|
c = s.h2; |
|
d = s.h3; |
|
e = s.h4; |
|
// round 1 |
|
for(i = 0; i < 16; ++i){ |
|
t = bytes.getInt32(); |
|
w[i] = t; |
|
f = d ^ b & (c ^ d); |
|
t = (a << 5 | a >>> 27) + f + e + 1518500249 + t; |
|
e = d; |
|
d = c; |
|
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug |
|
c = (b << 30 | b >>> 2) >>> 0; |
|
b = a; |
|
a = t; |
|
} |
|
for(; i < 20; ++i){ |
|
t = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]; |
|
t = t << 1 | t >>> 31; |
|
w[i] = t; |
|
f = d ^ b & (c ^ d); |
|
t = (a << 5 | a >>> 27) + f + e + 1518500249 + t; |
|
e = d; |
|
d = c; |
|
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug |
|
c = (b << 30 | b >>> 2) >>> 0; |
|
b = a; |
|
a = t; |
|
} |
|
// round 2 |
|
for(; i < 32; ++i){ |
|
t = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]; |
|
t = t << 1 | t >>> 31; |
|
w[i] = t; |
|
f = b ^ c ^ d; |
|
t = (a << 5 | a >>> 27) + f + e + 1859775393 + t; |
|
e = d; |
|
d = c; |
|
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug |
|
c = (b << 30 | b >>> 2) >>> 0; |
|
b = a; |
|
a = t; |
|
} |
|
for(; i < 40; ++i){ |
|
t = w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]; |
|
t = t << 2 | t >>> 30; |
|
w[i] = t; |
|
f = b ^ c ^ d; |
|
t = (a << 5 | a >>> 27) + f + e + 1859775393 + t; |
|
e = d; |
|
d = c; |
|
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug |
|
c = (b << 30 | b >>> 2) >>> 0; |
|
b = a; |
|
a = t; |
|
} |
|
// round 3 |
|
for(; i < 60; ++i){ |
|
t = w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]; |
|
t = t << 2 | t >>> 30; |
|
w[i] = t; |
|
f = b & c | d & (b ^ c); |
|
t = (a << 5 | a >>> 27) + f + e + 2400959708 + t; |
|
e = d; |
|
d = c; |
|
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug |
|
c = (b << 30 | b >>> 2) >>> 0; |
|
b = a; |
|
a = t; |
|
} |
|
// round 4 |
|
for(; i < 80; ++i){ |
|
t = w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]; |
|
t = t << 2 | t >>> 30; |
|
w[i] = t; |
|
f = b ^ c ^ d; |
|
t = (a << 5 | a >>> 27) + f + e + 3395469782 + t; |
|
e = d; |
|
d = c; |
|
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug |
|
c = (b << 30 | b >>> 2) >>> 0; |
|
b = a; |
|
a = t; |
|
} |
|
// update hash state |
|
s.h0 = s.h0 + a | 0; |
|
s.h1 = s.h1 + b | 0; |
|
s.h2 = s.h2 + c | 0; |
|
s.h3 = s.h3 + d | 0; |
|
s.h4 = s.h4 + e | 0; |
|
len -= 64; |
|
} |
|
} |
|
|
|
|
|
// shortcut for PKCS#1 API |
|
var $564ac6480d83471d$var$pkcs1 = $564ac6480d83471d$exports = $iGlOy.pkcs1 = $iGlOy.pkcs1 || { |
|
}; |
|
/** |
|
* Encode the given RSAES-OAEP message (M) using key, with optional label (L) |
|
* and seed. |
|
* |
|
* This method does not perform RSA encryption, it only encodes the message |
|
* using RSAES-OAEP. |
|
* |
|
* @param key the RSA key to use. |
|
* @param message the message to encode. |
|
* @param options the options to use: |
|
* label an optional label to use. |
|
* seed the seed to use. |
|
* md the message digest object to use, undefined for SHA-1. |
|
* mgf1 optional mgf1 parameters: |
|
* md the message digest object to use for MGF1. |
|
* |
|
* @return the encoded message bytes. |
|
*/ $564ac6480d83471d$var$pkcs1.encode_rsa_oaep = function(key, message, options) { |
|
// parse arguments |
|
var label; |
|
var seed; |
|
var md; |
|
var mgf1Md; |
|
// legacy args (label, seed, md) |
|
if (typeof options === 'string') { |
|
label = options; |
|
seed = arguments[3] || undefined; |
|
md = arguments[4] || undefined; |
|
} else if (options) { |
|
label = options.label || undefined; |
|
seed = options.seed || undefined; |
|
md = options.md || undefined; |
|
if (options.mgf1 && options.mgf1.md) mgf1Md = options.mgf1.md; |
|
} |
|
// default OAEP to SHA-1 message digest |
|
if (!md) md = $iGlOy.md.sha1.create(); |
|
else md.start(); |
|
// default MGF-1 to same as OAEP |
|
if (!mgf1Md) mgf1Md = md; |
|
// compute length in bytes and check output |
|
var keyLength = Math.ceil(key.n.bitLength() / 8); |
|
var maxLength = keyLength - 2 * md.digestLength - 2; |
|
if (message.length > maxLength) { |
|
var error = new Error('RSAES-OAEP input message length is too long.'); |
|
error.length = message.length; |
|
error.maxLength = maxLength; |
|
throw error; |
|
} |
|
if (!label) label = ''; |
|
md.update(label, 'raw'); |
|
var lHash = md.digest(); |
|
var PS = ''; |
|
var PS_length = maxLength - message.length; |
|
for(var i = 0; i < PS_length; i++)PS += '\x00'; |
|
var DB = lHash.getBytes() + PS + '\x01' + message; |
|
if (!seed) seed = $iGlOy.random.getBytes(md.digestLength); |
|
else if (seed.length !== md.digestLength) { |
|
var error = new Error("Invalid RSAES-OAEP seed. The seed length must match the digest length."); |
|
error.seedLength = seed.length; |
|
error.digestLength = md.digestLength; |
|
throw error; |
|
} |
|
var dbMask = $564ac6480d83471d$var$rsa_mgf1(seed, keyLength - md.digestLength - 1, mgf1Md); |
|
var maskedDB = $iGlOy.util.xorBytes(DB, dbMask, DB.length); |
|
var seedMask = $564ac6480d83471d$var$rsa_mgf1(maskedDB, md.digestLength, mgf1Md); |
|
var maskedSeed = $iGlOy.util.xorBytes(seed, seedMask, seed.length); |
|
// return encoded message |
|
return '\x00' + maskedSeed + maskedDB; |
|
}; |
|
/** |
|
* Decode the given RSAES-OAEP encoded message (EM) using key, with optional |
|
* label (L). |
|
* |
|
* This method does not perform RSA decryption, it only decodes the message |
|
* using RSAES-OAEP. |
|
* |
|
* @param key the RSA key to use. |
|
* @param em the encoded message to decode. |
|
* @param options the options to use: |
|
* label an optional label to use. |
|
* md the message digest object to use for OAEP, undefined for SHA-1. |
|
* mgf1 optional mgf1 parameters: |
|
* md the message digest object to use for MGF1. |
|
* |
|
* @return the decoded message bytes. |
|
*/ $564ac6480d83471d$var$pkcs1.decode_rsa_oaep = function(key, em, options) { |
|
// parse args |
|
var label; |
|
var md; |
|
var mgf1Md; |
|
// legacy args |
|
if (typeof options === 'string') { |
|
label = options; |
|
md = arguments[3] || undefined; |
|
} else if (options) { |
|
label = options.label || undefined; |
|
md = options.md || undefined; |
|
if (options.mgf1 && options.mgf1.md) mgf1Md = options.mgf1.md; |
|
} |
|
// compute length in bytes |
|
var keyLength = Math.ceil(key.n.bitLength() / 8); |
|
if (em.length !== keyLength) { |
|
var error = new Error('RSAES-OAEP encoded message length is invalid.'); |
|
error.length = em.length; |
|
error.expectedLength = keyLength; |
|
throw error; |
|
} |
|
// default OAEP to SHA-1 message digest |
|
if (md === undefined) md = $iGlOy.md.sha1.create(); |
|
else md.start(); |
|
// default MGF-1 to same as OAEP |
|
if (!mgf1Md) mgf1Md = md; |
|
if (keyLength < 2 * md.digestLength + 2) throw new Error('RSAES-OAEP key is too short for the hash function.'); |
|
if (!label) label = ''; |
|
md.update(label, 'raw'); |
|
var lHash = md.digest().getBytes(); |
|
// split the message into its parts |
|
var y = em.charAt(0); |
|
var maskedSeed = em.substring(1, md.digestLength + 1); |
|
var maskedDB = em.substring(1 + md.digestLength); |
|
var seedMask = $564ac6480d83471d$var$rsa_mgf1(maskedDB, md.digestLength, mgf1Md); |
|
var seed = $iGlOy.util.xorBytes(maskedSeed, seedMask, maskedSeed.length); |
|
var dbMask = $564ac6480d83471d$var$rsa_mgf1(seed, keyLength - md.digestLength - 1, mgf1Md); |
|
var db = $iGlOy.util.xorBytes(maskedDB, dbMask, maskedDB.length); |
|
var lHashPrime = db.substring(0, md.digestLength); |
|
// constant time check that all values match what is expected |
|
var error = y !== '\x00'; |
|
// constant time check lHash vs lHashPrime |
|
for(var i = 0; i < md.digestLength; ++i)error |= lHash.charAt(i) !== lHashPrime.charAt(i); |
|
// "constant time" find the 0x1 byte separating the padding (zeros) from the |
|
// message |
|
// TODO: It must be possible to do this in a better/smarter way? |
|
var in_ps = 1; |
|
var index = md.digestLength; |
|
for(var j = md.digestLength; j < db.length; j++){ |
|
var code = db.charCodeAt(j); |
|
var is_0 = code & 1 ^ 1; |
|
// non-zero if not 0 or 1 in the ps section |
|
var error_mask = in_ps ? 65534 : 0; |
|
error |= code & error_mask; |
|
// latch in_ps to zero after we find 0x1 |
|
in_ps = in_ps & is_0; |
|
index += in_ps; |
|
} |
|
if (error || db.charCodeAt(index) !== 1) throw new Error('Invalid RSAES-OAEP padding.'); |
|
return db.substring(index + 1); |
|
}; |
|
function $564ac6480d83471d$var$rsa_mgf1(seed, maskLength, hash) { |
|
// default to SHA-1 message digest |
|
if (!hash) hash = $iGlOy.md.sha1.create(); |
|
var t = ''; |
|
var count = Math.ceil(maskLength / hash.digestLength); |
|
for(var i = 0; i < count; ++i){ |
|
var c = String.fromCharCode(i >> 24 & 255, i >> 16 & 255, i >> 8 & 255, i & 255); |
|
hash.start(); |
|
hash.update(seed + c); |
|
t += hash.digest().getBytes(); |
|
} |
|
return t.substring(0, maskLength); |
|
} |
|
|
|
|
|
var $82c15eca7626be33$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
|
|
(function() { |
|
// forge.prime already defined |
|
if ($iGlOy.prime) { |
|
$82c15eca7626be33$exports = $iGlOy.prime; |
|
return; |
|
} |
|
/* PRIME API */ var prime = $82c15eca7626be33$exports = $iGlOy.prime = $iGlOy.prime || { |
|
}; |
|
var BigInteger = $iGlOy.jsbn.BigInteger; |
|
// primes are 30k+i for i = 1, 7, 11, 13, 17, 19, 23, 29 |
|
var GCD_30_DELTA = [ |
|
6, |
|
4, |
|
2, |
|
4, |
|
2, |
|
4, |
|
6, |
|
2 |
|
]; |
|
var THIRTY = new BigInteger(null); |
|
THIRTY.fromInt(30); |
|
var op_or = function(x, y) { |
|
return x | y; |
|
}; |
|
/** |
|
* Generates a random probable prime with the given number of bits. |
|
* |
|
* Alternative algorithms can be specified by name as a string or as an |
|
* object with custom options like so: |
|
* |
|
* { |
|
* name: 'PRIMEINC', |
|
* options: { |
|
* maxBlockTime: <the maximum amount of time to block the main |
|
* thread before allowing I/O other JS to run>, |
|
* millerRabinTests: <the number of miller-rabin tests to run>, |
|
* workerScript: <the worker script URL>, |
|
* workers: <the number of web workers (if supported) to use, |
|
* -1 to use estimated cores minus one>. |
|
* workLoad: the size of the work load, ie: number of possible prime |
|
* numbers for each web worker to check per work assignment, |
|
* (default: 100). |
|
* } |
|
* } |
|
* |
|
* @param bits the number of bits for the prime number. |
|
* @param options the options to use. |
|
* [algorithm] the algorithm to use (default: 'PRIMEINC'). |
|
* [prng] a custom crypto-secure pseudo-random number generator to use, |
|
* that must define "getBytesSync". |
|
* |
|
* @return callback(err, num) called once the operation completes. |
|
*/ prime.generateProbablePrime = function(bits, options, callback) { |
|
if (typeof options === 'function') { |
|
callback = options; |
|
options = { |
|
}; |
|
} |
|
options = options || { |
|
}; |
|
// default to PRIMEINC algorithm |
|
var algorithm = options.algorithm || 'PRIMEINC'; |
|
if (typeof algorithm === 'string') algorithm = { |
|
name: algorithm |
|
}; |
|
algorithm.options = algorithm.options || { |
|
}; |
|
// create prng with api that matches BigInteger secure random |
|
var prng = options.prng || $iGlOy.random; |
|
var rng = { |
|
// x is an array to fill with bytes |
|
nextBytes: function(x) { |
|
var b = prng.getBytesSync(x.length); |
|
for(var i = 0; i < x.length; ++i)x[i] = b.charCodeAt(i); |
|
} |
|
}; |
|
if (algorithm.name === 'PRIMEINC') return primeincFindPrime(bits, rng, algorithm.options, callback); |
|
throw new Error('Invalid prime generation algorithm: ' + algorithm.name); |
|
}; |
|
function primeincFindPrime(bits, rng, options, callback) { |
|
if ('workers' in options) return primeincFindPrimeWithWorkers(bits, rng, options, callback); |
|
return primeincFindPrimeWithoutWorkers(bits, rng, options, callback); |
|
} |
|
function primeincFindPrimeWithoutWorkers(bits, rng, options, callback) { |
|
// initialize random number |
|
var num = generateRandom(bits, rng); |
|
/* Note: All primes are of the form 30k+i for i < 30 and gcd(30, i)=1. The |
|
number we are given is always aligned at 30k + 1. Each time the number is |
|
determined not to be prime we add to get to the next 'i', eg: if the number |
|
was at 30k + 1 we add 6. */ var deltaIdx = 0; |
|
// get required number of MR tests |
|
var mrTests = getMillerRabinTests(num.bitLength()); |
|
if ('millerRabinTests' in options) mrTests = options.millerRabinTests; |
|
// find prime nearest to 'num' for maxBlockTime ms |
|
// 10 ms gives 5ms of leeway for other calculations before dropping |
|
// below 60fps (1000/60 == 16.67), but in reality, the number will |
|
// likely be higher due to an 'atomic' big int modPow |
|
var maxBlockTime = 10; |
|
if ('maxBlockTime' in options) maxBlockTime = options.maxBlockTime; |
|
_primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback); |
|
} |
|
function _primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback) { |
|
var start = +new Date(); |
|
do { |
|
// overflow, regenerate random number |
|
if (num.bitLength() > bits) num = generateRandom(bits, rng); |
|
// do primality test |
|
if (num.isProbablePrime(mrTests)) return callback(null, num); |
|
// get next potential prime |
|
num.dAddOffset(GCD_30_DELTA[(deltaIdx++) % 8], 0); |
|
}while (maxBlockTime < 0 || +new Date() - start < maxBlockTime) |
|
// keep trying later |
|
$iGlOy.util.setImmediate(function() { |
|
_primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback); |
|
}); |
|
} |
|
// NOTE: This algorithm is indeterminate in nature because workers |
|
// run in parallel looking at different segments of numbers. Even if this |
|
// algorithm is run twice with the same input from a predictable RNG, it |
|
// may produce different outputs. |
|
function primeincFindPrimeWithWorkers(bits, rng, options, callback) { |
|
// web workers unavailable |
|
if (typeof Worker === 'undefined') return primeincFindPrimeWithoutWorkers(bits, rng, options, callback); |
|
// initialize random number |
|
var num = generateRandom(bits, rng); |
|
// use web workers to generate keys |
|
var numWorkers = options.workers; |
|
var workLoad = options.workLoad || 100; |
|
var range = workLoad * 30 / 8; |
|
var workerScript = options.workerScript || 'forge/prime.worker.js'; |
|
if (numWorkers === -1) return $iGlOy.util.estimateCores(function(err, cores) { |
|
if (err) // default to 2 |
|
cores = 2; |
|
numWorkers = cores - 1; |
|
generate(); |
|
}); |
|
generate(); |
|
function generate() { |
|
// require at least 1 worker |
|
numWorkers = Math.max(1, numWorkers); |
|
// TODO: consider optimizing by starting workers outside getPrime() ... |
|
// note that in order to clean up they will have to be made internally |
|
// asynchronous which may actually be slower |
|
// start workers immediately |
|
var workers = []; |
|
for(var i1 = 0; i1 < numWorkers; ++i1)// FIXME: fix path or use blob URLs |
|
workers[i1] = new Worker(workerScript); |
|
var running = numWorkers; |
|
// listen for requests from workers and assign ranges to find prime |
|
for(var i1 = 0; i1 < numWorkers; ++i1)workers[i1].addEventListener('message', workerMessage); |
|
/* Note: The distribution of random numbers is unknown. Therefore, each |
|
web worker is continuously allocated a range of numbers to check for a |
|
random number until one is found. |
|
|
|
Every 30 numbers will be checked just 8 times, because prime numbers |
|
have the form: |
|
|
|
30k+i, for i < 30 and gcd(30, i)=1 (there are 8 values of i for this) |
|
|
|
Therefore, if we want a web worker to run N checks before asking for |
|
a new range of numbers, each range must contain N*30/8 numbers. |
|
|
|
For 100 checks (workLoad), this is a range of 375. */ var found = false; |
|
function workerMessage(e) { |
|
// ignore message, prime already found |
|
if (found) return; |
|
--running; |
|
var data = e.data; |
|
if (data.found) { |
|
// terminate all workers |
|
for(var i = 0; i < workers.length; ++i)workers[i].terminate(); |
|
found = true; |
|
return callback(null, new BigInteger(data.prime, 16)); |
|
} |
|
// overflow, regenerate random number |
|
if (num.bitLength() > bits) num = generateRandom(bits, rng); |
|
// assign new range to check |
|
var hex = num.toString(16); |
|
// start prime search |
|
e.target.postMessage({ |
|
hex: hex, |
|
workLoad: workLoad |
|
}); |
|
num.dAddOffset(range, 0); |
|
} |
|
} |
|
} |
|
/** |
|
* Generates a random number using the given number of bits and RNG. |
|
* |
|
* @param bits the number of bits for the number. |
|
* @param rng the random number generator to use. |
|
* |
|
* @return the random number. |
|
*/ function generateRandom(bits, rng) { |
|
var num = new BigInteger(bits, rng); |
|
// force MSB set |
|
var bits1 = bits - 1; |
|
if (!num.testBit(bits1)) num.bitwiseTo(BigInteger.ONE.shiftLeft(bits1), op_or, num); |
|
// align number on 30k+1 boundary |
|
num.dAddOffset(31 - num.mod(THIRTY).byteValue(), 0); |
|
return num; |
|
} |
|
/** |
|
* Returns the required number of Miller-Rabin tests to generate a |
|
* prime with an error probability of (1/2)^80. |
|
* |
|
* See Handbook of Applied Cryptography Chapter 4, Table 4.4. |
|
* |
|
* @param bits the bit size. |
|
* |
|
* @return the required number of iterations. |
|
*/ function getMillerRabinTests(bits) { |
|
if (bits <= 100) return 27; |
|
if (bits <= 150) return 18; |
|
if (bits <= 200) return 15; |
|
if (bits <= 250) return 12; |
|
if (bits <= 300) return 9; |
|
if (bits <= 350) return 8; |
|
if (bits <= 400) return 7; |
|
if (bits <= 500) return 6; |
|
if (bits <= 600) return 5; |
|
if (bits <= 800) return 4; |
|
if (bits <= 1250) return 3; |
|
return 2; |
|
} |
|
})(); |
|
|
|
|
|
|
|
|
|
if (typeof $8ab3548bea1beb81$var$BigInteger === 'undefined') var $8ab3548bea1beb81$var$BigInteger = $iGlOy.jsbn.BigInteger; |
|
|
|
var $8ab3548bea1beb81$var$_crypto = $iGlOy.util.isNodejs ? $8C1kk$crypto : null; |
|
// shortcut for asn.1 API |
|
var $8ab3548bea1beb81$var$asn1 = $iGlOy.asn1; |
|
// shortcut for util API |
|
var $8ab3548bea1beb81$var$util = $iGlOy.util; |
|
/* |
|
* RSA encryption and decryption, see RFC 2313. |
|
*/ $iGlOy.pki = $iGlOy.pki || { |
|
}; |
|
$8ab3548bea1beb81$exports = $iGlOy.pki.rsa = $iGlOy.rsa = $iGlOy.rsa || { |
|
}; |
|
var $8ab3548bea1beb81$var$pki = $iGlOy.pki; |
|
// for finding primes, which are 30k+i for i = 1, 7, 11, 13, 17, 19, 23, 29 |
|
var $8ab3548bea1beb81$var$GCD_30_DELTA = [ |
|
6, |
|
4, |
|
2, |
|
4, |
|
2, |
|
4, |
|
6, |
|
2 |
|
]; |
|
// validator for a PrivateKeyInfo structure |
|
var $8ab3548bea1beb81$var$privateKeyValidator = { |
|
// PrivateKeyInfo |
|
name: 'PrivateKeyInfo', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
// Version (INTEGER) |
|
name: 'PrivateKeyInfo.version', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyVersion' |
|
}, |
|
{ |
|
// privateKeyAlgorithm |
|
name: 'PrivateKeyInfo.privateKeyAlgorithm', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'AlgorithmIdentifier.algorithm', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'privateKeyOid' |
|
} |
|
] |
|
}, |
|
{ |
|
// PrivateKey |
|
name: 'PrivateKeyInfo', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'privateKey' |
|
} |
|
] |
|
}; |
|
// validator for an RSA private key |
|
var $8ab3548bea1beb81$var$rsaPrivateKeyValidator = { |
|
// RSAPrivateKey |
|
name: 'RSAPrivateKey', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
// Version (INTEGER) |
|
name: 'RSAPrivateKey.version', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyVersion' |
|
}, |
|
{ |
|
// modulus (n) |
|
name: 'RSAPrivateKey.modulus', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyModulus' |
|
}, |
|
{ |
|
// publicExponent (e) |
|
name: 'RSAPrivateKey.publicExponent', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyPublicExponent' |
|
}, |
|
{ |
|
// privateExponent (d) |
|
name: 'RSAPrivateKey.privateExponent', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyPrivateExponent' |
|
}, |
|
{ |
|
// prime1 (p) |
|
name: 'RSAPrivateKey.prime1', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyPrime1' |
|
}, |
|
{ |
|
// prime2 (q) |
|
name: 'RSAPrivateKey.prime2', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyPrime2' |
|
}, |
|
{ |
|
// exponent1 (d mod (p-1)) |
|
name: 'RSAPrivateKey.exponent1', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyExponent1' |
|
}, |
|
{ |
|
// exponent2 (d mod (q-1)) |
|
name: 'RSAPrivateKey.exponent2', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyExponent2' |
|
}, |
|
{ |
|
// coefficient ((inverse of q) mod p) |
|
name: 'RSAPrivateKey.coefficient', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyCoefficient' |
|
} |
|
] |
|
}; |
|
// validator for an RSA public key |
|
var $8ab3548bea1beb81$var$rsaPublicKeyValidator = { |
|
// RSAPublicKey |
|
name: 'RSAPublicKey', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
// modulus (n) |
|
name: 'RSAPublicKey.modulus', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'publicKeyModulus' |
|
}, |
|
{ |
|
// publicExponent (e) |
|
name: 'RSAPublicKey.exponent', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'publicKeyExponent' |
|
} |
|
] |
|
}; |
|
// validator for an SubjectPublicKeyInfo structure |
|
// Note: Currently only works with an RSA public key |
|
var $8ab3548bea1beb81$var$publicKeyValidator = $iGlOy.pki.rsa.publicKeyValidator = { |
|
name: 'SubjectPublicKeyInfo', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'subjectPublicKeyInfo', |
|
value: [ |
|
{ |
|
name: 'SubjectPublicKeyInfo.AlgorithmIdentifier', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'AlgorithmIdentifier.algorithm', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'publicKeyOid' |
|
} |
|
] |
|
}, |
|
{ |
|
// subjectPublicKey |
|
name: 'SubjectPublicKeyInfo.subjectPublicKey', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.BITSTRING, |
|
constructed: false, |
|
value: [ |
|
{ |
|
// RSAPublicKey |
|
name: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey', |
|
tagClass: $8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, |
|
type: $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
optional: true, |
|
captureAsn1: 'rsaPublicKey' |
|
} |
|
] |
|
} |
|
] |
|
}; |
|
/** |
|
* Wrap digest in DigestInfo object. |
|
* |
|
* This function implements EMSA-PKCS1-v1_5-ENCODE as per RFC 3447. |
|
* |
|
* DigestInfo ::= SEQUENCE { |
|
* digestAlgorithm DigestAlgorithmIdentifier, |
|
* digest Digest |
|
* } |
|
* |
|
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier |
|
* Digest ::= OCTET STRING |
|
* |
|
* @param md the message digest object with the hash to sign. |
|
* |
|
* @return the encoded message (ready for RSA encrytion) |
|
*/ var $8ab3548bea1beb81$var$emsaPkcs1v15encode = function(md) { |
|
// get the oid for the algorithm |
|
var oid; |
|
if (md.algorithm in $8ab3548bea1beb81$var$pki.oids) oid = $8ab3548bea1beb81$var$pki.oids[md.algorithm]; |
|
else { |
|
var error = new Error('Unknown message digest algorithm.'); |
|
error.algorithm = md.algorithm; |
|
throw error; |
|
} |
|
var oidBytes = $8ab3548bea1beb81$var$asn1.oidToDer(oid).getBytes(); |
|
// create the digest info |
|
var digestInfo = $8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, true, []); |
|
var digestAlgorithm = $8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, true, []); |
|
digestAlgorithm.value.push($8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.OID, false, oidBytes)); |
|
digestAlgorithm.value.push($8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.NULL, false, '')); |
|
var digest = $8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.OCTETSTRING, false, md.digest().getBytes()); |
|
digestInfo.value.push(digestAlgorithm); |
|
digestInfo.value.push(digest); |
|
// encode digest info |
|
return $8ab3548bea1beb81$var$asn1.toDer(digestInfo).getBytes(); |
|
}; |
|
/** |
|
* Performs x^c mod n (RSA encryption or decryption operation). |
|
* |
|
* @param x the number to raise and mod. |
|
* @param key the key to use. |
|
* @param pub true if the key is public, false if private. |
|
* |
|
* @return the result of x^c mod n. |
|
*/ var $8ab3548bea1beb81$var$_modPow = function(x, key, pub) { |
|
if (pub) return x.modPow(key.e, key.n); |
|
if (!key.p || !key.q) // allow calculation without CRT params (slow) |
|
return x.modPow(key.d, key.n); |
|
// pre-compute dP, dQ, and qInv if necessary |
|
if (!key.dP) key.dP = key.d.mod(key.p.subtract($8ab3548bea1beb81$var$BigInteger.ONE)); |
|
if (!key.dQ) key.dQ = key.d.mod(key.q.subtract($8ab3548bea1beb81$var$BigInteger.ONE)); |
|
if (!key.qInv) key.qInv = key.q.modInverse(key.p); |
|
/* Chinese remainder theorem (CRT) states: |
|
|
|
Suppose n1, n2, ..., nk are positive integers which are pairwise |
|
coprime (n1 and n2 have no common factors other than 1). For any |
|
integers x1, x2, ..., xk there exists an integer x solving the |
|
system of simultaneous congruences (where ~= means modularly |
|
congruent so a ~= b mod n means a mod n = b mod n): |
|
|
|
x ~= x1 mod n1 |
|
x ~= x2 mod n2 |
|
... |
|
x ~= xk mod nk |
|
|
|
This system of congruences has a single simultaneous solution x |
|
between 0 and n - 1. Furthermore, each xk solution and x itself |
|
is congruent modulo the product n = n1*n2*...*nk. |
|
So x1 mod n = x2 mod n = xk mod n = x mod n. |
|
|
|
The single simultaneous solution x can be solved with the following |
|
equation: |
|
|
|
x = sum(xi*ri*si) mod n where ri = n/ni and si = ri^-1 mod ni. |
|
|
|
Where x is less than n, xi = x mod ni. |
|
|
|
For RSA we are only concerned with k = 2. The modulus n = pq, where |
|
p and q are coprime. The RSA decryption algorithm is: |
|
|
|
y = x^d mod n |
|
|
|
Given the above: |
|
|
|
x1 = x^d mod p |
|
r1 = n/p = q |
|
s1 = q^-1 mod p |
|
x2 = x^d mod q |
|
r2 = n/q = p |
|
s2 = p^-1 mod q |
|
|
|
So y = (x1r1s1 + x2r2s2) mod n |
|
= ((x^d mod p)q(q^-1 mod p) + (x^d mod q)p(p^-1 mod q)) mod n |
|
|
|
According to Fermat's Little Theorem, if the modulus P is prime, |
|
for any integer A not evenly divisible by P, A^(P-1) ~= 1 mod P. |
|
Since A is not divisible by P it follows that if: |
|
N ~= M mod (P - 1), then A^N mod P = A^M mod P. Therefore: |
|
|
|
A^N mod P = A^(M mod (P - 1)) mod P. (The latter takes less effort |
|
to calculate). In order to calculate x^d mod p more quickly the |
|
exponent d mod (p - 1) is stored in the RSA private key (the same |
|
is done for x^d mod q). These values are referred to as dP and dQ |
|
respectively. Therefore we now have: |
|
|
|
y = ((x^dP mod p)q(q^-1 mod p) + (x^dQ mod q)p(p^-1 mod q)) mod n |
|
|
|
Since we'll be reducing x^dP by modulo p (same for q) we can also |
|
reduce x by p (and q respectively) before hand. Therefore, let |
|
|
|
xp = ((x mod p)^dP mod p), and |
|
xq = ((x mod q)^dQ mod q), yielding: |
|
|
|
y = (xp*q*(q^-1 mod p) + xq*p*(p^-1 mod q)) mod n |
|
|
|
This can be further reduced to a simple algorithm that only |
|
requires 1 inverse (the q inverse is used) to be used and stored. |
|
The algorithm is called Garner's algorithm. If qInv is the |
|
inverse of q, we simply calculate: |
|
|
|
y = (qInv*(xp - xq) mod p) * q + xq |
|
|
|
However, there are two further complications. First, we need to |
|
ensure that xp > xq to prevent signed BigIntegers from being used |
|
so we add p until this is true (since we will be mod'ing with |
|
p anyway). Then, there is a known timing attack on algorithms |
|
using the CRT. To mitigate this risk, "cryptographic blinding" |
|
should be used. This requires simply generating a random number r |
|
between 0 and n-1 and its inverse and multiplying x by r^e before |
|
calculating y and then multiplying y by r^-1 afterwards. Note that |
|
r must be coprime with n (gcd(r, n) === 1) in order to have an |
|
inverse. |
|
*/ // cryptographic blinding |
|
var r; |
|
do r = new $8ab3548bea1beb81$var$BigInteger($iGlOy.util.bytesToHex($iGlOy.random.getBytes(key.n.bitLength() / 8)), 16); |
|
while (r.compareTo(key.n) >= 0 || !r.gcd(key.n).equals($8ab3548bea1beb81$var$BigInteger.ONE)) |
|
x = x.multiply(r.modPow(key.e, key.n)).mod(key.n); |
|
// calculate xp and xq |
|
var xp = x.mod(key.p).modPow(key.dP, key.p); |
|
var xq = x.mod(key.q).modPow(key.dQ, key.q); |
|
// xp must be larger than xq to avoid signed bit usage |
|
while(xp.compareTo(xq) < 0)xp = xp.add(key.p); |
|
// do last step |
|
var y = xp.subtract(xq).multiply(key.qInv).mod(key.p).multiply(key.q).add(xq); |
|
// remove effect of random for cryptographic blinding |
|
y = y.multiply(r.modInverse(key.n)).mod(key.n); |
|
return y; |
|
}; |
|
/** |
|
* NOTE: THIS METHOD IS DEPRECATED, use 'sign' on a private key object or |
|
* 'encrypt' on a public key object instead. |
|
* |
|
* Performs RSA encryption. |
|
* |
|
* The parameter bt controls whether to put padding bytes before the |
|
* message passed in. Set bt to either true or false to disable padding |
|
* completely (in order to handle e.g. EMSA-PSS encoding seperately before), |
|
* signaling whether the encryption operation is a public key operation |
|
* (i.e. encrypting data) or not, i.e. private key operation (data signing). |
|
* |
|
* For PKCS#1 v1.5 padding pass in the block type to use, i.e. either 0x01 |
|
* (for signing) or 0x02 (for encryption). The key operation mode (private |
|
* or public) is derived from this flag in that case). |
|
* |
|
* @param m the message to encrypt as a byte string. |
|
* @param key the RSA key to use. |
|
* @param bt for PKCS#1 v1.5 padding, the block type to use |
|
* (0x01 for private key, 0x02 for public), |
|
* to disable padding: true = public key, false = private key. |
|
* |
|
* @return the encrypted bytes as a string. |
|
*/ $8ab3548bea1beb81$var$pki.rsa.encrypt = function(m, key, bt) { |
|
var pub = bt; |
|
var eb; |
|
// get the length of the modulus in bytes |
|
var k = Math.ceil(key.n.bitLength() / 8); |
|
if (bt !== false && bt !== true) { |
|
// legacy, default to PKCS#1 v1.5 padding |
|
pub = bt === 2; |
|
eb = $8ab3548bea1beb81$var$_encodePkcs1_v1_5(m, key, bt); |
|
} else { |
|
eb = $iGlOy.util.createBuffer(); |
|
eb.putBytes(m); |
|
} |
|
// load encryption block as big integer 'x' |
|
// FIXME: hex conversion inefficient, get BigInteger w/byte strings |
|
var x = new $8ab3548bea1beb81$var$BigInteger(eb.toHex(), 16); |
|
// do RSA encryption |
|
var y = $8ab3548bea1beb81$var$_modPow(x, key, pub); |
|
// convert y into the encrypted data byte string, if y is shorter in |
|
// bytes than k, then prepend zero bytes to fill up ed |
|
// FIXME: hex conversion inefficient, get BigInteger w/byte strings |
|
var yhex = y.toString(16); |
|
var ed = $iGlOy.util.createBuffer(); |
|
var zeros = k - Math.ceil(yhex.length / 2); |
|
while(zeros > 0){ |
|
ed.putByte(0); |
|
--zeros; |
|
} |
|
ed.putBytes($iGlOy.util.hexToBytes(yhex)); |
|
return ed.getBytes(); |
|
}; |
|
/** |
|
* NOTE: THIS METHOD IS DEPRECATED, use 'decrypt' on a private key object or |
|
* 'verify' on a public key object instead. |
|
* |
|
* Performs RSA decryption. |
|
* |
|
* The parameter ml controls whether to apply PKCS#1 v1.5 padding |
|
* or not. Set ml = false to disable padding removal completely |
|
* (in order to handle e.g. EMSA-PSS later on) and simply pass back |
|
* the RSA encryption block. |
|
* |
|
* @param ed the encrypted data to decrypt in as a byte string. |
|
* @param key the RSA key to use. |
|
* @param pub true for a public key operation, false for private. |
|
* @param ml the message length, if known, false to disable padding. |
|
* |
|
* @return the decrypted message as a byte string. |
|
*/ $8ab3548bea1beb81$var$pki.rsa.decrypt = function(ed, key, pub, ml) { |
|
// get the length of the modulus in bytes |
|
var k = Math.ceil(key.n.bitLength() / 8); |
|
// error if the length of the encrypted data ED is not k |
|
if (ed.length !== k) { |
|
var error = new Error('Encrypted message length is invalid.'); |
|
error.length = ed.length; |
|
error.expected = k; |
|
throw error; |
|
} |
|
// convert encrypted data into a big integer |
|
// FIXME: hex conversion inefficient, get BigInteger w/byte strings |
|
var y = new $8ab3548bea1beb81$var$BigInteger($iGlOy.util.createBuffer(ed).toHex(), 16); |
|
// y must be less than the modulus or it wasn't the result of |
|
// a previous mod operation (encryption) using that modulus |
|
if (y.compareTo(key.n) >= 0) throw new Error('Encrypted message is invalid.'); |
|
// do RSA decryption |
|
var x = $8ab3548bea1beb81$var$_modPow(y, key, pub); |
|
// create the encryption block, if x is shorter in bytes than k, then |
|
// prepend zero bytes to fill up eb |
|
// FIXME: hex conversion inefficient, get BigInteger w/byte strings |
|
var xhex = x.toString(16); |
|
var eb = $iGlOy.util.createBuffer(); |
|
var zeros = k - Math.ceil(xhex.length / 2); |
|
while(zeros > 0){ |
|
eb.putByte(0); |
|
--zeros; |
|
} |
|
eb.putBytes($iGlOy.util.hexToBytes(xhex)); |
|
if (ml !== false) // legacy, default to PKCS#1 v1.5 padding |
|
return $8ab3548bea1beb81$var$_decodePkcs1_v1_5(eb.getBytes(), key, pub); |
|
// return message |
|
return eb.getBytes(); |
|
}; |
|
/** |
|
* Creates an RSA key-pair generation state object. It is used to allow |
|
* key-generation to be performed in steps. It also allows for a UI to |
|
* display progress updates. |
|
* |
|
* @param bits the size for the private key in bits, defaults to 2048. |
|
* @param e the public exponent to use, defaults to 65537 (0x10001). |
|
* @param [options] the options to use. |
|
* prng a custom crypto-secure pseudo-random number generator to use, |
|
* that must define "getBytesSync". |
|
* algorithm the algorithm to use (default: 'PRIMEINC'). |
|
* |
|
* @return the state object to use to generate the key-pair. |
|
*/ $8ab3548bea1beb81$var$pki.rsa.createKeyPairGenerationState = function(bits, e, options) { |
|
// TODO: migrate step-based prime generation code to forge.prime |
|
// set default bits |
|
if (typeof bits === 'string') bits = parseInt(bits, 10); |
|
bits = bits || 2048; |
|
// create prng with api that matches BigInteger secure random |
|
options = options || { |
|
}; |
|
var prng = options.prng || $iGlOy.random; |
|
var rng = { |
|
// x is an array to fill with bytes |
|
nextBytes: function(x) { |
|
var b = prng.getBytesSync(x.length); |
|
for(var i = 0; i < x.length; ++i)x[i] = b.charCodeAt(i); |
|
} |
|
}; |
|
var algorithm = options.algorithm || 'PRIMEINC'; |
|
// create PRIMEINC algorithm state |
|
var rval; |
|
if (algorithm === 'PRIMEINC') { |
|
rval = { |
|
algorithm: algorithm, |
|
state: 0, |
|
bits: bits, |
|
rng: rng, |
|
eInt: e || 65537, |
|
e: new $8ab3548bea1beb81$var$BigInteger(null), |
|
p: null, |
|
q: null, |
|
qBits: bits >> 1, |
|
pBits: bits - (bits >> 1), |
|
pqState: 0, |
|
num: null, |
|
keys: null |
|
}; |
|
rval.e.fromInt(rval.eInt); |
|
} else throw new Error('Invalid key generation algorithm: ' + algorithm); |
|
return rval; |
|
}; |
|
/** |
|
* Attempts to runs the key-generation algorithm for at most n seconds |
|
* (approximately) using the given state. When key-generation has completed, |
|
* the keys will be stored in state.keys. |
|
* |
|
* To use this function to update a UI while generating a key or to prevent |
|
* causing browser lockups/warnings, set "n" to a value other than 0. A |
|
* simple pattern for generating a key and showing a progress indicator is: |
|
* |
|
* var state = pki.rsa.createKeyPairGenerationState(2048); |
|
* var step = function() { |
|
* // step key-generation, run algorithm for 100 ms, repeat |
|
* if(!forge.pki.rsa.stepKeyPairGenerationState(state, 100)) { |
|
* setTimeout(step, 1); |
|
* } else { |
|
* // key-generation complete |
|
* // TODO: turn off progress indicator here |
|
* // TODO: use the generated key-pair in "state.keys" |
|
* } |
|
* }; |
|
* // TODO: turn on progress indicator here |
|
* setTimeout(step, 0); |
|
* |
|
* @param state the state to use. |
|
* @param n the maximum number of milliseconds to run the algorithm for, 0 |
|
* to run the algorithm to completion. |
|
* |
|
* @return true if the key-generation completed, false if not. |
|
*/ $8ab3548bea1beb81$var$pki.rsa.stepKeyPairGenerationState = function(state, n) { |
|
// set default algorithm if not set |
|
if (!('algorithm' in state)) state.algorithm = 'PRIMEINC'; |
|
// TODO: migrate step-based prime generation code to forge.prime |
|
// TODO: abstract as PRIMEINC algorithm |
|
// do key generation (based on Tom Wu's rsa.js, see jsbn.js license) |
|
// with some minor optimizations and designed to run in steps |
|
// local state vars |
|
var THIRTY = new $8ab3548bea1beb81$var$BigInteger(null); |
|
THIRTY.fromInt(30); |
|
var deltaIdx = 0; |
|
var op_or = function(x, y) { |
|
return x | y; |
|
}; |
|
// keep stepping until time limit is reached or done |
|
var t1 = +new Date(); |
|
var t2; |
|
var total = 0; |
|
while(state.keys === null && (n <= 0 || total < n)){ |
|
// generate p or q |
|
if (state.state === 0) { |
|
/* Note: All primes are of the form: |
|
|
|
30k+i, for i < 30 and gcd(30, i)=1, where there are 8 values for i |
|
|
|
When we generate a random number, we always align it at 30k + 1. Each |
|
time the number is determined not to be prime we add to get to the |
|
next 'i', eg: if the number was at 30k + 1 we add 6. */ var bits = state.p === null ? state.pBits : state.qBits; |
|
var bits1 = bits - 1; |
|
// get a random number |
|
if (state.pqState === 0) { |
|
state.num = new $8ab3548bea1beb81$var$BigInteger(bits, state.rng); |
|
// force MSB set |
|
if (!state.num.testBit(bits1)) state.num.bitwiseTo($8ab3548bea1beb81$var$BigInteger.ONE.shiftLeft(bits1), op_or, state.num); |
|
// align number on 30k+1 boundary |
|
state.num.dAddOffset(31 - state.num.mod(THIRTY).byteValue(), 0); |
|
deltaIdx = 0; |
|
++state.pqState; |
|
} else if (state.pqState === 1) { |
|
// try to make the number a prime |
|
if (state.num.bitLength() > bits) // overflow, try again |
|
state.pqState = 0; |
|
else if (state.num.isProbablePrime($8ab3548bea1beb81$var$_getMillerRabinTests(state.num.bitLength()))) ++state.pqState; |
|
else // get next potential prime |
|
state.num.dAddOffset($8ab3548bea1beb81$var$GCD_30_DELTA[(deltaIdx++) % 8], 0); |
|
} else if (state.pqState === 2) // ensure number is coprime with e |
|
state.pqState = state.num.subtract($8ab3548bea1beb81$var$BigInteger.ONE).gcd(state.e).compareTo($8ab3548bea1beb81$var$BigInteger.ONE) === 0 ? 3 : 0; |
|
else if (state.pqState === 3) { |
|
// store p or q |
|
state.pqState = 0; |
|
if (state.p === null) state.p = state.num; |
|
else state.q = state.num; |
|
// advance state if both p and q are ready |
|
if (state.p !== null && state.q !== null) ++state.state; |
|
state.num = null; |
|
} |
|
} else if (state.state === 1) { |
|
// ensure p is larger than q (swap them if not) |
|
if (state.p.compareTo(state.q) < 0) { |
|
state.num = state.p; |
|
state.p = state.q; |
|
state.q = state.num; |
|
} |
|
++state.state; |
|
} else if (state.state === 2) { |
|
// compute phi: (p - 1)(q - 1) (Euler's totient function) |
|
state.p1 = state.p.subtract($8ab3548bea1beb81$var$BigInteger.ONE); |
|
state.q1 = state.q.subtract($8ab3548bea1beb81$var$BigInteger.ONE); |
|
state.phi = state.p1.multiply(state.q1); |
|
++state.state; |
|
} else if (state.state === 3) { |
|
// ensure e and phi are coprime |
|
if (state.phi.gcd(state.e).compareTo($8ab3548bea1beb81$var$BigInteger.ONE) === 0) // phi and e are coprime, advance |
|
++state.state; |
|
else { |
|
// phi and e aren't coprime, so generate a new p and q |
|
state.p = null; |
|
state.q = null; |
|
state.state = 0; |
|
} |
|
} else if (state.state === 4) { |
|
// create n, ensure n is has the right number of bits |
|
state.n = state.p.multiply(state.q); |
|
// ensure n is right number of bits |
|
if (state.n.bitLength() === state.bits) // success, advance |
|
++state.state; |
|
else { |
|
// failed, get new q |
|
state.q = null; |
|
state.state = 0; |
|
} |
|
} else if (state.state === 5) { |
|
// set keys |
|
var d = state.e.modInverse(state.phi); |
|
state.keys = { |
|
privateKey: $8ab3548bea1beb81$var$pki.rsa.setPrivateKey(state.n, state.e, d, state.p, state.q, d.mod(state.p1), d.mod(state.q1), state.q.modInverse(state.p)), |
|
publicKey: $8ab3548bea1beb81$var$pki.rsa.setPublicKey(state.n, state.e) |
|
}; |
|
} |
|
// update timing |
|
t2 = +new Date(); |
|
total += t2 - t1; |
|
t1 = t2; |
|
} |
|
return state.keys !== null; |
|
}; |
|
/** |
|
* Generates an RSA public-private key pair in a single call. |
|
* |
|
* To generate a key-pair in steps (to allow for progress updates and to |
|
* prevent blocking or warnings in slow browsers) then use the key-pair |
|
* generation state functions. |
|
* |
|
* To generate a key-pair asynchronously (either through web-workers, if |
|
* available, or by breaking up the work on the main thread), pass a |
|
* callback function. |
|
* |
|
* @param [bits] the size for the private key in bits, defaults to 2048. |
|
* @param [e] the public exponent to use, defaults to 65537. |
|
* @param [options] options for key-pair generation, if given then 'bits' |
|
* and 'e' must *not* be given: |
|
* bits the size for the private key in bits, (default: 2048). |
|
* e the public exponent to use, (default: 65537 (0x10001)). |
|
* workerScript the worker script URL. |
|
* workers the number of web workers (if supported) to use, |
|
* (default: 2). |
|
* workLoad the size of the work load, ie: number of possible prime |
|
* numbers for each web worker to check per work assignment, |
|
* (default: 100). |
|
* prng a custom crypto-secure pseudo-random number generator to use, |
|
* that must define "getBytesSync". Disables use of native APIs. |
|
* algorithm the algorithm to use (default: 'PRIMEINC'). |
|
* @param [callback(err, keypair)] called once the operation completes. |
|
* |
|
* @return an object with privateKey and publicKey properties. |
|
*/ $8ab3548bea1beb81$var$pki.rsa.generateKeyPair = function(bits, e1, options, callback) { |
|
// (bits), (options), (callback) |
|
if (arguments.length === 1) { |
|
if (typeof bits === 'object') { |
|
options = bits; |
|
bits = undefined; |
|
} else if (typeof bits === 'function') { |
|
callback = bits; |
|
bits = undefined; |
|
} |
|
} else if (arguments.length === 2) { |
|
// (bits, e), (bits, options), (bits, callback), (options, callback) |
|
if (typeof bits === 'number') { |
|
if (typeof e1 === 'function') { |
|
callback = e1; |
|
e1 = undefined; |
|
} else if (typeof e1 !== 'number') { |
|
options = e1; |
|
e1 = undefined; |
|
} |
|
} else { |
|
options = bits; |
|
callback = e1; |
|
bits = undefined; |
|
e1 = undefined; |
|
} |
|
} else if (arguments.length === 3) { |
|
// (bits, e, options), (bits, e, callback), (bits, options, callback) |
|
if (typeof e1 === 'number') { |
|
if (typeof options === 'function') { |
|
callback = options; |
|
options = undefined; |
|
} |
|
} else { |
|
callback = options; |
|
options = e1; |
|
e1 = undefined; |
|
} |
|
} |
|
options = options || { |
|
}; |
|
if (bits === undefined) bits = options.bits || 2048; |
|
if (e1 === undefined) e1 = options.e || 65537; |
|
// use native code if permitted, available, and parameters are acceptable |
|
if (!$iGlOy.options.usePureJavaScript && !options.prng && bits >= 256 && bits <= 16384 && (e1 === 65537 || e1 === 3)) { |
|
if (callback) { |
|
// try native async |
|
if ($8ab3548bea1beb81$var$_detectNodeCrypto('generateKeyPair')) return $8ab3548bea1beb81$var$_crypto.generateKeyPair('rsa', { |
|
modulusLength: bits, |
|
publicExponent: e1, |
|
publicKeyEncoding: { |
|
type: 'spki', |
|
format: 'pem' |
|
}, |
|
privateKeyEncoding: { |
|
type: 'pkcs8', |
|
format: 'pem' |
|
} |
|
}, function(err, pub, priv) { |
|
if (err) return callback(err); |
|
callback(null, { |
|
privateKey: $8ab3548bea1beb81$var$pki.privateKeyFromPem(priv), |
|
publicKey: $8ab3548bea1beb81$var$pki.publicKeyFromPem(pub) |
|
}); |
|
}); |
|
if ($8ab3548bea1beb81$var$_detectSubtleCrypto('generateKey') && $8ab3548bea1beb81$var$_detectSubtleCrypto('exportKey')) // use standard native generateKey |
|
return $8ab3548bea1beb81$var$util.globalScope.crypto.subtle.generateKey({ |
|
name: 'RSASSA-PKCS1-v1_5', |
|
modulusLength: bits, |
|
publicExponent: $8ab3548bea1beb81$var$_intToUint8Array(e1), |
|
hash: { |
|
name: 'SHA-256' |
|
} |
|
}, true, [ |
|
'sign', |
|
'verify' |
|
]).then(function(pair) { |
|
return $8ab3548bea1beb81$var$util.globalScope.crypto.subtle.exportKey('pkcs8', pair.privateKey); |
|
// avoiding catch(function(err) {...}) to support IE <= 8 |
|
}).then(undefined, function(err) { |
|
callback(err); |
|
}).then(function(pkcs8) { |
|
if (pkcs8) { |
|
var privateKey = $8ab3548bea1beb81$var$pki.privateKeyFromAsn1($8ab3548bea1beb81$var$asn1.fromDer($iGlOy.util.createBuffer(pkcs8))); |
|
callback(null, { |
|
privateKey: privateKey, |
|
publicKey: $8ab3548bea1beb81$var$pki.setRsaPublicKey(privateKey.n, privateKey.e) |
|
}); |
|
} |
|
}); |
|
if ($8ab3548bea1beb81$var$_detectSubtleMsCrypto('generateKey') && $8ab3548bea1beb81$var$_detectSubtleMsCrypto('exportKey')) { |
|
var genOp = $8ab3548bea1beb81$var$util.globalScope.msCrypto.subtle.generateKey({ |
|
name: 'RSASSA-PKCS1-v1_5', |
|
modulusLength: bits, |
|
publicExponent: $8ab3548bea1beb81$var$_intToUint8Array(e1), |
|
hash: { |
|
name: 'SHA-256' |
|
} |
|
}, true, [ |
|
'sign', |
|
'verify' |
|
]); |
|
genOp.oncomplete = function(e2) { |
|
var pair = e2.target.result; |
|
var exportOp = $8ab3548bea1beb81$var$util.globalScope.msCrypto.subtle.exportKey('pkcs8', pair.privateKey); |
|
exportOp.oncomplete = function(e) { |
|
var pkcs8 = e.target.result; |
|
var privateKey = $8ab3548bea1beb81$var$pki.privateKeyFromAsn1($8ab3548bea1beb81$var$asn1.fromDer($iGlOy.util.createBuffer(pkcs8))); |
|
callback(null, { |
|
privateKey: privateKey, |
|
publicKey: $8ab3548bea1beb81$var$pki.setRsaPublicKey(privateKey.n, privateKey.e) |
|
}); |
|
}; |
|
exportOp.onerror = function(err) { |
|
callback(err); |
|
}; |
|
}; |
|
genOp.onerror = function(err) { |
|
callback(err); |
|
}; |
|
return; |
|
} |
|
} else // try native sync |
|
if ($8ab3548bea1beb81$var$_detectNodeCrypto('generateKeyPairSync')) { |
|
var keypair = $8ab3548bea1beb81$var$_crypto.generateKeyPairSync('rsa', { |
|
modulusLength: bits, |
|
publicExponent: e1, |
|
publicKeyEncoding: { |
|
type: 'spki', |
|
format: 'pem' |
|
}, |
|
privateKeyEncoding: { |
|
type: 'pkcs8', |
|
format: 'pem' |
|
} |
|
}); |
|
return { |
|
privateKey: $8ab3548bea1beb81$var$pki.privateKeyFromPem(keypair.privateKey), |
|
publicKey: $8ab3548bea1beb81$var$pki.publicKeyFromPem(keypair.publicKey) |
|
}; |
|
} |
|
} |
|
// use JavaScript implementation |
|
var state = $8ab3548bea1beb81$var$pki.rsa.createKeyPairGenerationState(bits, e1, options); |
|
if (!callback) { |
|
$8ab3548bea1beb81$var$pki.rsa.stepKeyPairGenerationState(state, 0); |
|
return state.keys; |
|
} |
|
$8ab3548bea1beb81$var$_generateKeyPair(state, options, callback); |
|
}; |
|
/** |
|
* Sets an RSA public key from BigIntegers modulus and exponent. |
|
* |
|
* @param n the modulus. |
|
* @param e the exponent. |
|
* |
|
* @return the public key. |
|
*/ $8ab3548bea1beb81$var$pki.setRsaPublicKey = $8ab3548bea1beb81$var$pki.rsa.setPublicKey = function(n, e3) { |
|
var key1 = { |
|
n: n, |
|
e: e3 |
|
}; |
|
/** |
|
* Encrypts the given data with this public key. Newer applications |
|
* should use the 'RSA-OAEP' decryption scheme, 'RSAES-PKCS1-V1_5' is for |
|
* legacy applications. |
|
* |
|
* @param data the byte string to encrypt. |
|
* @param scheme the encryption scheme to use: |
|
* 'RSAES-PKCS1-V1_5' (default), |
|
* 'RSA-OAEP', |
|
* 'RAW', 'NONE', or null to perform raw RSA encryption, |
|
* an object with an 'encode' property set to a function |
|
* with the signature 'function(data, key)' that returns |
|
* a binary-encoded string representing the encoded data. |
|
* @param schemeOptions any scheme-specific options. |
|
* |
|
* @return the encrypted byte string. |
|
*/ key1.encrypt = function(data, scheme, schemeOptions) { |
|
if (typeof scheme === 'string') scheme = scheme.toUpperCase(); |
|
else if (scheme === undefined) scheme = 'RSAES-PKCS1-V1_5'; |
|
if (scheme === 'RSAES-PKCS1-V1_5') scheme = { |
|
encode: function(m, key, pub) { |
|
return $8ab3548bea1beb81$var$_encodePkcs1_v1_5(m, key, 2).getBytes(); |
|
} |
|
}; |
|
else if (scheme === 'RSA-OAEP' || scheme === 'RSAES-OAEP') scheme = { |
|
encode: function(m, key) { |
|
return $iGlOy.pkcs1.encode_rsa_oaep(key, m, schemeOptions); |
|
} |
|
}; |
|
else if ([ |
|
'RAW', |
|
'NONE', |
|
'NULL', |
|
null |
|
].indexOf(scheme) !== -1) scheme = { |
|
encode: function(e) { |
|
return e; |
|
} |
|
}; |
|
else if (typeof scheme === 'string') throw new Error('Unsupported encryption scheme: "' + scheme + '".'); |
|
// do scheme-based encoding then rsa encryption |
|
var e4 = scheme.encode(data, key1, true); |
|
return $8ab3548bea1beb81$var$pki.rsa.encrypt(e4, key1, true); |
|
}; |
|
/** |
|
* Verifies the given signature against the given digest. |
|
* |
|
* PKCS#1 supports multiple (currently two) signature schemes: |
|
* RSASSA-PKCS1-V1_5 and RSASSA-PSS. |
|
* |
|
* By default this implementation uses the "old scheme", i.e. |
|
* RSASSA-PKCS1-V1_5, in which case once RSA-decrypted, the |
|
* signature is an OCTET STRING that holds a DigestInfo. |
|
* |
|
* DigestInfo ::= SEQUENCE { |
|
* digestAlgorithm DigestAlgorithmIdentifier, |
|
* digest Digest |
|
* } |
|
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier |
|
* Digest ::= OCTET STRING |
|
* |
|
* To perform PSS signature verification, provide an instance |
|
* of Forge PSS object as the scheme parameter. |
|
* |
|
* @param digest the message digest hash to compare against the signature, |
|
* as a binary-encoded string. |
|
* @param signature the signature to verify, as a binary-encoded string. |
|
* @param scheme signature verification scheme to use: |
|
* 'RSASSA-PKCS1-V1_5' or undefined for RSASSA PKCS#1 v1.5, |
|
* a Forge PSS object for RSASSA-PSS, |
|
* 'NONE' or null for none, DigestInfo will not be expected, but |
|
* PKCS#1 v1.5 padding will still be used. |
|
* |
|
* @return true if the signature was verified, false if not. |
|
*/ key1.verify = function(digest1, signature, scheme) { |
|
if (typeof scheme === 'string') scheme = scheme.toUpperCase(); |
|
else if (scheme === undefined) scheme = 'RSASSA-PKCS1-V1_5'; |
|
if (scheme === 'RSASSA-PKCS1-V1_5') scheme = { |
|
verify: function(digest, d) { |
|
// remove padding |
|
d = $8ab3548bea1beb81$var$_decodePkcs1_v1_5(d, key1, true); |
|
// d is ASN.1 BER-encoded DigestInfo |
|
var obj = $8ab3548bea1beb81$var$asn1.fromDer(d); |
|
// compare the given digest to the decrypted one |
|
return digest === obj.value[1].value; |
|
} |
|
}; |
|
else if (scheme === 'NONE' || scheme === 'NULL' || scheme === null) scheme = { |
|
verify: function(digest, d) { |
|
// remove padding |
|
d = $8ab3548bea1beb81$var$_decodePkcs1_v1_5(d, key1, true); |
|
return digest === d; |
|
} |
|
}; |
|
// do rsa decryption w/o any decoding, then verify -- which does decoding |
|
var d1 = $8ab3548bea1beb81$var$pki.rsa.decrypt(signature, key1, true, false); |
|
return scheme.verify(digest1, d1, key1.n.bitLength()); |
|
}; |
|
return key1; |
|
}; |
|
/** |
|
* Sets an RSA private key from BigIntegers modulus, exponent, primes, |
|
* prime exponents, and modular multiplicative inverse. |
|
* |
|
* @param n the modulus. |
|
* @param e the public exponent. |
|
* @param d the private exponent ((inverse of e) mod n). |
|
* @param p the first prime. |
|
* @param q the second prime. |
|
* @param dP exponent1 (d mod (p-1)). |
|
* @param dQ exponent2 (d mod (q-1)). |
|
* @param qInv ((inverse of q) mod p) |
|
* |
|
* @return the private key. |
|
*/ $8ab3548bea1beb81$var$pki.setRsaPrivateKey = $8ab3548bea1beb81$var$pki.rsa.setPrivateKey = function(n, e, d2, p, q, dP, dQ, qInv) { |
|
var key2 = { |
|
n: n, |
|
e: e, |
|
d: d2, |
|
p: p, |
|
q: q, |
|
dP: dP, |
|
dQ: dQ, |
|
qInv: qInv |
|
}; |
|
/** |
|
* Decrypts the given data with this private key. The decryption scheme |
|
* must match the one used to encrypt the data. |
|
* |
|
* @param data the byte string to decrypt. |
|
* @param scheme the decryption scheme to use: |
|
* 'RSAES-PKCS1-V1_5' (default), |
|
* 'RSA-OAEP', |
|
* 'RAW', 'NONE', or null to perform raw RSA decryption. |
|
* @param schemeOptions any scheme-specific options. |
|
* |
|
* @return the decrypted byte string. |
|
*/ key2.decrypt = function(data, scheme, schemeOptions) { |
|
if (typeof scheme === 'string') scheme = scheme.toUpperCase(); |
|
else if (scheme === undefined) scheme = 'RSAES-PKCS1-V1_5'; |
|
// do rsa decryption w/o any decoding |
|
var d3 = $8ab3548bea1beb81$var$pki.rsa.decrypt(data, key2, false, false); |
|
if (scheme === 'RSAES-PKCS1-V1_5') scheme = { |
|
decode: $8ab3548bea1beb81$var$_decodePkcs1_v1_5 |
|
}; |
|
else if (scheme === 'RSA-OAEP' || scheme === 'RSAES-OAEP') scheme = { |
|
decode: function(d, key) { |
|
return $iGlOy.pkcs1.decode_rsa_oaep(key, d, schemeOptions); |
|
} |
|
}; |
|
else if ([ |
|
'RAW', |
|
'NONE', |
|
'NULL', |
|
null |
|
].indexOf(scheme) !== -1) scheme = { |
|
decode: function(d) { |
|
return d; |
|
} |
|
}; |
|
else throw new Error('Unsupported encryption scheme: "' + scheme + '".'); |
|
// decode according to scheme |
|
return scheme.decode(d3, key2, false); |
|
}; |
|
/** |
|
* Signs the given digest, producing a signature. |
|
* |
|
* PKCS#1 supports multiple (currently two) signature schemes: |
|
* RSASSA-PKCS1-V1_5 and RSASSA-PSS. |
|
* |
|
* By default this implementation uses the "old scheme", i.e. |
|
* RSASSA-PKCS1-V1_5. In order to generate a PSS signature, provide |
|
* an instance of Forge PSS object as the scheme parameter. |
|
* |
|
* @param md the message digest object with the hash to sign. |
|
* @param scheme the signature scheme to use: |
|
* 'RSASSA-PKCS1-V1_5' or undefined for RSASSA PKCS#1 v1.5, |
|
* a Forge PSS object for RSASSA-PSS, |
|
* 'NONE' or null for none, DigestInfo will not be used but |
|
* PKCS#1 v1.5 padding will still be used. |
|
* |
|
* @return the signature as a byte string. |
|
*/ key2.sign = function(md, scheme) { |
|
/* Note: The internal implementation of RSA operations is being |
|
transitioned away from a PKCS#1 v1.5 hard-coded scheme. Some legacy |
|
code like the use of an encoding block identifier 'bt' will eventually |
|
be removed. */ // private key operation |
|
var bt = false; |
|
if (typeof scheme === 'string') scheme = scheme.toUpperCase(); |
|
if (scheme === undefined || scheme === 'RSASSA-PKCS1-V1_5') { |
|
scheme = { |
|
encode: $8ab3548bea1beb81$var$emsaPkcs1v15encode |
|
}; |
|
bt = 1; |
|
} else if (scheme === 'NONE' || scheme === 'NULL' || scheme === null) { |
|
scheme = { |
|
encode: function() { |
|
return md; |
|
} |
|
}; |
|
bt = 1; |
|
} |
|
// encode and then encrypt |
|
var d = scheme.encode(md, key2.n.bitLength()); |
|
return $8ab3548bea1beb81$var$pki.rsa.encrypt(d, key2, bt); |
|
}; |
|
return key2; |
|
}; |
|
/** |
|
* Wraps an RSAPrivateKey ASN.1 object in an ASN.1 PrivateKeyInfo object. |
|
* |
|
* @param rsaKey the ASN.1 RSAPrivateKey. |
|
* |
|
* @return the ASN.1 PrivateKeyInfo. |
|
*/ $8ab3548bea1beb81$var$pki.wrapRsaPrivateKey = function(rsaKey) { |
|
// PrivateKeyInfo |
|
return $8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, true, [ |
|
// version (0) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$asn1.integerToDer(0).getBytes()), |
|
// privateKeyAlgorithm |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, true, [ |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.OID, false, $8ab3548bea1beb81$var$asn1.oidToDer($8ab3548bea1beb81$var$pki.oids.rsaEncryption).getBytes()), |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.NULL, false, '') |
|
]), |
|
// PrivateKey |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.OCTETSTRING, false, $8ab3548bea1beb81$var$asn1.toDer(rsaKey).getBytes()) |
|
]); |
|
}; |
|
/** |
|
* Converts a private key from an ASN.1 object. |
|
* |
|
* @param obj the ASN.1 representation of a PrivateKeyInfo containing an |
|
* RSAPrivateKey or an RSAPrivateKey. |
|
* |
|
* @return the private key. |
|
*/ $8ab3548bea1beb81$var$pki.privateKeyFromAsn1 = function(obj) { |
|
// get PrivateKeyInfo |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if ($8ab3548bea1beb81$var$asn1.validate(obj, $8ab3548bea1beb81$var$privateKeyValidator, capture, errors)) obj = $8ab3548bea1beb81$var$asn1.fromDer($iGlOy.util.createBuffer(capture.privateKey)); |
|
// get RSAPrivateKey |
|
capture = { |
|
}; |
|
errors = []; |
|
if (!$8ab3548bea1beb81$var$asn1.validate(obj, $8ab3548bea1beb81$var$rsaPrivateKeyValidator, capture, errors)) { |
|
var error = new Error("Cannot read private key. ASN.1 object does not contain an RSAPrivateKey."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
// Note: Version is currently ignored. |
|
// capture.privateKeyVersion |
|
// FIXME: inefficient, get a BigInteger that uses byte strings |
|
var n, e, d, p, q, dP, dQ, qInv; |
|
n = $iGlOy.util.createBuffer(capture.privateKeyModulus).toHex(); |
|
e = $iGlOy.util.createBuffer(capture.privateKeyPublicExponent).toHex(); |
|
d = $iGlOy.util.createBuffer(capture.privateKeyPrivateExponent).toHex(); |
|
p = $iGlOy.util.createBuffer(capture.privateKeyPrime1).toHex(); |
|
q = $iGlOy.util.createBuffer(capture.privateKeyPrime2).toHex(); |
|
dP = $iGlOy.util.createBuffer(capture.privateKeyExponent1).toHex(); |
|
dQ = $iGlOy.util.createBuffer(capture.privateKeyExponent2).toHex(); |
|
qInv = $iGlOy.util.createBuffer(capture.privateKeyCoefficient).toHex(); |
|
// set private key |
|
return $8ab3548bea1beb81$var$pki.setRsaPrivateKey(new $8ab3548bea1beb81$var$BigInteger(n, 16), new $8ab3548bea1beb81$var$BigInteger(e, 16), new $8ab3548bea1beb81$var$BigInteger(d, 16), new $8ab3548bea1beb81$var$BigInteger(p, 16), new $8ab3548bea1beb81$var$BigInteger(q, 16), new $8ab3548bea1beb81$var$BigInteger(dP, 16), new $8ab3548bea1beb81$var$BigInteger(dQ, 16), new $8ab3548bea1beb81$var$BigInteger(qInv, 16)); |
|
}; |
|
/** |
|
* Converts a private key to an ASN.1 RSAPrivateKey. |
|
* |
|
* @param key the private key. |
|
* |
|
* @return the ASN.1 representation of an RSAPrivateKey. |
|
*/ $8ab3548bea1beb81$var$pki.privateKeyToAsn1 = $8ab3548bea1beb81$var$pki.privateKeyToRSAPrivateKey = function(key) { |
|
// RSAPrivateKey |
|
return $8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, true, [ |
|
// version (0 = only 2 primes, 1 multiple primes) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$asn1.integerToDer(0).getBytes()), |
|
// modulus (n) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.n)), |
|
// publicExponent (e) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.e)), |
|
// privateExponent (d) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.d)), |
|
// privateKeyPrime1 (p) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.p)), |
|
// privateKeyPrime2 (q) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.q)), |
|
// privateKeyExponent1 (dP) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.dP)), |
|
// privateKeyExponent2 (dQ) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.dQ)), |
|
// coefficient (qInv) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.qInv)) |
|
]); |
|
}; |
|
/** |
|
* Converts a public key from an ASN.1 SubjectPublicKeyInfo or RSAPublicKey. |
|
* |
|
* @param obj the asn1 representation of a SubjectPublicKeyInfo or RSAPublicKey. |
|
* |
|
* @return the public key. |
|
*/ $8ab3548bea1beb81$var$pki.publicKeyFromAsn1 = function(obj) { |
|
// get SubjectPublicKeyInfo |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if ($8ab3548bea1beb81$var$asn1.validate(obj, $8ab3548bea1beb81$var$publicKeyValidator, capture, errors)) { |
|
// get oid |
|
var oid = $8ab3548bea1beb81$var$asn1.derToOid(capture.publicKeyOid); |
|
if (oid !== $8ab3548bea1beb81$var$pki.oids.rsaEncryption) { |
|
var error = new Error('Cannot read public key. Unknown OID.'); |
|
error.oid = oid; |
|
throw error; |
|
} |
|
obj = capture.rsaPublicKey; |
|
} |
|
// get RSA params |
|
errors = []; |
|
if (!$8ab3548bea1beb81$var$asn1.validate(obj, $8ab3548bea1beb81$var$rsaPublicKeyValidator, capture, errors)) { |
|
var error = new Error("Cannot read public key. ASN.1 object does not contain an RSAPublicKey."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
// FIXME: inefficient, get a BigInteger that uses byte strings |
|
var n = $iGlOy.util.createBuffer(capture.publicKeyModulus).toHex(); |
|
var e = $iGlOy.util.createBuffer(capture.publicKeyExponent).toHex(); |
|
// set public key |
|
return $8ab3548bea1beb81$var$pki.setRsaPublicKey(new $8ab3548bea1beb81$var$BigInteger(n, 16), new $8ab3548bea1beb81$var$BigInteger(e, 16)); |
|
}; |
|
/** |
|
* Converts a public key to an ASN.1 SubjectPublicKeyInfo. |
|
* |
|
* @param key the public key. |
|
* |
|
* @return the asn1 representation of a SubjectPublicKeyInfo. |
|
*/ $8ab3548bea1beb81$var$pki.publicKeyToAsn1 = $8ab3548bea1beb81$var$pki.publicKeyToSubjectPublicKeyInfo = function(key) { |
|
// SubjectPublicKeyInfo |
|
return $8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, true, [ |
|
// AlgorithmIdentifier |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, true, [ |
|
// algorithm |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.OID, false, $8ab3548bea1beb81$var$asn1.oidToDer($8ab3548bea1beb81$var$pki.oids.rsaEncryption).getBytes()), |
|
// parameters (null) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.NULL, false, '') |
|
]), |
|
// subjectPublicKey |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.BITSTRING, false, [ |
|
$8ab3548bea1beb81$var$pki.publicKeyToRSAPublicKey(key) |
|
]) |
|
]); |
|
}; |
|
/** |
|
* Converts a public key to an ASN.1 RSAPublicKey. |
|
* |
|
* @param key the public key. |
|
* |
|
* @return the asn1 representation of a RSAPublicKey. |
|
*/ $8ab3548bea1beb81$var$pki.publicKeyToRSAPublicKey = function(key) { |
|
// RSAPublicKey |
|
return $8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.SEQUENCE, true, [ |
|
// modulus (n) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.n)), |
|
// publicExponent (e) |
|
$8ab3548bea1beb81$var$asn1.create($8ab3548bea1beb81$var$asn1.Class.UNIVERSAL, $8ab3548bea1beb81$var$asn1.Type.INTEGER, false, $8ab3548bea1beb81$var$_bnToBytes(key.e)) |
|
]); |
|
}; |
|
/** |
|
* Encodes a message using PKCS#1 v1.5 padding. |
|
* |
|
* @param m the message to encode. |
|
* @param key the RSA key to use. |
|
* @param bt the block type to use, i.e. either 0x01 (for signing) or 0x02 |
|
* (for encryption). |
|
* |
|
* @return the padded byte buffer. |
|
*/ function $8ab3548bea1beb81$var$_encodePkcs1_v1_5(m, key, bt) { |
|
var eb = $iGlOy.util.createBuffer(); |
|
// get the length of the modulus in bytes |
|
var k = Math.ceil(key.n.bitLength() / 8); |
|
/* use PKCS#1 v1.5 padding */ if (m.length > k - 11) { |
|
var error = new Error('Message is too long for PKCS#1 v1.5 padding.'); |
|
error.length = m.length; |
|
error.max = k - 11; |
|
throw error; |
|
} |
|
/* A block type BT, a padding string PS, and the data D shall be |
|
formatted into an octet string EB, the encryption block: |
|
|
|
EB = 00 || BT || PS || 00 || D |
|
|
|
The block type BT shall be a single octet indicating the structure of |
|
the encryption block. For this version of the document it shall have |
|
value 00, 01, or 02. For a private-key operation, the block type |
|
shall be 00 or 01. For a public-key operation, it shall be 02. |
|
|
|
The padding string PS shall consist of k-3-||D|| octets. For block |
|
type 00, the octets shall have value 00; for block type 01, they |
|
shall have value FF; and for block type 02, they shall be |
|
pseudorandomly generated and nonzero. This makes the length of the |
|
encryption block EB equal to k. */ // build the encryption block |
|
eb.putByte(0); |
|
eb.putByte(bt); |
|
// create the padding |
|
var padNum = k - 3 - m.length; |
|
var padByte; |
|
// private key op |
|
if (bt === 0 || bt === 1) { |
|
padByte = bt === 0 ? 0 : 255; |
|
for(var i = 0; i < padNum; ++i)eb.putByte(padByte); |
|
} else // public key op |
|
// pad with random non-zero values |
|
while(padNum > 0){ |
|
var numZeros = 0; |
|
var padBytes = $iGlOy.random.getBytes(padNum); |
|
for(var i = 0; i < padNum; ++i){ |
|
padByte = padBytes.charCodeAt(i); |
|
if (padByte === 0) ++numZeros; |
|
else eb.putByte(padByte); |
|
} |
|
padNum = numZeros; |
|
} |
|
// zero followed by message |
|
eb.putByte(0); |
|
eb.putBytes(m); |
|
return eb; |
|
} |
|
/** |
|
* Decodes a message using PKCS#1 v1.5 padding. |
|
* |
|
* @param em the message to decode. |
|
* @param key the RSA key to use. |
|
* @param pub true if the key is a public key, false if it is private. |
|
* @param ml the message length, if specified. |
|
* |
|
* @return the decoded bytes. |
|
*/ function $8ab3548bea1beb81$var$_decodePkcs1_v1_5(em, key, pub, ml) { |
|
// get the length of the modulus in bytes |
|
var k = Math.ceil(key.n.bitLength() / 8); |
|
/* It is an error if any of the following conditions occurs: |
|
|
|
1. The encryption block EB cannot be parsed unambiguously. |
|
2. The padding string PS consists of fewer than eight octets |
|
or is inconsisent with the block type BT. |
|
3. The decryption process is a public-key operation and the block |
|
type BT is not 00 or 01, or the decryption process is a |
|
private-key operation and the block type is not 02. |
|
*/ // parse the encryption block |
|
var eb = $iGlOy.util.createBuffer(em); |
|
var first = eb.getByte(); |
|
var bt = eb.getByte(); |
|
if (first !== 0 || pub && bt !== 0 && bt !== 1 || !pub && bt != 2 || pub && bt === 0 && typeof ml === 'undefined') throw new Error('Encryption block is invalid.'); |
|
var padNum = 0; |
|
if (bt === 0) { |
|
// check all padding bytes for 0x00 |
|
padNum = k - 3 - ml; |
|
for(var i = 0; i < padNum; ++i){ |
|
if (eb.getByte() !== 0) throw new Error('Encryption block is invalid.'); |
|
} |
|
} else if (bt === 1) { |
|
// find the first byte that isn't 0xFF, should be after all padding |
|
padNum = 0; |
|
while(eb.length() > 1){ |
|
if (eb.getByte() !== 255) { |
|
--eb.read; |
|
break; |
|
} |
|
++padNum; |
|
} |
|
} else if (bt === 2) { |
|
// look for 0x00 byte |
|
padNum = 0; |
|
while(eb.length() > 1){ |
|
if (eb.getByte() === 0) { |
|
--eb.read; |
|
break; |
|
} |
|
++padNum; |
|
} |
|
} |
|
// zero must be 0x00 and padNum must be (k - 3 - message length) |
|
var zero = eb.getByte(); |
|
if (zero !== 0 || padNum !== k - 3 - eb.length()) throw new Error('Encryption block is invalid.'); |
|
return eb.getBytes(); |
|
} |
|
/** |
|
* Runs the key-generation algorithm asynchronously, either in the background |
|
* via Web Workers, or using the main thread and setImmediate. |
|
* |
|
* @param state the key-pair generation state. |
|
* @param [options] options for key-pair generation: |
|
* workerScript the worker script URL. |
|
* workers the number of web workers (if supported) to use, |
|
* (default: 2, -1 to use estimated cores minus one). |
|
* workLoad the size of the work load, ie: number of possible prime |
|
* numbers for each web worker to check per work assignment, |
|
* (default: 100). |
|
* @param callback(err, keypair) called once the operation completes. |
|
*/ function $8ab3548bea1beb81$var$_generateKeyPair(state, options, callback1) { |
|
if (typeof options === 'function') { |
|
callback1 = options; |
|
options = { |
|
}; |
|
} |
|
options = options || { |
|
}; |
|
var opts = { |
|
algorithm: { |
|
name: options.algorithm || 'PRIMEINC', |
|
options: { |
|
workers: options.workers || 2, |
|
workLoad: options.workLoad || 100, |
|
workerScript: options.workerScript |
|
} |
|
} |
|
}; |
|
if ('prng' in options) opts.prng = options.prng; |
|
generate(); |
|
function generate() { |
|
// find p and then q (done in series to simplify) |
|
getPrime(state.pBits, function(err, num) { |
|
if (err) return callback1(err); |
|
state.p = num; |
|
if (state.q !== null) return finish(err, state.q); |
|
getPrime(state.qBits, finish); |
|
}); |
|
} |
|
function getPrime(bits, callback) { |
|
$iGlOy.prime.generateProbablePrime(bits, opts, callback); |
|
} |
|
function finish(err, num) { |
|
if (err) return callback1(err); |
|
// set q |
|
state.q = num; |
|
// ensure p is larger than q (swap them if not) |
|
if (state.p.compareTo(state.q) < 0) { |
|
var tmp = state.p; |
|
state.p = state.q; |
|
state.q = tmp; |
|
} |
|
// ensure p is coprime with e |
|
if (state.p.subtract($8ab3548bea1beb81$var$BigInteger.ONE).gcd(state.e).compareTo($8ab3548bea1beb81$var$BigInteger.ONE) !== 0) { |
|
state.p = null; |
|
generate(); |
|
return; |
|
} |
|
// ensure q is coprime with e |
|
if (state.q.subtract($8ab3548bea1beb81$var$BigInteger.ONE).gcd(state.e).compareTo($8ab3548bea1beb81$var$BigInteger.ONE) !== 0) { |
|
state.q = null; |
|
getPrime(state.qBits, finish); |
|
return; |
|
} |
|
// compute phi: (p - 1)(q - 1) (Euler's totient function) |
|
state.p1 = state.p.subtract($8ab3548bea1beb81$var$BigInteger.ONE); |
|
state.q1 = state.q.subtract($8ab3548bea1beb81$var$BigInteger.ONE); |
|
state.phi = state.p1.multiply(state.q1); |
|
// ensure e and phi are coprime |
|
if (state.phi.gcd(state.e).compareTo($8ab3548bea1beb81$var$BigInteger.ONE) !== 0) { |
|
// phi and e aren't coprime, so generate a new p and q |
|
state.p = state.q = null; |
|
generate(); |
|
return; |
|
} |
|
// create n, ensure n is has the right number of bits |
|
state.n = state.p.multiply(state.q); |
|
if (state.n.bitLength() !== state.bits) { |
|
// failed, get new q |
|
state.q = null; |
|
getPrime(state.qBits, finish); |
|
return; |
|
} |
|
// set keys |
|
var d = state.e.modInverse(state.phi); |
|
state.keys = { |
|
privateKey: $8ab3548bea1beb81$var$pki.rsa.setPrivateKey(state.n, state.e, d, state.p, state.q, d.mod(state.p1), d.mod(state.q1), state.q.modInverse(state.p)), |
|
publicKey: $8ab3548bea1beb81$var$pki.rsa.setPublicKey(state.n, state.e) |
|
}; |
|
callback1(null, state.keys); |
|
} |
|
} |
|
/** |
|
* Converts a positive BigInteger into 2's-complement big-endian bytes. |
|
* |
|
* @param b the big integer to convert. |
|
* |
|
* @return the bytes. |
|
*/ function $8ab3548bea1beb81$var$_bnToBytes(b) { |
|
// prepend 0x00 if first byte >= 0x80 |
|
var hex = b.toString(16); |
|
if (hex[0] >= '8') hex = '00' + hex; |
|
var bytes = $iGlOy.util.hexToBytes(hex); |
|
// ensure integer is minimally-encoded |
|
if (bytes.length > 1 && (bytes.charCodeAt(0) === 0 && (bytes.charCodeAt(1) & 128) === 0 || bytes.charCodeAt(0) === 255 && (bytes.charCodeAt(1) & 128) === 128)) return bytes.substr(1); |
|
return bytes; |
|
} |
|
/** |
|
* Returns the required number of Miller-Rabin tests to generate a |
|
* prime with an error probability of (1/2)^80. |
|
* |
|
* See Handbook of Applied Cryptography Chapter 4, Table 4.4. |
|
* |
|
* @param bits the bit size. |
|
* |
|
* @return the required number of iterations. |
|
*/ function $8ab3548bea1beb81$var$_getMillerRabinTests(bits) { |
|
if (bits <= 100) return 27; |
|
if (bits <= 150) return 18; |
|
if (bits <= 200) return 15; |
|
if (bits <= 250) return 12; |
|
if (bits <= 300) return 9; |
|
if (bits <= 350) return 8; |
|
if (bits <= 400) return 7; |
|
if (bits <= 500) return 6; |
|
if (bits <= 600) return 5; |
|
if (bits <= 800) return 4; |
|
if (bits <= 1250) return 3; |
|
return 2; |
|
} |
|
/** |
|
* Performs feature detection on the Node crypto interface. |
|
* |
|
* @param fn the feature (function) to detect. |
|
* |
|
* @return true if detected, false if not. |
|
*/ function $8ab3548bea1beb81$var$_detectNodeCrypto(fn) { |
|
return $iGlOy.util.isNodejs && typeof $8ab3548bea1beb81$var$_crypto[fn] === 'function'; |
|
} |
|
/** |
|
* Performs feature detection on the SubtleCrypto interface. |
|
* |
|
* @param fn the feature (function) to detect. |
|
* |
|
* @return true if detected, false if not. |
|
*/ function $8ab3548bea1beb81$var$_detectSubtleCrypto(fn) { |
|
return typeof $8ab3548bea1beb81$var$util.globalScope !== 'undefined' && typeof $8ab3548bea1beb81$var$util.globalScope.crypto === 'object' && typeof $8ab3548bea1beb81$var$util.globalScope.crypto.subtle === 'object' && typeof $8ab3548bea1beb81$var$util.globalScope.crypto.subtle[fn] === 'function'; |
|
} |
|
/** |
|
* Performs feature detection on the deprecated Microsoft Internet Explorer |
|
* outdated SubtleCrypto interface. This function should only be used after |
|
* checking for the modern, standard SubtleCrypto interface. |
|
* |
|
* @param fn the feature (function) to detect. |
|
* |
|
* @return true if detected, false if not. |
|
*/ function $8ab3548bea1beb81$var$_detectSubtleMsCrypto(fn) { |
|
return typeof $8ab3548bea1beb81$var$util.globalScope !== 'undefined' && typeof $8ab3548bea1beb81$var$util.globalScope.msCrypto === 'object' && typeof $8ab3548bea1beb81$var$util.globalScope.msCrypto.subtle === 'object' && typeof $8ab3548bea1beb81$var$util.globalScope.msCrypto.subtle[fn] === 'function'; |
|
} |
|
function $8ab3548bea1beb81$var$_intToUint8Array(x) { |
|
var bytes = $iGlOy.util.hexToBytes(x.toString(16)); |
|
var buffer = new Uint8Array(bytes.length); |
|
for(var i = 0; i < bytes.length; ++i)buffer[i] = bytes.charCodeAt(i); |
|
return buffer; |
|
} |
|
function $8ab3548bea1beb81$var$_privateKeyFromJwk(jwk) { |
|
if (jwk.kty !== 'RSA') throw new Error('Unsupported key algorithm "' + jwk.kty + '"; algorithm must be "RSA".'); |
|
return $8ab3548bea1beb81$var$pki.setRsaPrivateKey($8ab3548bea1beb81$var$_base64ToBigInt(jwk.n), $8ab3548bea1beb81$var$_base64ToBigInt(jwk.e), $8ab3548bea1beb81$var$_base64ToBigInt(jwk.d), $8ab3548bea1beb81$var$_base64ToBigInt(jwk.p), $8ab3548bea1beb81$var$_base64ToBigInt(jwk.q), $8ab3548bea1beb81$var$_base64ToBigInt(jwk.dp), $8ab3548bea1beb81$var$_base64ToBigInt(jwk.dq), $8ab3548bea1beb81$var$_base64ToBigInt(jwk.qi)); |
|
} |
|
function $8ab3548bea1beb81$var$_publicKeyFromJwk(jwk) { |
|
if (jwk.kty !== 'RSA') throw new Error('Key algorithm must be "RSA".'); |
|
return $8ab3548bea1beb81$var$pki.setRsaPublicKey($8ab3548bea1beb81$var$_base64ToBigInt(jwk.n), $8ab3548bea1beb81$var$_base64ToBigInt(jwk.e)); |
|
} |
|
function $8ab3548bea1beb81$var$_base64ToBigInt(b64) { |
|
return new $8ab3548bea1beb81$var$BigInteger($iGlOy.util.bytesToHex($iGlOy.util.decode64(b64)), 16); |
|
} |
|
|
|
|
|
|
|
if (typeof $4ead143e6089ae29$var$BigInteger === 'undefined') var $4ead143e6089ae29$var$BigInteger = $iGlOy.jsbn.BigInteger; |
|
// shortcut for asn.1 API |
|
var $4ead143e6089ae29$var$asn1 = $iGlOy.asn1; |
|
/* Password-based encryption implementation. */ var $4ead143e6089ae29$var$pki = $iGlOy.pki = $iGlOy.pki || { |
|
}; |
|
$4ead143e6089ae29$exports = $4ead143e6089ae29$var$pki.pbe = $iGlOy.pbe = $iGlOy.pbe || { |
|
}; |
|
var $4ead143e6089ae29$var$oids = $4ead143e6089ae29$var$pki.oids; |
|
// validator for an EncryptedPrivateKeyInfo structure |
|
// Note: Currently only works w/algorithm params |
|
var $4ead143e6089ae29$var$encryptedPrivateKeyValidator = { |
|
name: 'EncryptedPrivateKeyInfo', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'EncryptedPrivateKeyInfo.encryptionAlgorithm', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'AlgorithmIdentifier.algorithm', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'encryptionOid' |
|
}, |
|
{ |
|
name: 'AlgorithmIdentifier.parameters', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'encryptionParams' |
|
} |
|
] |
|
}, |
|
{ |
|
// encryptedData |
|
name: 'EncryptedPrivateKeyInfo.encryptedData', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'encryptedData' |
|
} |
|
] |
|
}; |
|
// validator for a PBES2Algorithms structure |
|
// Note: Currently only works w/PBKDF2 + AES encryption schemes |
|
var $4ead143e6089ae29$var$PBES2AlgorithmsValidator = { |
|
name: 'PBES2Algorithms', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'PBES2Algorithms.keyDerivationFunc', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'PBES2Algorithms.keyDerivationFunc.oid', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'kdfOid' |
|
}, |
|
{ |
|
name: 'PBES2Algorithms.params', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'PBES2Algorithms.params.salt', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'kdfSalt' |
|
}, |
|
{ |
|
name: 'PBES2Algorithms.params.iterationCount', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'kdfIterationCount' |
|
}, |
|
{ |
|
name: 'PBES2Algorithms.params.keyLength', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
optional: true, |
|
capture: 'keyLength' |
|
}, |
|
{ |
|
// prf |
|
name: 'PBES2Algorithms.params.prf', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
optional: true, |
|
value: [ |
|
{ |
|
name: 'PBES2Algorithms.params.prf.algorithm', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'prfOid' |
|
} |
|
] |
|
} |
|
] |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'PBES2Algorithms.encryptionScheme', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'PBES2Algorithms.encryptionScheme.oid', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'encOid' |
|
}, |
|
{ |
|
name: 'PBES2Algorithms.encryptionScheme.iv', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'encIv' |
|
} |
|
] |
|
} |
|
] |
|
}; |
|
var $4ead143e6089ae29$var$pkcs12PbeParamsValidator = { |
|
name: 'pkcs-12PbeParams', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'pkcs-12PbeParams.salt', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'salt' |
|
}, |
|
{ |
|
name: 'pkcs-12PbeParams.iterations', |
|
tagClass: $4ead143e6089ae29$var$asn1.Class.UNIVERSAL, |
|
type: $4ead143e6089ae29$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'iterations' |
|
} |
|
] |
|
}; |
|
/** |
|
* Encrypts a ASN.1 PrivateKeyInfo object, producing an EncryptedPrivateKeyInfo. |
|
* |
|
* PBES2Algorithms ALGORITHM-IDENTIFIER ::= |
|
* { {PBES2-params IDENTIFIED BY id-PBES2}, ...} |
|
* |
|
* id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} |
|
* |
|
* PBES2-params ::= SEQUENCE { |
|
* keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, |
|
* encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} |
|
* } |
|
* |
|
* PBES2-KDFs ALGORITHM-IDENTIFIER ::= |
|
* { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... } |
|
* |
|
* PBES2-Encs ALGORITHM-IDENTIFIER ::= { ... } |
|
* |
|
* PBKDF2-params ::= SEQUENCE { |
|
* salt CHOICE { |
|
* specified OCTET STRING, |
|
* otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} |
|
* }, |
|
* iterationCount INTEGER (1..MAX), |
|
* keyLength INTEGER (1..MAX) OPTIONAL, |
|
* prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 |
|
* } |
|
* |
|
* @param obj the ASN.1 PrivateKeyInfo object. |
|
* @param password the password to encrypt with. |
|
* @param options: |
|
* algorithm the encryption algorithm to use |
|
* ('aes128', 'aes192', 'aes256', '3des'), defaults to 'aes128'. |
|
* count the iteration count to use. |
|
* saltSize the salt size to use. |
|
* prfAlgorithm the PRF message digest algorithm to use |
|
* ('sha1', 'sha224', 'sha256', 'sha384', 'sha512') |
|
* |
|
* @return the ASN.1 EncryptedPrivateKeyInfo. |
|
*/ $4ead143e6089ae29$var$pki.encryptPrivateKeyInfo = function(obj, password, options) { |
|
// set default options |
|
options = options || { |
|
}; |
|
options.saltSize = options.saltSize || 8; |
|
options.count = options.count || 2048; |
|
options.algorithm = options.algorithm || 'aes128'; |
|
options.prfAlgorithm = options.prfAlgorithm || 'sha1'; |
|
// generate PBE params |
|
var salt = $iGlOy.random.getBytesSync(options.saltSize); |
|
var count = options.count; |
|
var countBytes = $4ead143e6089ae29$var$asn1.integerToDer(count); |
|
var dkLen; |
|
var encryptionAlgorithm; |
|
var encryptedData; |
|
if (options.algorithm.indexOf('aes') === 0 || options.algorithm === 'des') { |
|
// do PBES2 |
|
var ivLen, encOid, cipherFn; |
|
switch(options.algorithm){ |
|
case 'aes128': |
|
dkLen = 16; |
|
ivLen = 16; |
|
encOid = $4ead143e6089ae29$var$oids['aes128-CBC']; |
|
cipherFn = $iGlOy.aes.createEncryptionCipher; |
|
break; |
|
case 'aes192': |
|
dkLen = 24; |
|
ivLen = 16; |
|
encOid = $4ead143e6089ae29$var$oids['aes192-CBC']; |
|
cipherFn = $iGlOy.aes.createEncryptionCipher; |
|
break; |
|
case 'aes256': |
|
dkLen = 32; |
|
ivLen = 16; |
|
encOid = $4ead143e6089ae29$var$oids['aes256-CBC']; |
|
cipherFn = $iGlOy.aes.createEncryptionCipher; |
|
break; |
|
case 'des': |
|
dkLen = 8; |
|
ivLen = 8; |
|
encOid = $4ead143e6089ae29$var$oids['desCBC']; |
|
cipherFn = $iGlOy.des.createEncryptionCipher; |
|
break; |
|
default: |
|
var error = new Error('Cannot encrypt private key. Unknown encryption algorithm.'); |
|
error.algorithm = options.algorithm; |
|
throw error; |
|
} |
|
// get PRF message digest |
|
var prfAlgorithm = 'hmacWith' + options.prfAlgorithm.toUpperCase(); |
|
var md = $4ead143e6089ae29$var$prfAlgorithmToMessageDigest(prfAlgorithm); |
|
// encrypt private key using pbe SHA-1 and AES/DES |
|
var dk = $iGlOy.pkcs5.pbkdf2(password, salt, count, dkLen, md); |
|
var iv = $iGlOy.random.getBytesSync(ivLen); |
|
var cipher = cipherFn(dk); |
|
cipher.start(iv); |
|
cipher.update($4ead143e6089ae29$var$asn1.toDer(obj)); |
|
cipher.finish(); |
|
encryptedData = cipher.output.getBytes(); |
|
// get PBKDF2-params |
|
var params = $4ead143e6089ae29$var$createPbkdf2Params(salt, countBytes, dkLen, prfAlgorithm); |
|
encryptionAlgorithm = $4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.SEQUENCE, true, [ |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.OID, false, $4ead143e6089ae29$var$asn1.oidToDer($4ead143e6089ae29$var$oids['pkcs5PBES2']).getBytes()), |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.SEQUENCE, true, [ |
|
// keyDerivationFunc |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.SEQUENCE, true, [ |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.OID, false, $4ead143e6089ae29$var$asn1.oidToDer($4ead143e6089ae29$var$oids['pkcs5PBKDF2']).getBytes()), |
|
// PBKDF2-params |
|
params |
|
]), |
|
// encryptionScheme |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.SEQUENCE, true, [ |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.OID, false, $4ead143e6089ae29$var$asn1.oidToDer(encOid).getBytes()), |
|
// iv |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.OCTETSTRING, false, iv) |
|
]) |
|
]) |
|
]); |
|
} else if (options.algorithm === '3des') { |
|
// Do PKCS12 PBE |
|
dkLen = 24; |
|
var saltBytes = new $iGlOy.util.ByteBuffer(salt); |
|
var dk = $4ead143e6089ae29$var$pki.pbe.generatePkcs12Key(password, saltBytes, 1, count, dkLen); |
|
var iv = $4ead143e6089ae29$var$pki.pbe.generatePkcs12Key(password, saltBytes, 2, count, dkLen); |
|
var cipher = $iGlOy.des.createEncryptionCipher(dk); |
|
cipher.start(iv); |
|
cipher.update($4ead143e6089ae29$var$asn1.toDer(obj)); |
|
cipher.finish(); |
|
encryptedData = cipher.output.getBytes(); |
|
encryptionAlgorithm = $4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.SEQUENCE, true, [ |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.OID, false, $4ead143e6089ae29$var$asn1.oidToDer($4ead143e6089ae29$var$oids['pbeWithSHAAnd3-KeyTripleDES-CBC']).getBytes()), |
|
// pkcs-12PbeParams |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.SEQUENCE, true, [ |
|
// salt |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.OCTETSTRING, false, salt), |
|
// iteration count |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.INTEGER, false, countBytes.getBytes()) |
|
]) |
|
]); |
|
} else { |
|
var error = new Error('Cannot encrypt private key. Unknown encryption algorithm.'); |
|
error.algorithm = options.algorithm; |
|
throw error; |
|
} |
|
// EncryptedPrivateKeyInfo |
|
var rval = $4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.SEQUENCE, true, [ |
|
// encryptionAlgorithm |
|
encryptionAlgorithm, |
|
// encryptedData |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.OCTETSTRING, false, encryptedData) |
|
]); |
|
return rval; |
|
}; |
|
/** |
|
* Decrypts a ASN.1 PrivateKeyInfo object. |
|
* |
|
* @param obj the ASN.1 EncryptedPrivateKeyInfo object. |
|
* @param password the password to decrypt with. |
|
* |
|
* @return the ASN.1 PrivateKeyInfo on success, null on failure. |
|
*/ $4ead143e6089ae29$var$pki.decryptPrivateKeyInfo = function(obj, password) { |
|
var rval = null; |
|
// get PBE params |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$4ead143e6089ae29$var$asn1.validate(obj, $4ead143e6089ae29$var$encryptedPrivateKeyValidator, capture, errors)) { |
|
var error = new Error("Cannot read encrypted private key. ASN.1 object is not a supported EncryptedPrivateKeyInfo."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
// get cipher |
|
var oid = $4ead143e6089ae29$var$asn1.derToOid(capture.encryptionOid); |
|
var cipher = $4ead143e6089ae29$var$pki.pbe.getCipher(oid, capture.encryptionParams, password); |
|
// get encrypted data |
|
var encrypted = $iGlOy.util.createBuffer(capture.encryptedData); |
|
cipher.update(encrypted); |
|
if (cipher.finish()) rval = $4ead143e6089ae29$var$asn1.fromDer(cipher.output); |
|
return rval; |
|
}; |
|
/** |
|
* Converts a EncryptedPrivateKeyInfo to PEM format. |
|
* |
|
* @param epki the EncryptedPrivateKeyInfo. |
|
* @param maxline the maximum characters per line, defaults to 64. |
|
* |
|
* @return the PEM-formatted encrypted private key. |
|
*/ $4ead143e6089ae29$var$pki.encryptedPrivateKeyToPem = function(epki, maxline) { |
|
// convert to DER, then PEM-encode |
|
var msg = { |
|
type: 'ENCRYPTED PRIVATE KEY', |
|
body: $4ead143e6089ae29$var$asn1.toDer(epki).getBytes() |
|
}; |
|
return $iGlOy.pem.encode(msg, { |
|
maxline: maxline |
|
}); |
|
}; |
|
/** |
|
* Converts a PEM-encoded EncryptedPrivateKeyInfo to ASN.1 format. Decryption |
|
* is not performed. |
|
* |
|
* @param pem the EncryptedPrivateKeyInfo in PEM-format. |
|
* |
|
* @return the ASN.1 EncryptedPrivateKeyInfo. |
|
*/ $4ead143e6089ae29$var$pki.encryptedPrivateKeyFromPem = function(pem) { |
|
var msg = $iGlOy.pem.decode(pem)[0]; |
|
if (msg.type !== 'ENCRYPTED PRIVATE KEY') { |
|
var error = new Error("Could not convert encrypted private key from PEM; PEM header type is \"ENCRYPTED PRIVATE KEY\"."); |
|
error.headerType = msg.type; |
|
throw error; |
|
} |
|
if (msg.procType && msg.procType.type === 'ENCRYPTED') throw new Error("Could not convert encrypted private key from PEM; PEM is encrypted."); |
|
// convert DER to ASN.1 object |
|
return $4ead143e6089ae29$var$asn1.fromDer(msg.body); |
|
}; |
|
/** |
|
* Encrypts an RSA private key. By default, the key will be wrapped in |
|
* a PrivateKeyInfo and encrypted to produce a PKCS#8 EncryptedPrivateKeyInfo. |
|
* This is the standard, preferred way to encrypt a private key. |
|
* |
|
* To produce a non-standard PEM-encrypted private key that uses encapsulated |
|
* headers to indicate the encryption algorithm (old-style non-PKCS#8 OpenSSL |
|
* private key encryption), set the 'legacy' option to true. Note: Using this |
|
* option will cause the iteration count to be forced to 1. |
|
* |
|
* Note: The 'des' algorithm is supported, but it is not considered to be |
|
* secure because it only uses a single 56-bit key. If possible, it is highly |
|
* recommended that a different algorithm be used. |
|
* |
|
* @param rsaKey the RSA key to encrypt. |
|
* @param password the password to use. |
|
* @param options: |
|
* algorithm: the encryption algorithm to use |
|
* ('aes128', 'aes192', 'aes256', '3des', 'des'). |
|
* count: the iteration count to use. |
|
* saltSize: the salt size to use. |
|
* legacy: output an old non-PKCS#8 PEM-encrypted+encapsulated |
|
* headers (DEK-Info) private key. |
|
* |
|
* @return the PEM-encoded ASN.1 EncryptedPrivateKeyInfo. |
|
*/ $4ead143e6089ae29$var$pki.encryptRsaPrivateKey = function(rsaKey, password, options) { |
|
// standard PKCS#8 |
|
options = options || { |
|
}; |
|
if (!options.legacy) { |
|
// encrypt PrivateKeyInfo |
|
var rval = $4ead143e6089ae29$var$pki.wrapRsaPrivateKey($4ead143e6089ae29$var$pki.privateKeyToAsn1(rsaKey)); |
|
rval = $4ead143e6089ae29$var$pki.encryptPrivateKeyInfo(rval, password, options); |
|
return $4ead143e6089ae29$var$pki.encryptedPrivateKeyToPem(rval); |
|
} |
|
// legacy non-PKCS#8 |
|
var algorithm; |
|
var iv; |
|
var dkLen; |
|
var cipherFn; |
|
switch(options.algorithm){ |
|
case 'aes128': |
|
algorithm = 'AES-128-CBC'; |
|
dkLen = 16; |
|
iv = $iGlOy.random.getBytesSync(16); |
|
cipherFn = $iGlOy.aes.createEncryptionCipher; |
|
break; |
|
case 'aes192': |
|
algorithm = 'AES-192-CBC'; |
|
dkLen = 24; |
|
iv = $iGlOy.random.getBytesSync(16); |
|
cipherFn = $iGlOy.aes.createEncryptionCipher; |
|
break; |
|
case 'aes256': |
|
algorithm = 'AES-256-CBC'; |
|
dkLen = 32; |
|
iv = $iGlOy.random.getBytesSync(16); |
|
cipherFn = $iGlOy.aes.createEncryptionCipher; |
|
break; |
|
case '3des': |
|
algorithm = 'DES-EDE3-CBC'; |
|
dkLen = 24; |
|
iv = $iGlOy.random.getBytesSync(8); |
|
cipherFn = $iGlOy.des.createEncryptionCipher; |
|
break; |
|
case 'des': |
|
algorithm = 'DES-CBC'; |
|
dkLen = 8; |
|
iv = $iGlOy.random.getBytesSync(8); |
|
cipherFn = $iGlOy.des.createEncryptionCipher; |
|
break; |
|
default: |
|
var error = new Error("Could not encrypt RSA private key; unsupported encryption algorithm \"" + options.algorithm + '".'); |
|
error.algorithm = options.algorithm; |
|
throw error; |
|
} |
|
// encrypt private key using OpenSSL legacy key derivation |
|
var dk = $iGlOy.pbe.opensslDeriveBytes(password, iv.substr(0, 8), dkLen); |
|
var cipher = cipherFn(dk); |
|
cipher.start(iv); |
|
cipher.update($4ead143e6089ae29$var$asn1.toDer($4ead143e6089ae29$var$pki.privateKeyToAsn1(rsaKey))); |
|
cipher.finish(); |
|
var msg = { |
|
type: 'RSA PRIVATE KEY', |
|
procType: { |
|
version: '4', |
|
type: 'ENCRYPTED' |
|
}, |
|
dekInfo: { |
|
algorithm: algorithm, |
|
parameters: $iGlOy.util.bytesToHex(iv).toUpperCase() |
|
}, |
|
body: cipher.output.getBytes() |
|
}; |
|
return $iGlOy.pem.encode(msg); |
|
}; |
|
/** |
|
* Decrypts an RSA private key. |
|
* |
|
* @param pem the PEM-formatted EncryptedPrivateKeyInfo to decrypt. |
|
* @param password the password to use. |
|
* |
|
* @return the RSA key on success, null on failure. |
|
*/ $4ead143e6089ae29$var$pki.decryptRsaPrivateKey = function(pem, password) { |
|
var rval = null; |
|
var msg = $iGlOy.pem.decode(pem)[0]; |
|
if (msg.type !== 'ENCRYPTED PRIVATE KEY' && msg.type !== 'PRIVATE KEY' && msg.type !== 'RSA PRIVATE KEY') { |
|
var error = new Error("Could not convert private key from PEM; PEM header type is not \"ENCRYPTED PRIVATE KEY\", \"PRIVATE KEY\", or \"RSA PRIVATE KEY\"."); |
|
error.headerType = error; |
|
throw error; |
|
} |
|
if (msg.procType && msg.procType.type === 'ENCRYPTED') { |
|
var dkLen; |
|
var cipherFn; |
|
switch(msg.dekInfo.algorithm){ |
|
case 'DES-CBC': |
|
dkLen = 8; |
|
cipherFn = $iGlOy.des.createDecryptionCipher; |
|
break; |
|
case 'DES-EDE3-CBC': |
|
dkLen = 24; |
|
cipherFn = $iGlOy.des.createDecryptionCipher; |
|
break; |
|
case 'AES-128-CBC': |
|
dkLen = 16; |
|
cipherFn = $iGlOy.aes.createDecryptionCipher; |
|
break; |
|
case 'AES-192-CBC': |
|
dkLen = 24; |
|
cipherFn = $iGlOy.aes.createDecryptionCipher; |
|
break; |
|
case 'AES-256-CBC': |
|
dkLen = 32; |
|
cipherFn = $iGlOy.aes.createDecryptionCipher; |
|
break; |
|
case 'RC2-40-CBC': |
|
dkLen = 5; |
|
cipherFn = function(key) { |
|
return $iGlOy.rc2.createDecryptionCipher(key, 40); |
|
}; |
|
break; |
|
case 'RC2-64-CBC': |
|
dkLen = 8; |
|
cipherFn = function(key) { |
|
return $iGlOy.rc2.createDecryptionCipher(key, 64); |
|
}; |
|
break; |
|
case 'RC2-128-CBC': |
|
dkLen = 16; |
|
cipherFn = function(key) { |
|
return $iGlOy.rc2.createDecryptionCipher(key, 128); |
|
}; |
|
break; |
|
default: |
|
var error = new Error("Could not decrypt private key; unsupported encryption algorithm \"" + msg.dekInfo.algorithm + '".'); |
|
error.algorithm = msg.dekInfo.algorithm; |
|
throw error; |
|
} |
|
// use OpenSSL legacy key derivation |
|
var iv = $iGlOy.util.hexToBytes(msg.dekInfo.parameters); |
|
var dk = $iGlOy.pbe.opensslDeriveBytes(password, iv.substr(0, 8), dkLen); |
|
var cipher = cipherFn(dk); |
|
cipher.start(iv); |
|
cipher.update($iGlOy.util.createBuffer(msg.body)); |
|
if (cipher.finish()) rval = cipher.output.getBytes(); |
|
else return rval; |
|
} else rval = msg.body; |
|
if (msg.type === 'ENCRYPTED PRIVATE KEY') rval = $4ead143e6089ae29$var$pki.decryptPrivateKeyInfo($4ead143e6089ae29$var$asn1.fromDer(rval), password); |
|
else // decryption already performed above |
|
rval = $4ead143e6089ae29$var$asn1.fromDer(rval); |
|
if (rval !== null) rval = $4ead143e6089ae29$var$pki.privateKeyFromAsn1(rval); |
|
return rval; |
|
}; |
|
/** |
|
* Derives a PKCS#12 key. |
|
* |
|
* @param password the password to derive the key material from, null or |
|
* undefined for none. |
|
* @param salt the salt, as a ByteBuffer, to use. |
|
* @param id the PKCS#12 ID byte (1 = key material, 2 = IV, 3 = MAC). |
|
* @param iter the iteration count. |
|
* @param n the number of bytes to derive from the password. |
|
* @param md the message digest to use, defaults to SHA-1. |
|
* |
|
* @return a ByteBuffer with the bytes derived from the password. |
|
*/ $4ead143e6089ae29$var$pki.pbe.generatePkcs12Key = function(password, salt, id, iter, n, md) { |
|
var j, l; |
|
if (typeof md === 'undefined' || md === null) { |
|
if (!('sha1' in $iGlOy.md)) throw new Error('"sha1" hash algorithm unavailable.'); |
|
md = $iGlOy.md.sha1.create(); |
|
} |
|
var u = md.digestLength; |
|
var v = md.blockLength; |
|
var result = new $iGlOy.util.ByteBuffer(); |
|
/* Convert password to Unicode byte buffer + trailing 0-byte. */ var passBuf = new $iGlOy.util.ByteBuffer(); |
|
if (password !== null && password !== undefined) { |
|
for(l = 0; l < password.length; l++)passBuf.putInt16(password.charCodeAt(l)); |
|
passBuf.putInt16(0); |
|
} |
|
/* Length of salt and password in BYTES. */ var p = passBuf.length(); |
|
var s = salt.length(); |
|
/* 1. Construct a string, D (the "diversifier"), by concatenating |
|
v copies of ID. */ var D = new $iGlOy.util.ByteBuffer(); |
|
D.fillWithByte(id, v); |
|
/* 2. Concatenate copies of the salt together to create a string S of length |
|
v * ceil(s / v) bytes (the final copy of the salt may be trunacted |
|
to create S). |
|
Note that if the salt is the empty string, then so is S. */ var Slen = v * Math.ceil(s / v); |
|
var S = new $iGlOy.util.ByteBuffer(); |
|
for(l = 0; l < Slen; l++)S.putByte(salt.at(l % s)); |
|
/* 3. Concatenate copies of the password together to create a string P of |
|
length v * ceil(p / v) bytes (the final copy of the password may be |
|
truncated to create P). |
|
Note that if the password is the empty string, then so is P. */ var Plen = v * Math.ceil(p / v); |
|
var P = new $iGlOy.util.ByteBuffer(); |
|
for(l = 0; l < Plen; l++)P.putByte(passBuf.at(l % p)); |
|
/* 4. Set I=S||P to be the concatenation of S and P. */ var I = S; |
|
I.putBuffer(P); |
|
/* 5. Set c=ceil(n / u). */ var c = Math.ceil(n / u); |
|
/* 6. For i=1, 2, ..., c, do the following: */ for(var i = 1; i <= c; i++){ |
|
/* a) Set Ai=H^r(D||I). (l.e. the rth hash of D||I, H(H(H(...H(D||I)))) */ var buf = new $iGlOy.util.ByteBuffer(); |
|
buf.putBytes(D.bytes()); |
|
buf.putBytes(I.bytes()); |
|
for(var round = 0; round < iter; round++){ |
|
md.start(); |
|
md.update(buf.getBytes()); |
|
buf = md.digest(); |
|
} |
|
/* b) Concatenate copies of Ai to create a string B of length v bytes (the |
|
final copy of Ai may be truncated to create B). */ var B = new $iGlOy.util.ByteBuffer(); |
|
for(l = 0; l < v; l++)B.putByte(buf.at(l % u)); |
|
/* c) Treating I as a concatenation I0, I1, ..., Ik-1 of v-byte blocks, |
|
where k=ceil(s / v) + ceil(p / v), modify I by setting |
|
Ij=(Ij+B+1) mod 2v for each j. */ var k = Math.ceil(s / v) + Math.ceil(p / v); |
|
var Inew = new $iGlOy.util.ByteBuffer(); |
|
for(j = 0; j < k; j++){ |
|
var chunk = new $iGlOy.util.ByteBuffer(I.getBytes(v)); |
|
var x = 511; |
|
for(l = B.length() - 1; l >= 0; l--){ |
|
x = x >> 8; |
|
x += B.at(l) + chunk.at(l); |
|
chunk.setAt(l, x & 255); |
|
} |
|
Inew.putBuffer(chunk); |
|
} |
|
I = Inew; |
|
/* Add Ai to A. */ result.putBuffer(buf); |
|
} |
|
result.truncate(result.length() - n); |
|
return result; |
|
}; |
|
/** |
|
* Get new Forge cipher object instance. |
|
* |
|
* @param oid the OID (in string notation). |
|
* @param params the ASN.1 params object. |
|
* @param password the password to decrypt with. |
|
* |
|
* @return new cipher object instance. |
|
*/ $4ead143e6089ae29$var$pki.pbe.getCipher = function(oid, params, password) { |
|
switch(oid){ |
|
case $4ead143e6089ae29$var$pki.oids['pkcs5PBES2']: |
|
return $4ead143e6089ae29$var$pki.pbe.getCipherForPBES2(oid, params, password); |
|
case $4ead143e6089ae29$var$pki.oids['pbeWithSHAAnd3-KeyTripleDES-CBC']: |
|
case $4ead143e6089ae29$var$pki.oids['pbewithSHAAnd40BitRC2-CBC']: |
|
return $4ead143e6089ae29$var$pki.pbe.getCipherForPKCS12PBE(oid, params, password); |
|
default: |
|
var error = new Error('Cannot read encrypted PBE data block. Unsupported OID.'); |
|
error.oid = oid; |
|
error.supportedOids = [ |
|
'pkcs5PBES2', |
|
'pbeWithSHAAnd3-KeyTripleDES-CBC', |
|
'pbewithSHAAnd40BitRC2-CBC' |
|
]; |
|
throw error; |
|
} |
|
}; |
|
/** |
|
* Get new Forge cipher object instance according to PBES2 params block. |
|
* |
|
* The returned cipher instance is already started using the IV |
|
* from PBES2 parameter block. |
|
* |
|
* @param oid the PKCS#5 PBKDF2 OID (in string notation). |
|
* @param params the ASN.1 PBES2-params object. |
|
* @param password the password to decrypt with. |
|
* |
|
* @return new cipher object instance. |
|
*/ $4ead143e6089ae29$var$pki.pbe.getCipherForPBES2 = function(oid, params, password) { |
|
// get PBE params |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$4ead143e6089ae29$var$asn1.validate(params, $4ead143e6089ae29$var$PBES2AlgorithmsValidator, capture, errors)) { |
|
var error = new Error("Cannot read password-based-encryption algorithm parameters. ASN.1 object is not a supported EncryptedPrivateKeyInfo."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
// check oids |
|
oid = $4ead143e6089ae29$var$asn1.derToOid(capture.kdfOid); |
|
if (oid !== $4ead143e6089ae29$var$pki.oids['pkcs5PBKDF2']) { |
|
var error = new Error("Cannot read encrypted private key. Unsupported key derivation function OID."); |
|
error.oid = oid; |
|
error.supportedOids = [ |
|
'pkcs5PBKDF2' |
|
]; |
|
throw error; |
|
} |
|
oid = $4ead143e6089ae29$var$asn1.derToOid(capture.encOid); |
|
if (oid !== $4ead143e6089ae29$var$pki.oids['aes128-CBC'] && oid !== $4ead143e6089ae29$var$pki.oids['aes192-CBC'] && oid !== $4ead143e6089ae29$var$pki.oids['aes256-CBC'] && oid !== $4ead143e6089ae29$var$pki.oids['des-EDE3-CBC'] && oid !== $4ead143e6089ae29$var$pki.oids['desCBC']) { |
|
var error = new Error("Cannot read encrypted private key. Unsupported encryption scheme OID."); |
|
error.oid = oid; |
|
error.supportedOids = [ |
|
'aes128-CBC', |
|
'aes192-CBC', |
|
'aes256-CBC', |
|
'des-EDE3-CBC', |
|
'desCBC' |
|
]; |
|
throw error; |
|
} |
|
// set PBE params |
|
var salt = capture.kdfSalt; |
|
var count = $iGlOy.util.createBuffer(capture.kdfIterationCount); |
|
count = count.getInt(count.length() << 3); |
|
var dkLen; |
|
var cipherFn; |
|
switch($4ead143e6089ae29$var$pki.oids[oid]){ |
|
case 'aes128-CBC': |
|
dkLen = 16; |
|
cipherFn = $iGlOy.aes.createDecryptionCipher; |
|
break; |
|
case 'aes192-CBC': |
|
dkLen = 24; |
|
cipherFn = $iGlOy.aes.createDecryptionCipher; |
|
break; |
|
case 'aes256-CBC': |
|
dkLen = 32; |
|
cipherFn = $iGlOy.aes.createDecryptionCipher; |
|
break; |
|
case 'des-EDE3-CBC': |
|
dkLen = 24; |
|
cipherFn = $iGlOy.des.createDecryptionCipher; |
|
break; |
|
case 'desCBC': |
|
dkLen = 8; |
|
cipherFn = $iGlOy.des.createDecryptionCipher; |
|
break; |
|
} |
|
// get PRF message digest |
|
var md = $4ead143e6089ae29$var$prfOidToMessageDigest(capture.prfOid); |
|
// decrypt private key using pbe with chosen PRF and AES/DES |
|
var dk = $iGlOy.pkcs5.pbkdf2(password, salt, count, dkLen, md); |
|
var iv = capture.encIv; |
|
var cipher = cipherFn(dk); |
|
cipher.start(iv); |
|
return cipher; |
|
}; |
|
/** |
|
* Get new Forge cipher object instance for PKCS#12 PBE. |
|
* |
|
* The returned cipher instance is already started using the key & IV |
|
* derived from the provided password and PKCS#12 PBE salt. |
|
* |
|
* @param oid The PKCS#12 PBE OID (in string notation). |
|
* @param params The ASN.1 PKCS#12 PBE-params object. |
|
* @param password The password to decrypt with. |
|
* |
|
* @return the new cipher object instance. |
|
*/ $4ead143e6089ae29$var$pki.pbe.getCipherForPKCS12PBE = function(oid, params, password) { |
|
// get PBE params |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$4ead143e6089ae29$var$asn1.validate(params, $4ead143e6089ae29$var$pkcs12PbeParamsValidator, capture, errors)) { |
|
var error = new Error("Cannot read password-based-encryption algorithm parameters. ASN.1 object is not a supported EncryptedPrivateKeyInfo."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
var salt = $iGlOy.util.createBuffer(capture.salt); |
|
var count = $iGlOy.util.createBuffer(capture.iterations); |
|
count = count.getInt(count.length() << 3); |
|
var dkLen, dIvLen, cipherFn; |
|
switch(oid){ |
|
case $4ead143e6089ae29$var$pki.oids['pbeWithSHAAnd3-KeyTripleDES-CBC']: |
|
dkLen = 24; |
|
dIvLen = 8; |
|
cipherFn = $iGlOy.des.startDecrypting; |
|
break; |
|
case $4ead143e6089ae29$var$pki.oids['pbewithSHAAnd40BitRC2-CBC']: |
|
dkLen = 5; |
|
dIvLen = 8; |
|
cipherFn = function(key, iv) { |
|
var cipher = $iGlOy.rc2.createDecryptionCipher(key, 40); |
|
cipher.start(iv, null); |
|
return cipher; |
|
}; |
|
break; |
|
default: |
|
var error = new Error('Cannot read PKCS #12 PBE data block. Unsupported OID.'); |
|
error.oid = oid; |
|
throw error; |
|
} |
|
// get PRF message digest |
|
var md = $4ead143e6089ae29$var$prfOidToMessageDigest(capture.prfOid); |
|
var key1 = $4ead143e6089ae29$var$pki.pbe.generatePkcs12Key(password, salt, 1, count, dkLen, md); |
|
md.start(); |
|
var iv1 = $4ead143e6089ae29$var$pki.pbe.generatePkcs12Key(password, salt, 2, count, dIvLen, md); |
|
return cipherFn(key1, iv1); |
|
}; |
|
/** |
|
* OpenSSL's legacy key derivation function. |
|
* |
|
* See: http://www.openssl.org/docs/crypto/EVP_BytesToKey.html |
|
* |
|
* @param password the password to derive the key from. |
|
* @param salt the salt to use, null for none. |
|
* @param dkLen the number of bytes needed for the derived key. |
|
* @param [options] the options to use: |
|
* [md] an optional message digest object to use. |
|
*/ $4ead143e6089ae29$var$pki.pbe.opensslDeriveBytes = function(password, salt, dkLen, md) { |
|
if (typeof md === 'undefined' || md === null) { |
|
if (!('md5' in $iGlOy.md)) throw new Error('"md5" hash algorithm unavailable.'); |
|
md = $iGlOy.md.md5.create(); |
|
} |
|
if (salt === null) salt = ''; |
|
var digests = [ |
|
$4ead143e6089ae29$var$hash(md, password + salt) |
|
]; |
|
for(var length = 16, i = 1; length < dkLen; ++i, length += 16)digests.push($4ead143e6089ae29$var$hash(md, digests[i - 1] + password + salt)); |
|
return digests.join('').substr(0, dkLen); |
|
}; |
|
function $4ead143e6089ae29$var$hash(md, bytes) { |
|
return md.start().update(bytes).digest().getBytes(); |
|
} |
|
function $4ead143e6089ae29$var$prfOidToMessageDigest(prfOid) { |
|
// get PRF algorithm, default to SHA-1 |
|
var prfAlgorithm; |
|
if (!prfOid) prfAlgorithm = 'hmacWithSHA1'; |
|
else { |
|
prfAlgorithm = $4ead143e6089ae29$var$pki.oids[$4ead143e6089ae29$var$asn1.derToOid(prfOid)]; |
|
if (!prfAlgorithm) { |
|
var error = new Error('Unsupported PRF OID.'); |
|
error.oid = prfOid; |
|
error.supported = [ |
|
'hmacWithSHA1', |
|
'hmacWithSHA224', |
|
'hmacWithSHA256', |
|
'hmacWithSHA384', |
|
'hmacWithSHA512' |
|
]; |
|
throw error; |
|
} |
|
} |
|
return $4ead143e6089ae29$var$prfAlgorithmToMessageDigest(prfAlgorithm); |
|
} |
|
function $4ead143e6089ae29$var$prfAlgorithmToMessageDigest(prfAlgorithm) { |
|
var factory = $iGlOy.md; |
|
switch(prfAlgorithm){ |
|
case 'hmacWithSHA224': |
|
factory = $iGlOy.md.sha512; |
|
case 'hmacWithSHA1': |
|
case 'hmacWithSHA256': |
|
case 'hmacWithSHA384': |
|
case 'hmacWithSHA512': |
|
prfAlgorithm = prfAlgorithm.substr(8).toLowerCase(); |
|
break; |
|
default: |
|
var error = new Error('Unsupported PRF algorithm.'); |
|
error.algorithm = prfAlgorithm; |
|
error.supported = [ |
|
'hmacWithSHA1', |
|
'hmacWithSHA224', |
|
'hmacWithSHA256', |
|
'hmacWithSHA384', |
|
'hmacWithSHA512' |
|
]; |
|
throw error; |
|
} |
|
if (!factory || !(prfAlgorithm in factory)) throw new Error('Unknown hash algorithm: ' + prfAlgorithm); |
|
return factory[prfAlgorithm].create(); |
|
} |
|
function $4ead143e6089ae29$var$createPbkdf2Params(salt, countBytes, dkLen, prfAlgorithm) { |
|
var params = $4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.SEQUENCE, true, [ |
|
// salt |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.OCTETSTRING, false, salt), |
|
// iteration count |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.INTEGER, false, countBytes.getBytes()) |
|
]); |
|
// when PRF algorithm is not SHA-1 default, add key length and PRF algorithm |
|
if (prfAlgorithm !== 'hmacWithSHA1') params.value.push(// key length |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.INTEGER, false, $iGlOy.util.hexToBytes(dkLen.toString(16))), // AlgorithmIdentifier |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.SEQUENCE, true, [ |
|
// algorithm |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.OID, false, $4ead143e6089ae29$var$asn1.oidToDer($4ead143e6089ae29$var$pki.oids[prfAlgorithm]).getBytes()), |
|
// parameters (null) |
|
$4ead143e6089ae29$var$asn1.create($4ead143e6089ae29$var$asn1.Class.UNIVERSAL, $4ead143e6089ae29$var$asn1.Type.NULL, false, '') |
|
])); |
|
return params; |
|
} |
|
|
|
|
|
|
|
|
|
var $6fcb727b03413917$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
|
|
var $a5c085c32c6e5e1a$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
// shortcut for ASN.1 API |
|
var $a5c085c32c6e5e1a$var$asn1 = $iGlOy.asn1; |
|
// shortcut for PKCS#7 API |
|
var $a5c085c32c6e5e1a$var$p7v = $a5c085c32c6e5e1a$exports = $iGlOy.pkcs7asn1 = $iGlOy.pkcs7asn1 || { |
|
}; |
|
$iGlOy.pkcs7 = $iGlOy.pkcs7 || { |
|
}; |
|
$iGlOy.pkcs7.asn1 = $a5c085c32c6e5e1a$var$p7v; |
|
var $a5c085c32c6e5e1a$var$contentInfoValidator = { |
|
name: 'ContentInfo', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'ContentInfo.ContentType', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'contentType' |
|
}, |
|
{ |
|
name: 'ContentInfo.content', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 0, |
|
constructed: true, |
|
optional: true, |
|
captureAsn1: 'content' |
|
} |
|
] |
|
}; |
|
$a5c085c32c6e5e1a$var$p7v.contentInfoValidator = $a5c085c32c6e5e1a$var$contentInfoValidator; |
|
var $a5c085c32c6e5e1a$var$encryptedContentInfoValidator = { |
|
name: 'EncryptedContentInfo', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'EncryptedContentInfo.contentType', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'contentType' |
|
}, |
|
{ |
|
name: 'EncryptedContentInfo.contentEncryptionAlgorithm', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'EncryptedContentInfo.contentEncryptionAlgorithm.algorithm', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'encAlgorithm' |
|
}, |
|
{ |
|
name: 'EncryptedContentInfo.contentEncryptionAlgorithm.parameter', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
captureAsn1: 'encParameter' |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'EncryptedContentInfo.encryptedContent', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 0, |
|
/* The PKCS#7 structure output by OpenSSL somewhat differs from what |
|
* other implementations do generate. |
|
* |
|
* OpenSSL generates a structure like this: |
|
* SEQUENCE { |
|
* ... |
|
* [0] |
|
* 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38 |
|
* C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45 |
|
* ... |
|
* } |
|
* |
|
* Whereas other implementations (and this PKCS#7 module) generate: |
|
* SEQUENCE { |
|
* ... |
|
* [0] { |
|
* OCTET STRING |
|
* 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38 |
|
* C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45 |
|
* ... |
|
* } |
|
* } |
|
* |
|
* In order to support both, we just capture the context specific |
|
* field here. The OCTET STRING bit is removed below. |
|
*/ capture: 'encryptedContent', |
|
captureAsn1: 'encryptedContentAsn1' |
|
} |
|
] |
|
}; |
|
$a5c085c32c6e5e1a$var$p7v.envelopedDataValidator = { |
|
name: 'EnvelopedData', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'EnvelopedData.Version', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'version' |
|
}, |
|
{ |
|
name: 'EnvelopedData.RecipientInfos', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SET, |
|
constructed: true, |
|
captureAsn1: 'recipientInfos' |
|
} |
|
].concat($a5c085c32c6e5e1a$var$encryptedContentInfoValidator) |
|
}; |
|
$a5c085c32c6e5e1a$var$p7v.encryptedDataValidator = { |
|
name: 'EncryptedData', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'EncryptedData.Version', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'version' |
|
} |
|
].concat($a5c085c32c6e5e1a$var$encryptedContentInfoValidator) |
|
}; |
|
var $a5c085c32c6e5e1a$var$signerValidator = { |
|
name: 'SignerInfo', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'SignerInfo.version', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.INTEGER, |
|
constructed: false |
|
}, |
|
{ |
|
name: 'SignerInfo.issuerAndSerialNumber', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'SignerInfo.issuerAndSerialNumber.issuer', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'issuer' |
|
}, |
|
{ |
|
name: 'SignerInfo.issuerAndSerialNumber.serialNumber', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'serial' |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'SignerInfo.digestAlgorithm', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'SignerInfo.digestAlgorithm.algorithm', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'digestAlgorithm' |
|
}, |
|
{ |
|
name: 'SignerInfo.digestAlgorithm.parameter', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
constructed: false, |
|
captureAsn1: 'digestParameter', |
|
optional: true |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'SignerInfo.authenticatedAttributes', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 0, |
|
constructed: true, |
|
optional: true, |
|
capture: 'authenticatedAttributes' |
|
}, |
|
{ |
|
name: 'SignerInfo.digestEncryptionAlgorithm', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
capture: 'signatureAlgorithm' |
|
}, |
|
{ |
|
name: 'SignerInfo.encryptedDigest', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'signature' |
|
}, |
|
{ |
|
name: 'SignerInfo.unauthenticatedAttributes', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 1, |
|
constructed: true, |
|
optional: true, |
|
capture: 'unauthenticatedAttributes' |
|
} |
|
] |
|
}; |
|
$a5c085c32c6e5e1a$var$p7v.signedDataValidator = { |
|
name: 'SignedData', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'SignedData.Version', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'version' |
|
}, |
|
{ |
|
name: 'SignedData.DigestAlgorithms', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SET, |
|
constructed: true, |
|
captureAsn1: 'digestAlgorithms' |
|
}, |
|
$a5c085c32c6e5e1a$var$contentInfoValidator, |
|
{ |
|
name: 'SignedData.Certificates', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 0, |
|
optional: true, |
|
captureAsn1: 'certificates' |
|
}, |
|
{ |
|
name: 'SignedData.CertificateRevocationLists', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 1, |
|
optional: true, |
|
captureAsn1: 'crls' |
|
}, |
|
{ |
|
name: 'SignedData.SignerInfos', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SET, |
|
capture: 'signerInfos', |
|
optional: true, |
|
value: [ |
|
$a5c085c32c6e5e1a$var$signerValidator |
|
] |
|
} |
|
] |
|
}; |
|
$a5c085c32c6e5e1a$var$p7v.recipientInfoValidator = { |
|
name: 'RecipientInfo', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'RecipientInfo.version', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'version' |
|
}, |
|
{ |
|
name: 'RecipientInfo.issuerAndSerial', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'RecipientInfo.issuerAndSerial.issuer', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'issuer' |
|
}, |
|
{ |
|
name: 'RecipientInfo.issuerAndSerial.serialNumber', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'serial' |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'RecipientInfo.keyEncryptionAlgorithm', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'RecipientInfo.keyEncryptionAlgorithm.algorithm', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'encAlgorithm' |
|
}, |
|
{ |
|
name: 'RecipientInfo.keyEncryptionAlgorithm.parameter', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
constructed: false, |
|
captureAsn1: 'encParameter', |
|
optional: true |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'RecipientInfo.encryptedKey', |
|
tagClass: $a5c085c32c6e5e1a$var$asn1.Class.UNIVERSAL, |
|
type: $a5c085c32c6e5e1a$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'encKey' |
|
} |
|
] |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var $f71d929f259208f7$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
|
|
parcelRequire("ai0Z9"); |
|
var $c01d1f977f850a49$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
var $1a758e61c98aa2f6$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
$iGlOy.mgf = $iGlOy.mgf || { |
|
}; |
|
var $1a758e61c98aa2f6$var$mgf1 = $1a758e61c98aa2f6$exports = $iGlOy.mgf.mgf1 = $iGlOy.mgf1 = $iGlOy.mgf1 || { |
|
}; |
|
/** |
|
* Creates a MGF1 mask generation function object. |
|
* |
|
* @param md the message digest API to use (eg: forge.md.sha1.create()). |
|
* |
|
* @return a mask generation function object. |
|
*/ $1a758e61c98aa2f6$var$mgf1.create = function(md) { |
|
var mgf = { |
|
/** |
|
* Generate mask of specified length. |
|
* |
|
* @param {String} seed The seed for mask generation. |
|
* @param maskLen Number of bytes to generate. |
|
* @return {String} The generated mask. |
|
*/ generate: function(seed, maskLen) { |
|
/* 2. Let T be the empty octet string. */ var t = new $iGlOy.util.ByteBuffer(); |
|
/* 3. For counter from 0 to ceil(maskLen / hLen), do the following: */ var len = Math.ceil(maskLen / md.digestLength); |
|
for(var i = 0; i < len; i++){ |
|
/* a. Convert counter to an octet string C of length 4 octets */ var c = new $iGlOy.util.ByteBuffer(); |
|
c.putInt32(i); |
|
/* b. Concatenate the hash of the seed mgfSeed and C to the octet |
|
* string T: */ md.start(); |
|
md.update(seed + c.getBytes()); |
|
t.putBuffer(md.digest()); |
|
} |
|
/* Output the leading maskLen octets of T as the octet string mask. */ t.truncate(t.length() - maskLen); |
|
return t.getBytes(); |
|
} |
|
}; |
|
return mgf; |
|
}; |
|
|
|
|
|
$c01d1f977f850a49$exports = $iGlOy.mgf = $iGlOy.mgf || { |
|
}; |
|
$iGlOy.mgf.mgf1 = $iGlOy.mgf1; |
|
|
|
|
|
|
|
|
|
var $6aa068716df79957$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
// shortcut for PSS API |
|
var $6aa068716df79957$var$pss = $6aa068716df79957$exports = $iGlOy.pss = $iGlOy.pss || { |
|
}; |
|
/** |
|
* Creates a PSS signature scheme object. |
|
* |
|
* There are several ways to provide a salt for encoding: |
|
* |
|
* 1. Specify the saltLength only and the built-in PRNG will generate it. |
|
* 2. Specify the saltLength and a custom PRNG with 'getBytesSync' defined that |
|
* will be used. |
|
* 3. Specify the salt itself as a forge.util.ByteBuffer. |
|
* |
|
* @param options the options to use: |
|
* md the message digest object to use, a forge md instance. |
|
* mgf the mask generation function to use, a forge mgf instance. |
|
* [saltLength] the length of the salt in octets. |
|
* [prng] the pseudo-random number generator to use to produce a salt. |
|
* [salt] the salt to use when encoding. |
|
* |
|
* @return a signature scheme object. |
|
*/ $6aa068716df79957$var$pss.create = function(options) { |
|
// backwards compatibility w/legacy args: hash, mgf, sLen |
|
if (arguments.length === 3) options = { |
|
md: arguments[0], |
|
mgf: arguments[1], |
|
saltLength: arguments[2] |
|
}; |
|
var hash = options.md; |
|
var mgf = options.mgf; |
|
var hLen = hash.digestLength; |
|
var salt_ = options.salt || null; |
|
if (typeof salt_ === 'string') // assume binary-encoded string |
|
salt_ = $iGlOy.util.createBuffer(salt_); |
|
var sLen; |
|
if ('saltLength' in options) sLen = options.saltLength; |
|
else if (salt_ !== null) sLen = salt_.length(); |
|
else throw new Error('Salt length not specified or specific salt not given.'); |
|
if (salt_ !== null && salt_.length() !== sLen) throw new Error('Given salt length does not match length of given salt.'); |
|
var prng = options.prng || $iGlOy.random; |
|
var pssobj = { |
|
}; |
|
/** |
|
* Encodes a PSS signature. |
|
* |
|
* This function implements EMSA-PSS-ENCODE as per RFC 3447, section 9.1.1. |
|
* |
|
* @param md the message digest object with the hash to sign. |
|
* @param modsBits the length of the RSA modulus in bits. |
|
* |
|
* @return the encoded message as a binary-encoded string of length |
|
* ceil((modBits - 1) / 8). |
|
*/ pssobj.encode = function(md, modBits) { |
|
var i; |
|
var emBits = modBits - 1; |
|
var emLen = Math.ceil(emBits / 8); |
|
/* 2. Let mHash = Hash(M), an octet string of length hLen. */ var mHash = md.digest().getBytes(); |
|
/* 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. */ if (emLen < hLen + sLen + 2) throw new Error('Message is too long to encrypt.'); |
|
/* 4. Generate a random octet string salt of length sLen; if sLen = 0, |
|
* then salt is the empty string. */ var salt; |
|
if (salt_ === null) salt = prng.getBytesSync(sLen); |
|
else salt = salt_.bytes(); |
|
/* 5. Let M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt; */ var m_ = new $iGlOy.util.ByteBuffer(); |
|
m_.fillWithByte(0, 8); |
|
m_.putBytes(mHash); |
|
m_.putBytes(salt); |
|
/* 6. Let H = Hash(M'), an octet string of length hLen. */ hash.start(); |
|
hash.update(m_.getBytes()); |
|
var h = hash.digest().getBytes(); |
|
/* 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2 |
|
* zero octets. The length of PS may be 0. */ var ps = new $iGlOy.util.ByteBuffer(); |
|
ps.fillWithByte(0, emLen - sLen - hLen - 2); |
|
/* 8. Let DB = PS || 0x01 || salt; DB is an octet string of length |
|
* emLen - hLen - 1. */ ps.putByte(1); |
|
ps.putBytes(salt); |
|
var db = ps.getBytes(); |
|
/* 9. Let dbMask = MGF(H, emLen - hLen - 1). */ var maskLen = emLen - hLen - 1; |
|
var dbMask = mgf.generate(h, maskLen); |
|
/* 10. Let maskedDB = DB \xor dbMask. */ var maskedDB = ''; |
|
for(i = 0; i < maskLen; i++)maskedDB += String.fromCharCode(db.charCodeAt(i) ^ dbMask.charCodeAt(i)); |
|
/* 11. Set the leftmost 8emLen - emBits bits of the leftmost octet in |
|
* maskedDB to zero. */ var mask = 65280 >> 8 * emLen - emBits & 255; |
|
maskedDB = String.fromCharCode(maskedDB.charCodeAt(0) & ~mask) + maskedDB.substr(1); |
|
/* 12. Let EM = maskedDB || H || 0xbc. |
|
* 13. Output EM. */ return maskedDB + h + String.fromCharCode(188); |
|
}; |
|
/** |
|
* Verifies a PSS signature. |
|
* |
|
* This function implements EMSA-PSS-VERIFY as per RFC 3447, section 9.1.2. |
|
* |
|
* @param mHash the message digest hash, as a binary-encoded string, to |
|
* compare against the signature. |
|
* @param em the encoded message, as a binary-encoded string |
|
* (RSA decryption result). |
|
* @param modsBits the length of the RSA modulus in bits. |
|
* |
|
* @return true if the signature was verified, false if not. |
|
*/ pssobj.verify = function(mHash, em, modBits) { |
|
var i; |
|
var emBits = modBits - 1; |
|
var emLen = Math.ceil(emBits / 8); |
|
/* c. Convert the message representative m to an encoded message EM |
|
* of length emLen = ceil((modBits - 1) / 8) octets, where modBits |
|
* is the length in bits of the RSA modulus n */ em = em.substr(-emLen); |
|
/* 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. */ if (emLen < hLen + sLen + 2) throw new Error('Inconsistent parameters to PSS signature verification.'); |
|
/* 4. If the rightmost octet of EM does not have hexadecimal value |
|
* 0xbc, output "inconsistent" and stop. */ if (em.charCodeAt(emLen - 1) !== 188) throw new Error('Encoded message does not end in 0xBC.'); |
|
/* 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and |
|
* let H be the next hLen octets. */ var maskLen = emLen - hLen - 1; |
|
var maskedDB = em.substr(0, maskLen); |
|
var h = em.substr(maskLen, hLen); |
|
/* 6. If the leftmost 8emLen - emBits bits of the leftmost octet in |
|
* maskedDB are not all equal to zero, output "inconsistent" and stop. */ var mask = 65280 >> 8 * emLen - emBits & 255; |
|
if ((maskedDB.charCodeAt(0) & mask) !== 0) throw new Error('Bits beyond keysize not zero as expected.'); |
|
/* 7. Let dbMask = MGF(H, emLen - hLen - 1). */ var dbMask = mgf.generate(h, maskLen); |
|
/* 8. Let DB = maskedDB \xor dbMask. */ var db = ''; |
|
for(i = 0; i < maskLen; i++)db += String.fromCharCode(maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i)); |
|
/* 9. Set the leftmost 8emLen - emBits bits of the leftmost octet |
|
* in DB to zero. */ db = String.fromCharCode(db.charCodeAt(0) & ~mask) + db.substr(1); |
|
/* 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero |
|
* or if the octet at position emLen - hLen - sLen - 1 (the leftmost |
|
* position is "position 1") does not have hexadecimal value 0x01, |
|
* output "inconsistent" and stop. */ var checkLen = emLen - hLen - sLen - 2; |
|
for(i = 0; i < checkLen; i++){ |
|
if (db.charCodeAt(i) !== 0) throw new Error('Leftmost octets not zero as expected'); |
|
} |
|
if (db.charCodeAt(checkLen) !== 1) throw new Error('Inconsistent PSS signature, 0x01 marker not found'); |
|
/* 11. Let salt be the last sLen octets of DB. */ var salt = db.substr(-sLen); |
|
/* 12. Let M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt */ var m_ = new $iGlOy.util.ByteBuffer(); |
|
m_.fillWithByte(0, 8); |
|
m_.putBytes(mHash); |
|
m_.putBytes(salt); |
|
/* 13. Let H' = Hash(M'), an octet string of length hLen. */ hash.start(); |
|
hash.update(m_.getBytes()); |
|
var h_ = hash.digest().getBytes(); |
|
/* 14. If H = H', output "consistent." Otherwise, output "inconsistent." */ return h === h_; |
|
}; |
|
return pssobj; |
|
}; |
|
|
|
|
|
|
|
|
|
// shortcut for asn.1 API |
|
var $f71d929f259208f7$var$asn1 = $iGlOy.asn1; |
|
/* Public Key Infrastructure (PKI) implementation. */ var $f71d929f259208f7$var$pki = $f71d929f259208f7$exports = $iGlOy.pki = $iGlOy.pki || { |
|
}; |
|
var $f71d929f259208f7$var$oids = $f71d929f259208f7$var$pki.oids; |
|
// short name OID mappings |
|
var $f71d929f259208f7$var$_shortNames = { |
|
}; |
|
$f71d929f259208f7$var$_shortNames['CN'] = $f71d929f259208f7$var$oids['commonName']; |
|
$f71d929f259208f7$var$_shortNames['commonName'] = 'CN'; |
|
$f71d929f259208f7$var$_shortNames['C'] = $f71d929f259208f7$var$oids['countryName']; |
|
$f71d929f259208f7$var$_shortNames['countryName'] = 'C'; |
|
$f71d929f259208f7$var$_shortNames['L'] = $f71d929f259208f7$var$oids['localityName']; |
|
$f71d929f259208f7$var$_shortNames['localityName'] = 'L'; |
|
$f71d929f259208f7$var$_shortNames['ST'] = $f71d929f259208f7$var$oids['stateOrProvinceName']; |
|
$f71d929f259208f7$var$_shortNames['stateOrProvinceName'] = 'ST'; |
|
$f71d929f259208f7$var$_shortNames['O'] = $f71d929f259208f7$var$oids['organizationName']; |
|
$f71d929f259208f7$var$_shortNames['organizationName'] = 'O'; |
|
$f71d929f259208f7$var$_shortNames['OU'] = $f71d929f259208f7$var$oids['organizationalUnitName']; |
|
$f71d929f259208f7$var$_shortNames['organizationalUnitName'] = 'OU'; |
|
$f71d929f259208f7$var$_shortNames['E'] = $f71d929f259208f7$var$oids['emailAddress']; |
|
$f71d929f259208f7$var$_shortNames['emailAddress'] = 'E'; |
|
// validator for an SubjectPublicKeyInfo structure |
|
// Note: Currently only works with an RSA public key |
|
var $f71d929f259208f7$var$publicKeyValidator = $iGlOy.pki.rsa.publicKeyValidator; |
|
// validator for an X.509v3 certificate |
|
var $f71d929f259208f7$var$x509CertificateValidator = { |
|
name: 'Certificate', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'Certificate.TBSCertificate', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'tbsCertificate', |
|
value: [ |
|
{ |
|
name: 'Certificate.TBSCertificate.version', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 0, |
|
constructed: true, |
|
optional: true, |
|
value: [ |
|
{ |
|
name: 'Certificate.TBSCertificate.version.integer', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'certVersion' |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'Certificate.TBSCertificate.serialNumber', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'certSerialNumber' |
|
}, |
|
{ |
|
name: 'Certificate.TBSCertificate.signature', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'Certificate.TBSCertificate.signature.algorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'certinfoSignatureOid' |
|
}, |
|
{ |
|
name: 'Certificate.TBSCertificate.signature.parameters', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
optional: true, |
|
captureAsn1: 'certinfoSignatureParams' |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'Certificate.TBSCertificate.issuer', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'certIssuer' |
|
}, |
|
{ |
|
name: 'Certificate.TBSCertificate.validity', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
// Note: UTC and generalized times may both appear so the capture |
|
// names are based on their detected order, the names used below |
|
// are only for the common case, which validity time really means |
|
// "notBefore" and which means "notAfter" will be determined by order |
|
value: [ |
|
{ |
|
// notBefore (Time) (UTC time case) |
|
name: 'Certificate.TBSCertificate.validity.notBefore (utc)', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.UTCTIME, |
|
constructed: false, |
|
optional: true, |
|
capture: 'certValidity1UTCTime' |
|
}, |
|
{ |
|
// notBefore (Time) (generalized time case) |
|
name: 'Certificate.TBSCertificate.validity.notBefore (generalized)', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.GENERALIZEDTIME, |
|
constructed: false, |
|
optional: true, |
|
capture: 'certValidity2GeneralizedTime' |
|
}, |
|
{ |
|
// notAfter (Time) (only UTC time is supported) |
|
name: 'Certificate.TBSCertificate.validity.notAfter (utc)', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.UTCTIME, |
|
constructed: false, |
|
optional: true, |
|
capture: 'certValidity3UTCTime' |
|
}, |
|
{ |
|
// notAfter (Time) (only UTC time is supported) |
|
name: 'Certificate.TBSCertificate.validity.notAfter (generalized)', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.GENERALIZEDTIME, |
|
constructed: false, |
|
optional: true, |
|
capture: 'certValidity4GeneralizedTime' |
|
} |
|
] |
|
}, |
|
{ |
|
// Name (subject) (RDNSequence) |
|
name: 'Certificate.TBSCertificate.subject', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'certSubject' |
|
}, |
|
// SubjectPublicKeyInfo |
|
$f71d929f259208f7$var$publicKeyValidator, |
|
{ |
|
// issuerUniqueID (optional) |
|
name: 'Certificate.TBSCertificate.issuerUniqueID', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 1, |
|
constructed: true, |
|
optional: true, |
|
value: [ |
|
{ |
|
name: 'Certificate.TBSCertificate.issuerUniqueID.id', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.BITSTRING, |
|
constructed: false, |
|
// TODO: support arbitrary bit length ids |
|
captureBitStringValue: 'certIssuerUniqueId' |
|
} |
|
] |
|
}, |
|
{ |
|
// subjectUniqueID (optional) |
|
name: 'Certificate.TBSCertificate.subjectUniqueID', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 2, |
|
constructed: true, |
|
optional: true, |
|
value: [ |
|
{ |
|
name: 'Certificate.TBSCertificate.subjectUniqueID.id', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.BITSTRING, |
|
constructed: false, |
|
// TODO: support arbitrary bit length ids |
|
captureBitStringValue: 'certSubjectUniqueId' |
|
} |
|
] |
|
}, |
|
{ |
|
// Extensions (optional) |
|
name: 'Certificate.TBSCertificate.extensions', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 3, |
|
constructed: true, |
|
captureAsn1: 'certExtensions', |
|
optional: true |
|
} |
|
] |
|
}, |
|
{ |
|
// AlgorithmIdentifier (signature algorithm) |
|
name: 'Certificate.signatureAlgorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
// algorithm |
|
name: 'Certificate.signatureAlgorithm.algorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'certSignatureOid' |
|
}, |
|
{ |
|
name: 'Certificate.TBSCertificate.signature.parameters', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
optional: true, |
|
captureAsn1: 'certSignatureParams' |
|
} |
|
] |
|
}, |
|
{ |
|
// SignatureValue |
|
name: 'Certificate.signatureValue', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.BITSTRING, |
|
constructed: false, |
|
captureBitStringValue: 'certSignature' |
|
} |
|
] |
|
}; |
|
var $f71d929f259208f7$var$rsassaPssParameterValidator = { |
|
name: 'rsapss', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'rsapss.hashAlgorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 0, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'rsapss.hashAlgorithm.AlgorithmIdentifier', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Class.SEQUENCE, |
|
constructed: true, |
|
optional: true, |
|
value: [ |
|
{ |
|
name: 'rsapss.hashAlgorithm.AlgorithmIdentifier.algorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'hashOid' |
|
} |
|
] |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'rsapss.maskGenAlgorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 1, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Class.SEQUENCE, |
|
constructed: true, |
|
optional: true, |
|
value: [ |
|
{ |
|
name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.algorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'maskGenOid' |
|
}, |
|
{ |
|
name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.params', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.params.algorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'maskGenHashOid' |
|
} |
|
] |
|
} |
|
] |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'rsapss.saltLength', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 2, |
|
optional: true, |
|
value: [ |
|
{ |
|
name: 'rsapss.saltLength.saltLength', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Class.INTEGER, |
|
constructed: false, |
|
capture: 'saltLength' |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'rsapss.trailerField', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 3, |
|
optional: true, |
|
value: [ |
|
{ |
|
name: 'rsapss.trailer.trailer', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Class.INTEGER, |
|
constructed: false, |
|
capture: 'trailer' |
|
} |
|
] |
|
} |
|
] |
|
}; |
|
// validator for a CertificationRequestInfo structure |
|
var $f71d929f259208f7$var$certificationRequestInfoValidator = { |
|
name: 'CertificationRequestInfo', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'certificationRequestInfo', |
|
value: [ |
|
{ |
|
name: 'CertificationRequestInfo.integer', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'certificationRequestInfoVersion' |
|
}, |
|
{ |
|
// Name (subject) (RDNSequence) |
|
name: 'CertificationRequestInfo.subject', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'certificationRequestInfoSubject' |
|
}, |
|
// SubjectPublicKeyInfo |
|
$f71d929f259208f7$var$publicKeyValidator, |
|
{ |
|
name: 'CertificationRequestInfo.attributes', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, |
|
type: 0, |
|
constructed: true, |
|
optional: true, |
|
capture: 'certificationRequestInfoAttributes', |
|
value: [ |
|
{ |
|
name: 'CertificationRequestInfo.attributes', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'CertificationRequestInfo.attributes.type', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.OID, |
|
constructed: false |
|
}, |
|
{ |
|
name: 'CertificationRequestInfo.attributes.value', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SET, |
|
constructed: true |
|
} |
|
] |
|
} |
|
] |
|
} |
|
] |
|
}; |
|
// validator for a CertificationRequest structure |
|
var $f71d929f259208f7$var$certificationRequestValidator = { |
|
name: 'CertificationRequest', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'csr', |
|
value: [ |
|
$f71d929f259208f7$var$certificationRequestInfoValidator, |
|
{ |
|
// AlgorithmIdentifier (signature algorithm) |
|
name: 'CertificationRequest.signatureAlgorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
// algorithm |
|
name: 'CertificationRequest.signatureAlgorithm.algorithm', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'csrSignatureOid' |
|
}, |
|
{ |
|
name: 'CertificationRequest.signatureAlgorithm.parameters', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
optional: true, |
|
captureAsn1: 'csrSignatureParams' |
|
} |
|
] |
|
}, |
|
{ |
|
// signature |
|
name: 'CertificationRequest.signature', |
|
tagClass: $f71d929f259208f7$var$asn1.Class.UNIVERSAL, |
|
type: $f71d929f259208f7$var$asn1.Type.BITSTRING, |
|
constructed: false, |
|
captureBitStringValue: 'csrSignature' |
|
} |
|
] |
|
}; |
|
/** |
|
* Converts an RDNSequence of ASN.1 DER-encoded RelativeDistinguishedName |
|
* sets into an array with objects that have type and value properties. |
|
* |
|
* @param rdn the RDNSequence to convert. |
|
* @param md a message digest to append type and value to if provided. |
|
*/ $f71d929f259208f7$var$pki.RDNAttributesAsArray = function(rdn, md) { |
|
var rval = []; |
|
// each value in 'rdn' in is a SET of RelativeDistinguishedName |
|
var set, attr, obj; |
|
for(var si = 0; si < rdn.value.length; ++si){ |
|
// get the RelativeDistinguishedName set |
|
set = rdn.value[si]; |
|
// each value in the SET is an AttributeTypeAndValue sequence |
|
// containing first a type (an OID) and second a value (defined by |
|
// the OID) |
|
for(var i = 0; i < set.value.length; ++i){ |
|
obj = { |
|
}; |
|
attr = set.value[i]; |
|
obj.type = $f71d929f259208f7$var$asn1.derToOid(attr.value[0].value); |
|
obj.value = attr.value[1].value; |
|
obj.valueTagClass = attr.value[1].type; |
|
// if the OID is known, get its name and short name |
|
if (obj.type in $f71d929f259208f7$var$oids) { |
|
obj.name = $f71d929f259208f7$var$oids[obj.type]; |
|
if (obj.name in $f71d929f259208f7$var$_shortNames) obj.shortName = $f71d929f259208f7$var$_shortNames[obj.name]; |
|
} |
|
if (md) { |
|
md.update(obj.type); |
|
md.update(obj.value); |
|
} |
|
rval.push(obj); |
|
} |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Converts ASN.1 CRIAttributes into an array with objects that have type and |
|
* value properties. |
|
* |
|
* @param attributes the CRIAttributes to convert. |
|
*/ $f71d929f259208f7$var$pki.CRIAttributesAsArray = function(attributes) { |
|
var rval = []; |
|
// each value in 'attributes' in is a SEQUENCE with an OID and a SET |
|
for(var si = 0; si < attributes.length; ++si){ |
|
// get the attribute sequence |
|
var seq = attributes[si]; |
|
// each value in the SEQUENCE containing first a type (an OID) and |
|
// second a set of values (defined by the OID) |
|
var type = $f71d929f259208f7$var$asn1.derToOid(seq.value[0].value); |
|
var values = seq.value[1].value; |
|
for(var vi = 0; vi < values.length; ++vi){ |
|
var obj = { |
|
}; |
|
obj.type = type; |
|
obj.value = values[vi].value; |
|
obj.valueTagClass = values[vi].type; |
|
// if the OID is known, get its name and short name |
|
if (obj.type in $f71d929f259208f7$var$oids) { |
|
obj.name = $f71d929f259208f7$var$oids[obj.type]; |
|
if (obj.name in $f71d929f259208f7$var$_shortNames) obj.shortName = $f71d929f259208f7$var$_shortNames[obj.name]; |
|
} |
|
// parse extensions |
|
if (obj.type === $f71d929f259208f7$var$oids.extensionRequest) { |
|
obj.extensions = []; |
|
for(var ei = 0; ei < obj.value.length; ++ei)obj.extensions.push($f71d929f259208f7$var$pki.certificateExtensionFromAsn1(obj.value[ei])); |
|
} |
|
rval.push(obj); |
|
} |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Gets an issuer or subject attribute from its name, type, or short name. |
|
* |
|
* @param obj the issuer or subject object. |
|
* @param options a short name string or an object with: |
|
* shortName the short name for the attribute. |
|
* name the name for the attribute. |
|
* type the type for the attribute. |
|
* |
|
* @return the attribute. |
|
*/ function $f71d929f259208f7$var$_getAttribute(obj, options) { |
|
if (typeof options === 'string') options = { |
|
shortName: options |
|
}; |
|
var rval = null; |
|
var attr; |
|
for(var i = 0; rval === null && i < obj.attributes.length; ++i){ |
|
attr = obj.attributes[i]; |
|
if (options.type && options.type === attr.type) rval = attr; |
|
else if (options.name && options.name === attr.name) rval = attr; |
|
else if (options.shortName && options.shortName === attr.shortName) rval = attr; |
|
} |
|
return rval; |
|
} |
|
/** |
|
* Converts signature parameters from ASN.1 structure. |
|
* |
|
* Currently only RSASSA-PSS supported. The PKCS#1 v1.5 signature scheme had |
|
* no parameters. |
|
* |
|
* RSASSA-PSS-params ::= SEQUENCE { |
|
* hashAlgorithm [0] HashAlgorithm DEFAULT |
|
* sha1Identifier, |
|
* maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT |
|
* mgf1SHA1Identifier, |
|
* saltLength [2] INTEGER DEFAULT 20, |
|
* trailerField [3] INTEGER DEFAULT 1 |
|
* } |
|
* |
|
* HashAlgorithm ::= AlgorithmIdentifier |
|
* |
|
* MaskGenAlgorithm ::= AlgorithmIdentifier |
|
* |
|
* AlgorithmIdentifer ::= SEQUENCE { |
|
* algorithm OBJECT IDENTIFIER, |
|
* parameters ANY DEFINED BY algorithm OPTIONAL |
|
* } |
|
* |
|
* @param oid The OID specifying the signature algorithm |
|
* @param obj The ASN.1 structure holding the parameters |
|
* @param fillDefaults Whether to use return default values where omitted |
|
* @return signature parameter object |
|
*/ var $f71d929f259208f7$var$_readSignatureParameters = function(oid, obj, fillDefaults) { |
|
var params = { |
|
}; |
|
if (oid !== $f71d929f259208f7$var$oids['RSASSA-PSS']) return params; |
|
if (fillDefaults) params = { |
|
hash: { |
|
algorithmOid: $f71d929f259208f7$var$oids['sha1'] |
|
}, |
|
mgf: { |
|
algorithmOid: $f71d929f259208f7$var$oids['mgf1'], |
|
hash: { |
|
algorithmOid: $f71d929f259208f7$var$oids['sha1'] |
|
} |
|
}, |
|
saltLength: 20 |
|
}; |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$f71d929f259208f7$var$asn1.validate(obj, $f71d929f259208f7$var$rsassaPssParameterValidator, capture, errors)) { |
|
var error = new Error('Cannot read RSASSA-PSS parameter block.'); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
if (capture.hashOid !== undefined) { |
|
params.hash = params.hash || { |
|
}; |
|
params.hash.algorithmOid = $f71d929f259208f7$var$asn1.derToOid(capture.hashOid); |
|
} |
|
if (capture.maskGenOid !== undefined) { |
|
params.mgf = params.mgf || { |
|
}; |
|
params.mgf.algorithmOid = $f71d929f259208f7$var$asn1.derToOid(capture.maskGenOid); |
|
params.mgf.hash = params.mgf.hash || { |
|
}; |
|
params.mgf.hash.algorithmOid = $f71d929f259208f7$var$asn1.derToOid(capture.maskGenHashOid); |
|
} |
|
if (capture.saltLength !== undefined) params.saltLength = capture.saltLength.charCodeAt(0); |
|
return params; |
|
}; |
|
/** |
|
* Create signature digest for OID. |
|
* |
|
* @param options |
|
* signatureOid: the OID specifying the signature algorithm. |
|
* type: a human readable type for error messages |
|
* @return a created md instance. throws if unknown oid. |
|
*/ var $f71d929f259208f7$var$_createSignatureDigest = function(options) { |
|
switch($f71d929f259208f7$var$oids[options.signatureOid]){ |
|
case 'sha1WithRSAEncryption': |
|
// deprecated alias |
|
case 'sha1WithRSASignature': |
|
return $iGlOy.md.sha1.create(); |
|
case 'md5WithRSAEncryption': |
|
return $iGlOy.md.md5.create(); |
|
case 'sha256WithRSAEncryption': |
|
return $iGlOy.md.sha256.create(); |
|
case 'sha384WithRSAEncryption': |
|
return $iGlOy.md.sha384.create(); |
|
case 'sha512WithRSAEncryption': |
|
return $iGlOy.md.sha512.create(); |
|
case 'RSASSA-PSS': |
|
return $iGlOy.md.sha256.create(); |
|
default: |
|
var error = new Error('Could not compute ' + options.type + ' digest. ' + 'Unknown signature OID.'); |
|
error.signatureOid = options.signatureOid; |
|
throw error; |
|
} |
|
}; |
|
/** |
|
* Verify signature on certificate or CSR. |
|
* |
|
* @param options: |
|
* certificate the certificate or CSR to verify. |
|
* md the signature digest. |
|
* signature the signature |
|
* @return a created md instance. throws if unknown oid. |
|
*/ var $f71d929f259208f7$var$_verifySignature = function(options) { |
|
var cert = options.certificate; |
|
var scheme; |
|
switch(cert.signatureOid){ |
|
case $f71d929f259208f7$var$oids.sha1WithRSAEncryption: |
|
// deprecated alias |
|
case $f71d929f259208f7$var$oids.sha1WithRSASignature: |
|
break; |
|
case $f71d929f259208f7$var$oids['RSASSA-PSS']: |
|
var hash, mgf; |
|
/* initialize mgf */ hash = $f71d929f259208f7$var$oids[cert.signatureParameters.mgf.hash.algorithmOid]; |
|
if (hash === undefined || $iGlOy.md[hash] === undefined) { |
|
var error = new Error('Unsupported MGF hash function.'); |
|
error.oid = cert.signatureParameters.mgf.hash.algorithmOid; |
|
error.name = hash; |
|
throw error; |
|
} |
|
mgf = $f71d929f259208f7$var$oids[cert.signatureParameters.mgf.algorithmOid]; |
|
if (mgf === undefined || $iGlOy.mgf[mgf] === undefined) { |
|
var error = new Error('Unsupported MGF function.'); |
|
error.oid = cert.signatureParameters.mgf.algorithmOid; |
|
error.name = mgf; |
|
throw error; |
|
} |
|
mgf = $iGlOy.mgf[mgf].create($iGlOy.md[hash].create()); |
|
/* initialize hash function */ hash = $f71d929f259208f7$var$oids[cert.signatureParameters.hash.algorithmOid]; |
|
if (hash === undefined || $iGlOy.md[hash] === undefined) { |
|
var error = new Error('Unsupported RSASSA-PSS hash function.'); |
|
error.oid = cert.signatureParameters.hash.algorithmOid; |
|
error.name = hash; |
|
throw error; |
|
} |
|
scheme = $iGlOy.pss.create($iGlOy.md[hash].create(), mgf, cert.signatureParameters.saltLength); |
|
break; |
|
} |
|
// verify signature on cert using public key |
|
return cert.publicKey.verify(options.md.digest().getBytes(), options.signature, scheme); |
|
}; |
|
/** |
|
* Converts an X.509 certificate from PEM format. |
|
* |
|
* Note: If the certificate is to be verified then compute hash should |
|
* be set to true. This will scan the TBSCertificate part of the ASN.1 |
|
* object while it is converted so it doesn't need to be converted back |
|
* to ASN.1-DER-encoding later. |
|
* |
|
* @param pem the PEM-formatted certificate. |
|
* @param computeHash true to compute the hash for verification. |
|
* @param strict true to be strict when checking ASN.1 value lengths, false to |
|
* allow truncated values (default: true). |
|
* |
|
* @return the certificate. |
|
*/ $f71d929f259208f7$var$pki.certificateFromPem = function(pem, computeHash, strict) { |
|
var msg = $iGlOy.pem.decode(pem)[0]; |
|
if (msg.type !== 'CERTIFICATE' && msg.type !== 'X509 CERTIFICATE' && msg.type !== 'TRUSTED CERTIFICATE') { |
|
var error = new Error("Could not convert certificate from PEM; PEM header type is not \"CERTIFICATE\", \"X509 CERTIFICATE\", or \"TRUSTED CERTIFICATE\"."); |
|
error.headerType = msg.type; |
|
throw error; |
|
} |
|
if (msg.procType && msg.procType.type === 'ENCRYPTED') throw new Error('Could not convert certificate from PEM; PEM is encrypted.'); |
|
// convert DER to ASN.1 object |
|
var obj = $f71d929f259208f7$var$asn1.fromDer(msg.body, strict); |
|
return $f71d929f259208f7$var$pki.certificateFromAsn1(obj, computeHash); |
|
}; |
|
/** |
|
* Converts an X.509 certificate to PEM format. |
|
* |
|
* @param cert the certificate. |
|
* @param maxline the maximum characters per line, defaults to 64. |
|
* |
|
* @return the PEM-formatted certificate. |
|
*/ $f71d929f259208f7$var$pki.certificateToPem = function(cert, maxline) { |
|
// convert to ASN.1, then DER, then PEM-encode |
|
var msg = { |
|
type: 'CERTIFICATE', |
|
body: $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.certificateToAsn1(cert)).getBytes() |
|
}; |
|
return $iGlOy.pem.encode(msg, { |
|
maxline: maxline |
|
}); |
|
}; |
|
/** |
|
* Converts an RSA public key from PEM format. |
|
* |
|
* @param pem the PEM-formatted public key. |
|
* |
|
* @return the public key. |
|
*/ $f71d929f259208f7$var$pki.publicKeyFromPem = function(pem) { |
|
var msg = $iGlOy.pem.decode(pem)[0]; |
|
if (msg.type !== 'PUBLIC KEY' && msg.type !== 'RSA PUBLIC KEY') { |
|
var error = new Error("Could not convert public key from PEM; PEM header type is not \"PUBLIC KEY\" or \"RSA PUBLIC KEY\"."); |
|
error.headerType = msg.type; |
|
throw error; |
|
} |
|
if (msg.procType && msg.procType.type === 'ENCRYPTED') throw new Error('Could not convert public key from PEM; PEM is encrypted.'); |
|
// convert DER to ASN.1 object |
|
var obj = $f71d929f259208f7$var$asn1.fromDer(msg.body); |
|
return $f71d929f259208f7$var$pki.publicKeyFromAsn1(obj); |
|
}; |
|
/** |
|
* Converts an RSA public key to PEM format (using a SubjectPublicKeyInfo). |
|
* |
|
* @param key the public key. |
|
* @param maxline the maximum characters per line, defaults to 64. |
|
* |
|
* @return the PEM-formatted public key. |
|
*/ $f71d929f259208f7$var$pki.publicKeyToPem = function(key, maxline) { |
|
// convert to ASN.1, then DER, then PEM-encode |
|
var msg = { |
|
type: 'PUBLIC KEY', |
|
body: $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.publicKeyToAsn1(key)).getBytes() |
|
}; |
|
return $iGlOy.pem.encode(msg, { |
|
maxline: maxline |
|
}); |
|
}; |
|
/** |
|
* Converts an RSA public key to PEM format (using an RSAPublicKey). |
|
* |
|
* @param key the public key. |
|
* @param maxline the maximum characters per line, defaults to 64. |
|
* |
|
* @return the PEM-formatted public key. |
|
*/ $f71d929f259208f7$var$pki.publicKeyToRSAPublicKeyPem = function(key, maxline) { |
|
// convert to ASN.1, then DER, then PEM-encode |
|
var msg = { |
|
type: 'RSA PUBLIC KEY', |
|
body: $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.publicKeyToRSAPublicKey(key)).getBytes() |
|
}; |
|
return $iGlOy.pem.encode(msg, { |
|
maxline: maxline |
|
}); |
|
}; |
|
/** |
|
* Gets a fingerprint for the given public key. |
|
* |
|
* @param options the options to use. |
|
* [md] the message digest object to use (defaults to forge.md.sha1). |
|
* [type] the type of fingerprint, such as 'RSAPublicKey', |
|
* 'SubjectPublicKeyInfo' (defaults to 'RSAPublicKey'). |
|
* [encoding] an alternative output encoding, such as 'hex' |
|
* (defaults to none, outputs a byte buffer). |
|
* [delimiter] the delimiter to use between bytes for 'hex' encoded |
|
* output, eg: ':' (defaults to none). |
|
* |
|
* @return the fingerprint as a byte buffer or other encoding based on options. |
|
*/ $f71d929f259208f7$var$pki.getPublicKeyFingerprint = function(key, options) { |
|
options = options || { |
|
}; |
|
var md = options.md || $iGlOy.md.sha1.create(); |
|
var type = options.type || 'RSAPublicKey'; |
|
var bytes; |
|
switch(type){ |
|
case 'RSAPublicKey': |
|
bytes = $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.publicKeyToRSAPublicKey(key)).getBytes(); |
|
break; |
|
case 'SubjectPublicKeyInfo': |
|
bytes = $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.publicKeyToAsn1(key)).getBytes(); |
|
break; |
|
default: |
|
throw new Error('Unknown fingerprint type "' + options.type + '".'); |
|
} |
|
// hash public key bytes |
|
md.start(); |
|
md.update(bytes); |
|
var digest = md.digest(); |
|
if (options.encoding === 'hex') { |
|
var hex = digest.toHex(); |
|
if (options.delimiter) return hex.match(/.{2}/g).join(options.delimiter); |
|
return hex; |
|
} else if (options.encoding === 'binary') return digest.getBytes(); |
|
else if (options.encoding) throw new Error('Unknown encoding "' + options.encoding + '".'); |
|
return digest; |
|
}; |
|
/** |
|
* Converts a PKCS#10 certification request (CSR) from PEM format. |
|
* |
|
* Note: If the certification request is to be verified then compute hash |
|
* should be set to true. This will scan the CertificationRequestInfo part of |
|
* the ASN.1 object while it is converted so it doesn't need to be converted |
|
* back to ASN.1-DER-encoding later. |
|
* |
|
* @param pem the PEM-formatted certificate. |
|
* @param computeHash true to compute the hash for verification. |
|
* @param strict true to be strict when checking ASN.1 value lengths, false to |
|
* allow truncated values (default: true). |
|
* |
|
* @return the certification request (CSR). |
|
*/ $f71d929f259208f7$var$pki.certificationRequestFromPem = function(pem, computeHash, strict) { |
|
var msg = $iGlOy.pem.decode(pem)[0]; |
|
if (msg.type !== 'CERTIFICATE REQUEST') { |
|
var error = new Error("Could not convert certification request from PEM; PEM header type is not \"CERTIFICATE REQUEST\"."); |
|
error.headerType = msg.type; |
|
throw error; |
|
} |
|
if (msg.procType && msg.procType.type === 'ENCRYPTED') throw new Error("Could not convert certification request from PEM; PEM is encrypted."); |
|
// convert DER to ASN.1 object |
|
var obj = $f71d929f259208f7$var$asn1.fromDer(msg.body, strict); |
|
return $f71d929f259208f7$var$pki.certificationRequestFromAsn1(obj, computeHash); |
|
}; |
|
/** |
|
* Converts a PKCS#10 certification request (CSR) to PEM format. |
|
* |
|
* @param csr the certification request. |
|
* @param maxline the maximum characters per line, defaults to 64. |
|
* |
|
* @return the PEM-formatted certification request. |
|
*/ $f71d929f259208f7$var$pki.certificationRequestToPem = function(csr, maxline) { |
|
// convert to ASN.1, then DER, then PEM-encode |
|
var msg = { |
|
type: 'CERTIFICATE REQUEST', |
|
body: $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.certificationRequestToAsn1(csr)).getBytes() |
|
}; |
|
return $iGlOy.pem.encode(msg, { |
|
maxline: maxline |
|
}); |
|
}; |
|
/** |
|
* Creates an empty X.509v3 RSA certificate. |
|
* |
|
* @return the certificate. |
|
*/ $f71d929f259208f7$var$pki.createCertificate = function() { |
|
var cert = { |
|
}; |
|
cert.version = 2; |
|
cert.serialNumber = '00'; |
|
cert.signatureOid = null; |
|
cert.signature = null; |
|
cert.siginfo = { |
|
}; |
|
cert.siginfo.algorithmOid = null; |
|
cert.validity = { |
|
}; |
|
cert.validity.notBefore = new Date(); |
|
cert.validity.notAfter = new Date(); |
|
cert.issuer = { |
|
}; |
|
cert.issuer.getField = function(sn) { |
|
return $f71d929f259208f7$var$_getAttribute(cert.issuer, sn); |
|
}; |
|
cert.issuer.addField = function(attr) { |
|
$f71d929f259208f7$var$_fillMissingFields([ |
|
attr |
|
]); |
|
cert.issuer.attributes.push(attr); |
|
}; |
|
cert.issuer.attributes = []; |
|
cert.issuer.hash = null; |
|
cert.subject = { |
|
}; |
|
cert.subject.getField = function(sn) { |
|
return $f71d929f259208f7$var$_getAttribute(cert.subject, sn); |
|
}; |
|
cert.subject.addField = function(attr) { |
|
$f71d929f259208f7$var$_fillMissingFields([ |
|
attr |
|
]); |
|
cert.subject.attributes.push(attr); |
|
}; |
|
cert.subject.attributes = []; |
|
cert.subject.hash = null; |
|
cert.extensions = []; |
|
cert.publicKey = null; |
|
cert.md = null; |
|
/** |
|
* Sets the subject of this certificate. |
|
* |
|
* @param attrs the array of subject attributes to use. |
|
* @param uniqueId an optional a unique ID to use. |
|
*/ cert.setSubject = function(attrs, uniqueId) { |
|
// set new attributes, clear hash |
|
$f71d929f259208f7$var$_fillMissingFields(attrs); |
|
cert.subject.attributes = attrs; |
|
delete cert.subject.uniqueId; |
|
if (uniqueId) // TODO: support arbitrary bit length ids |
|
cert.subject.uniqueId = uniqueId; |
|
cert.subject.hash = null; |
|
}; |
|
/** |
|
* Sets the issuer of this certificate. |
|
* |
|
* @param attrs the array of issuer attributes to use. |
|
* @param uniqueId an optional a unique ID to use. |
|
*/ cert.setIssuer = function(attrs, uniqueId) { |
|
// set new attributes, clear hash |
|
$f71d929f259208f7$var$_fillMissingFields(attrs); |
|
cert.issuer.attributes = attrs; |
|
delete cert.issuer.uniqueId; |
|
if (uniqueId) // TODO: support arbitrary bit length ids |
|
cert.issuer.uniqueId = uniqueId; |
|
cert.issuer.hash = null; |
|
}; |
|
/** |
|
* Sets the extensions of this certificate. |
|
* |
|
* @param exts the array of extensions to use. |
|
*/ cert.setExtensions = function(exts) { |
|
for(var i = 0; i < exts.length; ++i)$f71d929f259208f7$var$_fillMissingExtensionFields(exts[i], { |
|
cert: cert |
|
}); |
|
// set new extensions |
|
cert.extensions = exts; |
|
}; |
|
/** |
|
* Gets an extension by its name or id. |
|
* |
|
* @param options the name to use or an object with: |
|
* name the name to use. |
|
* id the id to use. |
|
* |
|
* @return the extension or null if not found. |
|
*/ cert.getExtension = function(options) { |
|
if (typeof options === 'string') options = { |
|
name: options |
|
}; |
|
var rval = null; |
|
var ext; |
|
for(var i = 0; rval === null && i < cert.extensions.length; ++i){ |
|
ext = cert.extensions[i]; |
|
if (options.id && ext.id === options.id) rval = ext; |
|
else if (options.name && ext.name === options.name) rval = ext; |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Signs this certificate using the given private key. |
|
* |
|
* @param key the private key to sign with. |
|
* @param md the message digest object to use (defaults to forge.md.sha1). |
|
*/ cert.sign = function(key, md) { |
|
// TODO: get signature OID from private key |
|
cert.md = md || $iGlOy.md.sha1.create(); |
|
var algorithmOid = $f71d929f259208f7$var$oids[cert.md.algorithm + 'WithRSAEncryption']; |
|
if (!algorithmOid) { |
|
var error = new Error("Could not compute certificate digest. Unknown message digest algorithm OID."); |
|
error.algorithm = cert.md.algorithm; |
|
throw error; |
|
} |
|
cert.signatureOid = cert.siginfo.algorithmOid = algorithmOid; |
|
// get TBSCertificate, convert to DER |
|
cert.tbsCertificate = $f71d929f259208f7$var$pki.getTBSCertificate(cert); |
|
var bytes = $f71d929f259208f7$var$asn1.toDer(cert.tbsCertificate); |
|
// digest and sign |
|
cert.md.update(bytes.getBytes()); |
|
cert.signature = key.sign(cert.md); |
|
}; |
|
/** |
|
* Attempts verify the signature on the passed certificate using this |
|
* certificate's public key. |
|
* |
|
* @param child the certificate to verify. |
|
* |
|
* @return true if verified, false if not. |
|
*/ cert.verify = function(child) { |
|
var rval = false; |
|
if (!cert.issued(child)) { |
|
var issuer = child.issuer; |
|
var subject = cert.subject; |
|
var error = new Error("The parent certificate did not issue the given child certificate; the child certificate's issuer does not match the parent's subject."); |
|
error.expectedIssuer = subject.attributes; |
|
error.actualIssuer = issuer.attributes; |
|
throw error; |
|
} |
|
var md = child.md; |
|
if (md === null) { |
|
// create digest for OID signature types |
|
md = $f71d929f259208f7$var$_createSignatureDigest({ |
|
signatureOid: child.signatureOid, |
|
type: 'certificate' |
|
}); |
|
// produce DER formatted TBSCertificate and digest it |
|
var tbsCertificate = child.tbsCertificate || $f71d929f259208f7$var$pki.getTBSCertificate(child); |
|
var bytes = $f71d929f259208f7$var$asn1.toDer(tbsCertificate); |
|
md.update(bytes.getBytes()); |
|
} |
|
if (md !== null) rval = $f71d929f259208f7$var$_verifySignature({ |
|
certificate: cert, |
|
md: md, |
|
signature: child.signature |
|
}); |
|
return rval; |
|
}; |
|
/** |
|
* Returns true if this certificate's issuer matches the passed |
|
* certificate's subject. Note that no signature check is performed. |
|
* |
|
* @param parent the certificate to check. |
|
* |
|
* @return true if this certificate's issuer matches the passed certificate's |
|
* subject. |
|
*/ cert.isIssuer = function(parent) { |
|
var rval = false; |
|
var i = cert.issuer; |
|
var s = parent.subject; |
|
// compare hashes if present |
|
if (i.hash && s.hash) rval = i.hash === s.hash; |
|
else if (i.attributes.length === s.attributes.length) { |
|
// all attributes are the same so issuer matches subject |
|
rval = true; |
|
var iattr, sattr; |
|
for(var n = 0; rval && n < i.attributes.length; ++n){ |
|
iattr = i.attributes[n]; |
|
sattr = s.attributes[n]; |
|
if (iattr.type !== sattr.type || iattr.value !== sattr.value) // attribute mismatch |
|
rval = false; |
|
} |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Returns true if this certificate's subject matches the issuer of the |
|
* given certificate). Note that not signature check is performed. |
|
* |
|
* @param child the certificate to check. |
|
* |
|
* @return true if this certificate's subject matches the passed |
|
* certificate's issuer. |
|
*/ cert.issued = function(child) { |
|
return child.isIssuer(cert); |
|
}; |
|
/** |
|
* Generates the subjectKeyIdentifier for this certificate as byte buffer. |
|
* |
|
* @return the subjectKeyIdentifier for this certificate as byte buffer. |
|
*/ cert.generateSubjectKeyIdentifier = function() { |
|
/* See: 4.2.1.2 section of the the RFC3280, keyIdentifier is either: |
|
|
|
(1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the |
|
value of the BIT STRING subjectPublicKey (excluding the tag, |
|
length, and number of unused bits). |
|
|
|
(2) The keyIdentifier is composed of a four bit type field with |
|
the value 0100 followed by the least significant 60 bits of the |
|
SHA-1 hash of the value of the BIT STRING subjectPublicKey |
|
(excluding the tag, length, and number of unused bit string bits). |
|
*/ // skipping the tag, length, and number of unused bits is the same |
|
// as just using the RSAPublicKey (for RSA keys, which are the |
|
// only ones supported) |
|
return $f71d929f259208f7$var$pki.getPublicKeyFingerprint(cert.publicKey, { |
|
type: 'RSAPublicKey' |
|
}); |
|
}; |
|
/** |
|
* Verifies the subjectKeyIdentifier extension value for this certificate |
|
* against its public key. If no extension is found, false will be |
|
* returned. |
|
* |
|
* @return true if verified, false if not. |
|
*/ cert.verifySubjectKeyIdentifier = function() { |
|
var oid = $f71d929f259208f7$var$oids['subjectKeyIdentifier']; |
|
for(var i = 0; i < cert.extensions.length; ++i){ |
|
var ext = cert.extensions[i]; |
|
if (ext.id === oid) { |
|
var ski = cert.generateSubjectKeyIdentifier().getBytes(); |
|
return $iGlOy.util.hexToBytes(ext.subjectKeyIdentifier) === ski; |
|
} |
|
} |
|
return false; |
|
}; |
|
return cert; |
|
}; |
|
/** |
|
* Converts an X.509v3 RSA certificate from an ASN.1 object. |
|
* |
|
* Note: If the certificate is to be verified then compute hash should |
|
* be set to true. There is currently no implementation for converting |
|
* a certificate back to ASN.1 so the TBSCertificate part of the ASN.1 |
|
* object needs to be scanned before the cert object is created. |
|
* |
|
* @param obj the asn1 representation of an X.509v3 RSA certificate. |
|
* @param computeHash true to compute the hash for verification. |
|
* |
|
* @return the certificate. |
|
*/ $f71d929f259208f7$var$pki.certificateFromAsn1 = function(obj, computeHash) { |
|
// validate certificate and capture data |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$f71d929f259208f7$var$asn1.validate(obj, $f71d929f259208f7$var$x509CertificateValidator, capture, errors)) { |
|
var error = new Error("Cannot read X.509 certificate. ASN.1 object is not an X509v3 Certificate."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
// get oid |
|
var oid = $f71d929f259208f7$var$asn1.derToOid(capture.publicKeyOid); |
|
if (oid !== $f71d929f259208f7$var$pki.oids.rsaEncryption) throw new Error('Cannot read public key. OID is not RSA.'); |
|
// create certificate |
|
var cert = $f71d929f259208f7$var$pki.createCertificate(); |
|
cert.version = capture.certVersion ? capture.certVersion.charCodeAt(0) : 0; |
|
var serial = $iGlOy.util.createBuffer(capture.certSerialNumber); |
|
cert.serialNumber = serial.toHex(); |
|
cert.signatureOid = $iGlOy.asn1.derToOid(capture.certSignatureOid); |
|
cert.signatureParameters = $f71d929f259208f7$var$_readSignatureParameters(cert.signatureOid, capture.certSignatureParams, true); |
|
cert.siginfo.algorithmOid = $iGlOy.asn1.derToOid(capture.certinfoSignatureOid); |
|
cert.siginfo.parameters = $f71d929f259208f7$var$_readSignatureParameters(cert.siginfo.algorithmOid, capture.certinfoSignatureParams, false); |
|
cert.signature = capture.certSignature; |
|
var validity = []; |
|
if (capture.certValidity1UTCTime !== undefined) validity.push($f71d929f259208f7$var$asn1.utcTimeToDate(capture.certValidity1UTCTime)); |
|
if (capture.certValidity2GeneralizedTime !== undefined) validity.push($f71d929f259208f7$var$asn1.generalizedTimeToDate(capture.certValidity2GeneralizedTime)); |
|
if (capture.certValidity3UTCTime !== undefined) validity.push($f71d929f259208f7$var$asn1.utcTimeToDate(capture.certValidity3UTCTime)); |
|
if (capture.certValidity4GeneralizedTime !== undefined) validity.push($f71d929f259208f7$var$asn1.generalizedTimeToDate(capture.certValidity4GeneralizedTime)); |
|
if (validity.length > 2) throw new Error("Cannot read notBefore/notAfter validity times; more than two times were provided in the certificate."); |
|
if (validity.length < 2) throw new Error("Cannot read notBefore/notAfter validity times; they were not provided as either UTCTime or GeneralizedTime."); |
|
cert.validity.notBefore = validity[0]; |
|
cert.validity.notAfter = validity[1]; |
|
// keep TBSCertificate to preserve signature when exporting |
|
cert.tbsCertificate = capture.tbsCertificate; |
|
if (computeHash) { |
|
// create digest for OID signature type |
|
cert.md = $f71d929f259208f7$var$_createSignatureDigest({ |
|
signatureOid: cert.signatureOid, |
|
type: 'certificate' |
|
}); |
|
// produce DER formatted TBSCertificate and digest it |
|
var bytes = $f71d929f259208f7$var$asn1.toDer(cert.tbsCertificate); |
|
cert.md.update(bytes.getBytes()); |
|
} |
|
// handle issuer, build issuer message digest |
|
var imd = $iGlOy.md.sha1.create(); |
|
var ibytes = $f71d929f259208f7$var$asn1.toDer(capture.certIssuer); |
|
imd.update(ibytes.getBytes()); |
|
cert.issuer.getField = function(sn) { |
|
return $f71d929f259208f7$var$_getAttribute(cert.issuer, sn); |
|
}; |
|
cert.issuer.addField = function(attr) { |
|
$f71d929f259208f7$var$_fillMissingFields([ |
|
attr |
|
]); |
|
cert.issuer.attributes.push(attr); |
|
}; |
|
cert.issuer.attributes = $f71d929f259208f7$var$pki.RDNAttributesAsArray(capture.certIssuer); |
|
if (capture.certIssuerUniqueId) cert.issuer.uniqueId = capture.certIssuerUniqueId; |
|
cert.issuer.hash = imd.digest().toHex(); |
|
// handle subject, build subject message digest |
|
var smd = $iGlOy.md.sha1.create(); |
|
var sbytes = $f71d929f259208f7$var$asn1.toDer(capture.certSubject); |
|
smd.update(sbytes.getBytes()); |
|
cert.subject.getField = function(sn) { |
|
return $f71d929f259208f7$var$_getAttribute(cert.subject, sn); |
|
}; |
|
cert.subject.addField = function(attr) { |
|
$f71d929f259208f7$var$_fillMissingFields([ |
|
attr |
|
]); |
|
cert.subject.attributes.push(attr); |
|
}; |
|
cert.subject.attributes = $f71d929f259208f7$var$pki.RDNAttributesAsArray(capture.certSubject); |
|
if (capture.certSubjectUniqueId) cert.subject.uniqueId = capture.certSubjectUniqueId; |
|
cert.subject.hash = smd.digest().toHex(); |
|
// handle extensions |
|
if (capture.certExtensions) cert.extensions = $f71d929f259208f7$var$pki.certificateExtensionsFromAsn1(capture.certExtensions); |
|
else cert.extensions = []; |
|
// convert RSA public key from ASN.1 |
|
cert.publicKey = $f71d929f259208f7$var$pki.publicKeyFromAsn1(capture.subjectPublicKeyInfo); |
|
return cert; |
|
}; |
|
/** |
|
* Converts an ASN.1 extensions object (with extension sequences as its |
|
* values) into an array of extension objects with types and values. |
|
* |
|
* Supported extensions: |
|
* |
|
* id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } |
|
* KeyUsage ::= BIT STRING { |
|
* digitalSignature (0), |
|
* nonRepudiation (1), |
|
* keyEncipherment (2), |
|
* dataEncipherment (3), |
|
* keyAgreement (4), |
|
* keyCertSign (5), |
|
* cRLSign (6), |
|
* encipherOnly (7), |
|
* decipherOnly (8) |
|
* } |
|
* |
|
* id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } |
|
* BasicConstraints ::= SEQUENCE { |
|
* cA BOOLEAN DEFAULT FALSE, |
|
* pathLenConstraint INTEGER (0..MAX) OPTIONAL |
|
* } |
|
* |
|
* subjectAltName EXTENSION ::= { |
|
* SYNTAX GeneralNames |
|
* IDENTIFIED BY id-ce-subjectAltName |
|
* } |
|
* |
|
* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName |
|
* |
|
* GeneralName ::= CHOICE { |
|
* otherName [0] INSTANCE OF OTHER-NAME, |
|
* rfc822Name [1] IA5String, |
|
* dNSName [2] IA5String, |
|
* x400Address [3] ORAddress, |
|
* directoryName [4] Name, |
|
* ediPartyName [5] EDIPartyName, |
|
* uniformResourceIdentifier [6] IA5String, |
|
* IPAddress [7] OCTET STRING, |
|
* registeredID [8] OBJECT IDENTIFIER |
|
* } |
|
* |
|
* OTHER-NAME ::= TYPE-IDENTIFIER |
|
* |
|
* EDIPartyName ::= SEQUENCE { |
|
* nameAssigner [0] DirectoryString {ub-name} OPTIONAL, |
|
* partyName [1] DirectoryString {ub-name} |
|
* } |
|
* |
|
* @param exts the extensions ASN.1 with extension sequences to parse. |
|
* |
|
* @return the array. |
|
*/ $f71d929f259208f7$var$pki.certificateExtensionsFromAsn1 = function(exts) { |
|
var rval = []; |
|
for(var i = 0; i < exts.value.length; ++i){ |
|
// get extension sequence |
|
var extseq = exts.value[i]; |
|
for(var ei = 0; ei < extseq.value.length; ++ei)rval.push($f71d929f259208f7$var$pki.certificateExtensionFromAsn1(extseq.value[ei])); |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Parses a single certificate extension from ASN.1. |
|
* |
|
* @param ext the extension in ASN.1 format. |
|
* |
|
* @return the parsed extension as an object. |
|
*/ $f71d929f259208f7$var$pki.certificateExtensionFromAsn1 = function(ext) { |
|
// an extension has: |
|
// [0] extnID OBJECT IDENTIFIER |
|
// [1] critical BOOLEAN DEFAULT FALSE |
|
// [2] extnValue OCTET STRING |
|
var e = { |
|
}; |
|
e.id = $f71d929f259208f7$var$asn1.derToOid(ext.value[0].value); |
|
e.critical = false; |
|
if (ext.value[1].type === $f71d929f259208f7$var$asn1.Type.BOOLEAN) { |
|
e.critical = ext.value[1].value.charCodeAt(0) !== 0; |
|
e.value = ext.value[2].value; |
|
} else e.value = ext.value[1].value; |
|
// if the oid is known, get its name |
|
if (e.id in $f71d929f259208f7$var$oids) { |
|
e.name = $f71d929f259208f7$var$oids[e.id]; |
|
// handle key usage |
|
if (e.name === 'keyUsage') { |
|
// get value as BIT STRING |
|
var ev = $f71d929f259208f7$var$asn1.fromDer(e.value); |
|
var b2 = 0; |
|
var b3 = 0; |
|
if (ev.value.length > 1) { |
|
// skip first byte, just indicates unused bits which |
|
// will be padded with 0s anyway |
|
// get bytes with flag bits |
|
b2 = ev.value.charCodeAt(1); |
|
b3 = ev.value.length > 2 ? ev.value.charCodeAt(2) : 0; |
|
} |
|
// set flags |
|
e.digitalSignature = (b2 & 128) === 128; |
|
e.nonRepudiation = (b2 & 64) === 64; |
|
e.keyEncipherment = (b2 & 32) === 32; |
|
e.dataEncipherment = (b2 & 16) === 16; |
|
e.keyAgreement = (b2 & 8) === 8; |
|
e.keyCertSign = (b2 & 4) === 4; |
|
e.cRLSign = (b2 & 2) === 2; |
|
e.encipherOnly = (b2 & 1) === 1; |
|
e.decipherOnly = (b3 & 128) === 128; |
|
} else if (e.name === 'basicConstraints') { |
|
// handle basic constraints |
|
// get value as SEQUENCE |
|
var ev = $f71d929f259208f7$var$asn1.fromDer(e.value); |
|
// get cA BOOLEAN flag (defaults to false) |
|
if (ev.value.length > 0 && ev.value[0].type === $f71d929f259208f7$var$asn1.Type.BOOLEAN) e.cA = ev.value[0].value.charCodeAt(0) !== 0; |
|
else e.cA = false; |
|
// get path length constraint |
|
var value = null; |
|
if (ev.value.length > 0 && ev.value[0].type === $f71d929f259208f7$var$asn1.Type.INTEGER) value = ev.value[0].value; |
|
else if (ev.value.length > 1) value = ev.value[1].value; |
|
if (value !== null) e.pathLenConstraint = $f71d929f259208f7$var$asn1.derToInteger(value); |
|
} else if (e.name === 'extKeyUsage') { |
|
// handle extKeyUsage |
|
// value is a SEQUENCE of OIDs |
|
var ev = $f71d929f259208f7$var$asn1.fromDer(e.value); |
|
for(var vi = 0; vi < ev.value.length; ++vi){ |
|
var oid = $f71d929f259208f7$var$asn1.derToOid(ev.value[vi].value); |
|
if (oid in $f71d929f259208f7$var$oids) e[$f71d929f259208f7$var$oids[oid]] = true; |
|
else e[oid] = true; |
|
} |
|
} else if (e.name === 'nsCertType') { |
|
// handle nsCertType |
|
// get value as BIT STRING |
|
var ev = $f71d929f259208f7$var$asn1.fromDer(e.value); |
|
var b2 = 0; |
|
if (ev.value.length > 1) // skip first byte, just indicates unused bits which |
|
// will be padded with 0s anyway |
|
// get bytes with flag bits |
|
b2 = ev.value.charCodeAt(1); |
|
// set flags |
|
e.client = (b2 & 128) === 128; |
|
e.server = (b2 & 64) === 64; |
|
e.email = (b2 & 32) === 32; |
|
e.objsign = (b2 & 16) === 16; |
|
e.reserved = (b2 & 8) === 8; |
|
e.sslCA = (b2 & 4) === 4; |
|
e.emailCA = (b2 & 2) === 2; |
|
e.objCA = (b2 & 1) === 1; |
|
} else if (e.name === 'subjectAltName' || e.name === 'issuerAltName') { |
|
// handle subjectAltName/issuerAltName |
|
e.altNames = []; |
|
// ev is a SYNTAX SEQUENCE |
|
var gn; |
|
var ev = $f71d929f259208f7$var$asn1.fromDer(e.value); |
|
for(var n = 0; n < ev.value.length; ++n){ |
|
// get GeneralName |
|
gn = ev.value[n]; |
|
var altName = { |
|
type: gn.type, |
|
value: gn.value |
|
}; |
|
e.altNames.push(altName); |
|
// Note: Support for types 1,2,6,7,8 |
|
switch(gn.type){ |
|
// rfc822Name |
|
case 1: |
|
// dNSName |
|
case 2: |
|
// uniformResourceIdentifier (URI) |
|
case 6: |
|
break; |
|
// IPAddress |
|
case 7: |
|
// convert to IPv4/IPv6 string representation |
|
altName.ip = $iGlOy.util.bytesToIP(gn.value); |
|
break; |
|
// registeredID |
|
case 8: |
|
altName.oid = $f71d929f259208f7$var$asn1.derToOid(gn.value); |
|
break; |
|
default: |
|
} |
|
} |
|
} else if (e.name === 'subjectKeyIdentifier') { |
|
// value is an OCTETSTRING w/the hash of the key-type specific |
|
// public key structure (eg: RSAPublicKey) |
|
var ev = $f71d929f259208f7$var$asn1.fromDer(e.value); |
|
e.subjectKeyIdentifier = $iGlOy.util.bytesToHex(ev.value); |
|
} |
|
} |
|
return e; |
|
}; |
|
/** |
|
* Converts a PKCS#10 certification request (CSR) from an ASN.1 object. |
|
* |
|
* Note: If the certification request is to be verified then compute hash |
|
* should be set to true. There is currently no implementation for converting |
|
* a certificate back to ASN.1 so the CertificationRequestInfo part of the |
|
* ASN.1 object needs to be scanned before the csr object is created. |
|
* |
|
* @param obj the asn1 representation of a PKCS#10 certification request (CSR). |
|
* @param computeHash true to compute the hash for verification. |
|
* |
|
* @return the certification request (CSR). |
|
*/ $f71d929f259208f7$var$pki.certificationRequestFromAsn1 = function(obj, computeHash) { |
|
// validate certification request and capture data |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$f71d929f259208f7$var$asn1.validate(obj, $f71d929f259208f7$var$certificationRequestValidator, capture, errors)) { |
|
var error = new Error("Cannot read PKCS#10 certificate request. ASN.1 object is not a PKCS#10 CertificationRequest."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
// get oid |
|
var oid = $f71d929f259208f7$var$asn1.derToOid(capture.publicKeyOid); |
|
if (oid !== $f71d929f259208f7$var$pki.oids.rsaEncryption) throw new Error('Cannot read public key. OID is not RSA.'); |
|
// create certification request |
|
var csr = $f71d929f259208f7$var$pki.createCertificationRequest(); |
|
csr.version = capture.csrVersion ? capture.csrVersion.charCodeAt(0) : 0; |
|
csr.signatureOid = $iGlOy.asn1.derToOid(capture.csrSignatureOid); |
|
csr.signatureParameters = $f71d929f259208f7$var$_readSignatureParameters(csr.signatureOid, capture.csrSignatureParams, true); |
|
csr.siginfo.algorithmOid = $iGlOy.asn1.derToOid(capture.csrSignatureOid); |
|
csr.siginfo.parameters = $f71d929f259208f7$var$_readSignatureParameters(csr.siginfo.algorithmOid, capture.csrSignatureParams, false); |
|
csr.signature = capture.csrSignature; |
|
// keep CertificationRequestInfo to preserve signature when exporting |
|
csr.certificationRequestInfo = capture.certificationRequestInfo; |
|
if (computeHash) { |
|
// create digest for OID signature type |
|
csr.md = $f71d929f259208f7$var$_createSignatureDigest({ |
|
signatureOid: csr.signatureOid, |
|
type: 'certification request' |
|
}); |
|
// produce DER formatted CertificationRequestInfo and digest it |
|
var bytes = $f71d929f259208f7$var$asn1.toDer(csr.certificationRequestInfo); |
|
csr.md.update(bytes.getBytes()); |
|
} |
|
// handle subject, build subject message digest |
|
var smd = $iGlOy.md.sha1.create(); |
|
csr.subject.getField = function(sn) { |
|
return $f71d929f259208f7$var$_getAttribute(csr.subject, sn); |
|
}; |
|
csr.subject.addField = function(attr) { |
|
$f71d929f259208f7$var$_fillMissingFields([ |
|
attr |
|
]); |
|
csr.subject.attributes.push(attr); |
|
}; |
|
csr.subject.attributes = $f71d929f259208f7$var$pki.RDNAttributesAsArray(capture.certificationRequestInfoSubject, smd); |
|
csr.subject.hash = smd.digest().toHex(); |
|
// convert RSA public key from ASN.1 |
|
csr.publicKey = $f71d929f259208f7$var$pki.publicKeyFromAsn1(capture.subjectPublicKeyInfo); |
|
// convert attributes from ASN.1 |
|
csr.getAttribute = function(sn) { |
|
return $f71d929f259208f7$var$_getAttribute(csr, sn); |
|
}; |
|
csr.addAttribute = function(attr) { |
|
$f71d929f259208f7$var$_fillMissingFields([ |
|
attr |
|
]); |
|
csr.attributes.push(attr); |
|
}; |
|
csr.attributes = $f71d929f259208f7$var$pki.CRIAttributesAsArray(capture.certificationRequestInfoAttributes || []); |
|
return csr; |
|
}; |
|
/** |
|
* Creates an empty certification request (a CSR or certificate signing |
|
* request). Once created, its public key and attributes can be set and then |
|
* it can be signed. |
|
* |
|
* @return the empty certification request. |
|
*/ $f71d929f259208f7$var$pki.createCertificationRequest = function() { |
|
var csr = { |
|
}; |
|
csr.version = 0; |
|
csr.signatureOid = null; |
|
csr.signature = null; |
|
csr.siginfo = { |
|
}; |
|
csr.siginfo.algorithmOid = null; |
|
csr.subject = { |
|
}; |
|
csr.subject.getField = function(sn) { |
|
return $f71d929f259208f7$var$_getAttribute(csr.subject, sn); |
|
}; |
|
csr.subject.addField = function(attr) { |
|
$f71d929f259208f7$var$_fillMissingFields([ |
|
attr |
|
]); |
|
csr.subject.attributes.push(attr); |
|
}; |
|
csr.subject.attributes = []; |
|
csr.subject.hash = null; |
|
csr.publicKey = null; |
|
csr.attributes = []; |
|
csr.getAttribute = function(sn) { |
|
return $f71d929f259208f7$var$_getAttribute(csr, sn); |
|
}; |
|
csr.addAttribute = function(attr) { |
|
$f71d929f259208f7$var$_fillMissingFields([ |
|
attr |
|
]); |
|
csr.attributes.push(attr); |
|
}; |
|
csr.md = null; |
|
/** |
|
* Sets the subject of this certification request. |
|
* |
|
* @param attrs the array of subject attributes to use. |
|
*/ csr.setSubject = function(attrs) { |
|
// set new attributes |
|
$f71d929f259208f7$var$_fillMissingFields(attrs); |
|
csr.subject.attributes = attrs; |
|
csr.subject.hash = null; |
|
}; |
|
/** |
|
* Sets the attributes of this certification request. |
|
* |
|
* @param attrs the array of attributes to use. |
|
*/ csr.setAttributes = function(attrs) { |
|
// set new attributes |
|
$f71d929f259208f7$var$_fillMissingFields(attrs); |
|
csr.attributes = attrs; |
|
}; |
|
/** |
|
* Signs this certification request using the given private key. |
|
* |
|
* @param key the private key to sign with. |
|
* @param md the message digest object to use (defaults to forge.md.sha1). |
|
*/ csr.sign = function(key, md) { |
|
// TODO: get signature OID from private key |
|
csr.md = md || $iGlOy.md.sha1.create(); |
|
var algorithmOid = $f71d929f259208f7$var$oids[csr.md.algorithm + 'WithRSAEncryption']; |
|
if (!algorithmOid) { |
|
var error = new Error("Could not compute certification request digest. Unknown message digest algorithm OID."); |
|
error.algorithm = csr.md.algorithm; |
|
throw error; |
|
} |
|
csr.signatureOid = csr.siginfo.algorithmOid = algorithmOid; |
|
// get CertificationRequestInfo, convert to DER |
|
csr.certificationRequestInfo = $f71d929f259208f7$var$pki.getCertificationRequestInfo(csr); |
|
var bytes = $f71d929f259208f7$var$asn1.toDer(csr.certificationRequestInfo); |
|
// digest and sign |
|
csr.md.update(bytes.getBytes()); |
|
csr.signature = key.sign(csr.md); |
|
}; |
|
/** |
|
* Attempts verify the signature on the passed certification request using |
|
* its public key. |
|
* |
|
* A CSR that has been exported to a file in PEM format can be verified using |
|
* OpenSSL using this command: |
|
* |
|
* openssl req -in <the-csr-pem-file> -verify -noout -text |
|
* |
|
* @return true if verified, false if not. |
|
*/ csr.verify = function() { |
|
var rval = false; |
|
var md = csr.md; |
|
if (md === null) { |
|
md = $f71d929f259208f7$var$_createSignatureDigest({ |
|
signatureOid: csr.signatureOid, |
|
type: 'certification request' |
|
}); |
|
// produce DER formatted CertificationRequestInfo and digest it |
|
var cri = csr.certificationRequestInfo || $f71d929f259208f7$var$pki.getCertificationRequestInfo(csr); |
|
var bytes = $f71d929f259208f7$var$asn1.toDer(cri); |
|
md.update(bytes.getBytes()); |
|
} |
|
if (md !== null) rval = $f71d929f259208f7$var$_verifySignature({ |
|
certificate: csr, |
|
md: md, |
|
signature: csr.signature |
|
}); |
|
return rval; |
|
}; |
|
return csr; |
|
}; |
|
/** |
|
* Converts an X.509 subject or issuer to an ASN.1 RDNSequence. |
|
* |
|
* @param obj the subject or issuer (distinguished name). |
|
* |
|
* @return the ASN.1 RDNSequence. |
|
*/ function $f71d929f259208f7$var$_dnToAsn1(obj) { |
|
// create an empty RDNSequence |
|
var rval = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, []); |
|
// iterate over attributes |
|
var attr, set; |
|
var attrs = obj.attributes; |
|
for(var i = 0; i < attrs.length; ++i){ |
|
attr = attrs[i]; |
|
var value = attr.value; |
|
// reuse tag class for attribute value if available |
|
var valueTagClass = $f71d929f259208f7$var$asn1.Type.PRINTABLESTRING; |
|
if ('valueTagClass' in attr) { |
|
valueTagClass = attr.valueTagClass; |
|
if (valueTagClass === $f71d929f259208f7$var$asn1.Type.UTF8) value = $iGlOy.util.encodeUtf8(value); |
|
// FIXME: handle more encodings |
|
} |
|
// create a RelativeDistinguishedName set |
|
// each value in the set is an AttributeTypeAndValue first |
|
// containing the type (an OID) and second the value |
|
set = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SET, true, [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
// AttributeType |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(attr.type).getBytes()), |
|
// AttributeValue |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, valueTagClass, false, value) |
|
]) |
|
]); |
|
rval.value.push(set); |
|
} |
|
return rval; |
|
} |
|
/** |
|
* Gets all printable attributes (typically of an issuer or subject) in a |
|
* simplified JSON format for display. |
|
* |
|
* @param attrs the attributes. |
|
* |
|
* @return the JSON for display. |
|
*/ function $f71d929f259208f7$var$_getAttributesAsJson(attrs) { |
|
var rval = { |
|
}; |
|
for(var i = 0; i < attrs.length; ++i){ |
|
var attr = attrs[i]; |
|
if (attr.shortName && (attr.valueTagClass === $f71d929f259208f7$var$asn1.Type.UTF8 || attr.valueTagClass === $f71d929f259208f7$var$asn1.Type.PRINTABLESTRING || attr.valueTagClass === $f71d929f259208f7$var$asn1.Type.IA5STRING)) { |
|
var value = attr.value; |
|
if (attr.valueTagClass === $f71d929f259208f7$var$asn1.Type.UTF8) value = $iGlOy.util.encodeUtf8(attr.value); |
|
if (!(attr.shortName in rval)) rval[attr.shortName] = value; |
|
else if ($iGlOy.util.isArray(rval[attr.shortName])) rval[attr.shortName].push(value); |
|
else rval[attr.shortName] = [ |
|
rval[attr.shortName], |
|
value |
|
]; |
|
} |
|
} |
|
return rval; |
|
} |
|
/** |
|
* Fills in missing fields in attributes. |
|
* |
|
* @param attrs the attributes to fill missing fields in. |
|
*/ function $f71d929f259208f7$var$_fillMissingFields(attrs) { |
|
var attr; |
|
for(var i = 0; i < attrs.length; ++i){ |
|
attr = attrs[i]; |
|
// populate missing name |
|
if (typeof attr.name === 'undefined') { |
|
if (attr.type && attr.type in $f71d929f259208f7$var$pki.oids) attr.name = $f71d929f259208f7$var$pki.oids[attr.type]; |
|
else if (attr.shortName && attr.shortName in $f71d929f259208f7$var$_shortNames) attr.name = $f71d929f259208f7$var$pki.oids[$f71d929f259208f7$var$_shortNames[attr.shortName]]; |
|
} |
|
// populate missing type (OID) |
|
if (typeof attr.type === 'undefined') { |
|
if (attr.name && attr.name in $f71d929f259208f7$var$pki.oids) attr.type = $f71d929f259208f7$var$pki.oids[attr.name]; |
|
else { |
|
var error = new Error('Attribute type not specified.'); |
|
error.attribute = attr; |
|
throw error; |
|
} |
|
} |
|
// populate missing shortname |
|
if (typeof attr.shortName === 'undefined') { |
|
if (attr.name && attr.name in $f71d929f259208f7$var$_shortNames) attr.shortName = $f71d929f259208f7$var$_shortNames[attr.name]; |
|
} |
|
// convert extensions to value |
|
if (attr.type === $f71d929f259208f7$var$oids.extensionRequest) { |
|
attr.valueConstructed = true; |
|
attr.valueTagClass = $f71d929f259208f7$var$asn1.Type.SEQUENCE; |
|
if (!attr.value && attr.extensions) { |
|
attr.value = []; |
|
for(var ei = 0; ei < attr.extensions.length; ++ei)attr.value.push($f71d929f259208f7$var$pki.certificateExtensionToAsn1($f71d929f259208f7$var$_fillMissingExtensionFields(attr.extensions[ei]))); |
|
} |
|
} |
|
if (typeof attr.value === 'undefined') { |
|
var error = new Error('Attribute value not specified.'); |
|
error.attribute = attr; |
|
throw error; |
|
} |
|
} |
|
} |
|
/** |
|
* Fills in missing fields in certificate extensions. |
|
* |
|
* @param e the extension. |
|
* @param [options] the options to use. |
|
* [cert] the certificate the extensions are for. |
|
* |
|
* @return the extension. |
|
*/ function $f71d929f259208f7$var$_fillMissingExtensionFields(e, options) { |
|
options = options || { |
|
}; |
|
// populate missing name |
|
if (typeof e.name === 'undefined') { |
|
if (e.id && e.id in $f71d929f259208f7$var$pki.oids) e.name = $f71d929f259208f7$var$pki.oids[e.id]; |
|
} |
|
// populate missing id |
|
if (typeof e.id === 'undefined') { |
|
if (e.name && e.name in $f71d929f259208f7$var$pki.oids) e.id = $f71d929f259208f7$var$pki.oids[e.name]; |
|
else { |
|
var error = new Error('Extension ID not specified.'); |
|
error.extension = e; |
|
throw error; |
|
} |
|
} |
|
if (typeof e.value !== 'undefined') return e; |
|
// handle missing value: |
|
// value is a BIT STRING |
|
if (e.name === 'keyUsage') { |
|
// build flags |
|
var unused = 0; |
|
var b2 = 0; |
|
var b3 = 0; |
|
if (e.digitalSignature) { |
|
b2 |= 128; |
|
unused = 7; |
|
} |
|
if (e.nonRepudiation) { |
|
b2 |= 64; |
|
unused = 6; |
|
} |
|
if (e.keyEncipherment) { |
|
b2 |= 32; |
|
unused = 5; |
|
} |
|
if (e.dataEncipherment) { |
|
b2 |= 16; |
|
unused = 4; |
|
} |
|
if (e.keyAgreement) { |
|
b2 |= 8; |
|
unused = 3; |
|
} |
|
if (e.keyCertSign) { |
|
b2 |= 4; |
|
unused = 2; |
|
} |
|
if (e.cRLSign) { |
|
b2 |= 2; |
|
unused = 1; |
|
} |
|
if (e.encipherOnly) { |
|
b2 |= 1; |
|
unused = 0; |
|
} |
|
if (e.decipherOnly) { |
|
b3 |= 128; |
|
unused = 7; |
|
} |
|
// create bit string |
|
var value = String.fromCharCode(unused); |
|
if (b3 !== 0) value += String.fromCharCode(b2) + String.fromCharCode(b3); |
|
else if (b2 !== 0) value += String.fromCharCode(b2); |
|
e.value = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.BITSTRING, false, value); |
|
} else if (e.name === 'basicConstraints') { |
|
// basicConstraints is a SEQUENCE |
|
e.value = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, []); |
|
// cA BOOLEAN flag defaults to false |
|
if (e.cA) e.value.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.BOOLEAN, false, String.fromCharCode(255))); |
|
if ('pathLenConstraint' in e) e.value.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.INTEGER, false, $f71d929f259208f7$var$asn1.integerToDer(e.pathLenConstraint).getBytes())); |
|
} else if (e.name === 'extKeyUsage') { |
|
// extKeyUsage is a SEQUENCE of OIDs |
|
e.value = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, []); |
|
var seq = e.value.value; |
|
for(var key in e){ |
|
if (e[key] !== true) continue; |
|
// key is name in OID map |
|
if (key in $f71d929f259208f7$var$oids) seq.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer($f71d929f259208f7$var$oids[key]).getBytes())); |
|
else if (key.indexOf('.') !== -1) // assume key is an OID |
|
seq.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(key).getBytes())); |
|
} |
|
} else if (e.name === 'nsCertType') { |
|
// nsCertType is a BIT STRING |
|
// build flags |
|
var unused = 0; |
|
var b2 = 0; |
|
if (e.client) { |
|
b2 |= 128; |
|
unused = 7; |
|
} |
|
if (e.server) { |
|
b2 |= 64; |
|
unused = 6; |
|
} |
|
if (e.email) { |
|
b2 |= 32; |
|
unused = 5; |
|
} |
|
if (e.objsign) { |
|
b2 |= 16; |
|
unused = 4; |
|
} |
|
if (e.reserved) { |
|
b2 |= 8; |
|
unused = 3; |
|
} |
|
if (e.sslCA) { |
|
b2 |= 4; |
|
unused = 2; |
|
} |
|
if (e.emailCA) { |
|
b2 |= 2; |
|
unused = 1; |
|
} |
|
if (e.objCA) { |
|
b2 |= 1; |
|
unused = 0; |
|
} |
|
// create bit string |
|
var value = String.fromCharCode(unused); |
|
if (b2 !== 0) value += String.fromCharCode(b2); |
|
e.value = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.BITSTRING, false, value); |
|
} else if (e.name === 'subjectAltName' || e.name === 'issuerAltName') { |
|
// SYNTAX SEQUENCE |
|
e.value = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, []); |
|
var altName; |
|
for(var n = 0; n < e.altNames.length; ++n){ |
|
altName = e.altNames[n]; |
|
var value = altName.value; |
|
// handle IP |
|
if (altName.type === 7 && altName.ip) { |
|
value = $iGlOy.util.bytesFromIP(altName.ip); |
|
if (value === null) { |
|
var error = new Error('Extension "ip" value is not a valid IPv4 or IPv6 address.'); |
|
error.extension = e; |
|
throw error; |
|
} |
|
} else if (altName.type === 8) { |
|
// handle OID |
|
if (altName.oid) value = $f71d929f259208f7$var$asn1.oidToDer($f71d929f259208f7$var$asn1.oidToDer(altName.oid)); |
|
else // deprecated ... convert value to OID |
|
value = $f71d929f259208f7$var$asn1.oidToDer(value); |
|
} |
|
e.value.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, altName.type, false, value)); |
|
} |
|
} else if (e.name === 'nsComment' && options.cert) { |
|
// sanity check value is ASCII (req'd) and not too big |
|
if (!/^[\x00-\x7F]*$/.test(e.comment) || e.comment.length < 1 || e.comment.length > 128) throw new Error('Invalid "nsComment" content.'); |
|
// IA5STRING opaque comment |
|
e.value = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.IA5STRING, false, e.comment); |
|
} else if (e.name === 'subjectKeyIdentifier' && options.cert) { |
|
var ski = options.cert.generateSubjectKeyIdentifier(); |
|
e.subjectKeyIdentifier = ski.toHex(); |
|
// OCTETSTRING w/digest |
|
e.value = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OCTETSTRING, false, ski.getBytes()); |
|
} else if (e.name === 'authorityKeyIdentifier' && options.cert) { |
|
// SYNTAX SEQUENCE |
|
e.value = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, []); |
|
var seq = e.value.value; |
|
if (e.keyIdentifier) { |
|
var keyIdentifier = e.keyIdentifier === true ? options.cert.generateSubjectKeyIdentifier().getBytes() : e.keyIdentifier; |
|
seq.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 0, false, keyIdentifier)); |
|
} |
|
if (e.authorityCertIssuer) { |
|
var authorityCertIssuer = [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 4, true, [ |
|
$f71d929f259208f7$var$_dnToAsn1(e.authorityCertIssuer === true ? options.cert.issuer : e.authorityCertIssuer) |
|
]) |
|
]; |
|
seq.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 1, true, authorityCertIssuer)); |
|
} |
|
if (e.serialNumber) { |
|
var serialNumber = $iGlOy.util.hexToBytes(e.serialNumber === true ? options.cert.serialNumber : e.serialNumber); |
|
seq.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 2, false, serialNumber)); |
|
} |
|
} else if (e.name === 'cRLDistributionPoints') { |
|
e.value = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, []); |
|
var seq = e.value.value; |
|
// Create sub SEQUENCE of DistributionPointName |
|
var subSeq = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, []); |
|
// Create fullName CHOICE |
|
var fullNameGeneralNames = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, []); |
|
var altName; |
|
for(var n = 0; n < e.altNames.length; ++n){ |
|
altName = e.altNames[n]; |
|
var value = altName.value; |
|
// handle IP |
|
if (altName.type === 7 && altName.ip) { |
|
value = $iGlOy.util.bytesFromIP(altName.ip); |
|
if (value === null) { |
|
var error = new Error('Extension "ip" value is not a valid IPv4 or IPv6 address.'); |
|
error.extension = e; |
|
throw error; |
|
} |
|
} else if (altName.type === 8) { |
|
// handle OID |
|
if (altName.oid) value = $f71d929f259208f7$var$asn1.oidToDer($f71d929f259208f7$var$asn1.oidToDer(altName.oid)); |
|
else // deprecated ... convert value to OID |
|
value = $f71d929f259208f7$var$asn1.oidToDer(value); |
|
} |
|
fullNameGeneralNames.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, altName.type, false, value)); |
|
} |
|
// Add to the parent SEQUENCE |
|
subSeq.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
fullNameGeneralNames |
|
])); |
|
seq.push(subSeq); |
|
} |
|
// ensure value has been defined by now |
|
if (typeof e.value === 'undefined') { |
|
var error = new Error('Extension value not specified.'); |
|
error.extension = e; |
|
throw error; |
|
} |
|
return e; |
|
} |
|
/** |
|
* Convert signature parameters object to ASN.1 |
|
* |
|
* @param {String} oid Signature algorithm OID |
|
* @param params The signature parametrs object |
|
* @return ASN.1 object representing signature parameters |
|
*/ function $f71d929f259208f7$var$_signatureParametersToAsn1(oid, params) { |
|
switch(oid){ |
|
case $f71d929f259208f7$var$oids['RSASSA-PSS']: |
|
var parts = []; |
|
if (params.hash.algorithmOid !== undefined) parts.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(params.hash.algorithmOid).getBytes()), |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.NULL, false, '') |
|
]) |
|
])); |
|
if (params.mgf.algorithmOid !== undefined) parts.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 1, true, [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(params.mgf.algorithmOid).getBytes()), |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(params.mgf.hash.algorithmOid).getBytes()), |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.NULL, false, '') |
|
]) |
|
]) |
|
])); |
|
if (params.saltLength !== undefined) parts.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 2, true, [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.INTEGER, false, $f71d929f259208f7$var$asn1.integerToDer(params.saltLength).getBytes()) |
|
])); |
|
return $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, parts); |
|
default: |
|
return $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.NULL, false, ''); |
|
} |
|
} |
|
/** |
|
* Converts a certification request's attributes to an ASN.1 set of |
|
* CRIAttributes. |
|
* |
|
* @param csr certification request. |
|
* |
|
* @return the ASN.1 set of CRIAttributes. |
|
*/ function $f71d929f259208f7$var$_CRIAttributesToAsn1(csr) { |
|
// create an empty context-specific container |
|
var rval = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, []); |
|
// no attributes, return empty container |
|
if (csr.attributes.length === 0) return rval; |
|
// each attribute has a sequence with a type and a set of values |
|
var attrs = csr.attributes; |
|
for(var i = 0; i < attrs.length; ++i){ |
|
var attr = attrs[i]; |
|
var value = attr.value; |
|
// reuse tag class for attribute value if available |
|
var valueTagClass = $f71d929f259208f7$var$asn1.Type.UTF8; |
|
if ('valueTagClass' in attr) valueTagClass = attr.valueTagClass; |
|
if (valueTagClass === $f71d929f259208f7$var$asn1.Type.UTF8) value = $iGlOy.util.encodeUtf8(value); |
|
var valueConstructed = false; |
|
if ('valueConstructed' in attr) valueConstructed = attr.valueConstructed; |
|
// FIXME: handle more encodings |
|
// create a RelativeDistinguishedName set |
|
// each value in the set is an AttributeTypeAndValue first |
|
// containing the type (an OID) and second the value |
|
var seq = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
// AttributeType |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(attr.type).getBytes()), |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SET, true, [ |
|
// AttributeValue |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, valueTagClass, valueConstructed, value) |
|
]) |
|
]); |
|
rval.value.push(seq); |
|
} |
|
return rval; |
|
} |
|
var $f71d929f259208f7$var$jan_1_1950 = new Date('1950-01-01T00:00:00Z'); |
|
var $f71d929f259208f7$var$jan_1_2050 = new Date('2050-01-01T00:00:00Z'); |
|
/** |
|
* Converts a Date object to ASN.1 |
|
* Handles the different format before and after 1st January 2050 |
|
* |
|
* @param date date object. |
|
* |
|
* @return the ASN.1 object representing the date. |
|
*/ function $f71d929f259208f7$var$_dateToAsn1(date) { |
|
if (date >= $f71d929f259208f7$var$jan_1_1950 && date < $f71d929f259208f7$var$jan_1_2050) return $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.UTCTIME, false, $f71d929f259208f7$var$asn1.dateToUtcTime(date)); |
|
else return $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.GENERALIZEDTIME, false, $f71d929f259208f7$var$asn1.dateToGeneralizedTime(date)); |
|
} |
|
/** |
|
* Gets the ASN.1 TBSCertificate part of an X.509v3 certificate. |
|
* |
|
* @param cert the certificate. |
|
* |
|
* @return the asn1 TBSCertificate. |
|
*/ $f71d929f259208f7$var$pki.getTBSCertificate = function(cert) { |
|
// TBSCertificate |
|
var notBefore = $f71d929f259208f7$var$_dateToAsn1(cert.validity.notBefore); |
|
var notAfter = $f71d929f259208f7$var$_dateToAsn1(cert.validity.notAfter); |
|
var tbs = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
// version |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
// integer |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.INTEGER, false, $f71d929f259208f7$var$asn1.integerToDer(cert.version).getBytes()) |
|
]), |
|
// serialNumber |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.INTEGER, false, $iGlOy.util.hexToBytes(cert.serialNumber)), |
|
// signature |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
// algorithm |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(cert.siginfo.algorithmOid).getBytes()), |
|
// parameters |
|
$f71d929f259208f7$var$_signatureParametersToAsn1(cert.siginfo.algorithmOid, cert.siginfo.parameters) |
|
]), |
|
// issuer |
|
$f71d929f259208f7$var$_dnToAsn1(cert.issuer), |
|
// validity |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
notBefore, |
|
notAfter |
|
]), |
|
// subject |
|
$f71d929f259208f7$var$_dnToAsn1(cert.subject), |
|
// SubjectPublicKeyInfo |
|
$f71d929f259208f7$var$pki.publicKeyToAsn1(cert.publicKey) |
|
]); |
|
if (cert.issuer.uniqueId) // issuerUniqueID (optional) |
|
tbs.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 1, true, [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.BITSTRING, false, // TODO: support arbitrary bit length ids |
|
String.fromCharCode(0) + cert.issuer.uniqueId) |
|
])); |
|
if (cert.subject.uniqueId) // subjectUniqueID (optional) |
|
tbs.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 2, true, [ |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.BITSTRING, false, // TODO: support arbitrary bit length ids |
|
String.fromCharCode(0) + cert.subject.uniqueId) |
|
])); |
|
if (cert.extensions.length > 0) // extensions (optional) |
|
tbs.value.push($f71d929f259208f7$var$pki.certificateExtensionsToAsn1(cert.extensions)); |
|
return tbs; |
|
}; |
|
/** |
|
* Gets the ASN.1 CertificationRequestInfo part of a |
|
* PKCS#10 CertificationRequest. |
|
* |
|
* @param csr the certification request. |
|
* |
|
* @return the asn1 CertificationRequestInfo. |
|
*/ $f71d929f259208f7$var$pki.getCertificationRequestInfo = function(csr) { |
|
// CertificationRequestInfo |
|
var cri = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
// version |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.INTEGER, false, $f71d929f259208f7$var$asn1.integerToDer(csr.version).getBytes()), |
|
// subject |
|
$f71d929f259208f7$var$_dnToAsn1(csr.subject), |
|
// SubjectPublicKeyInfo |
|
$f71d929f259208f7$var$pki.publicKeyToAsn1(csr.publicKey), |
|
// attributes |
|
$f71d929f259208f7$var$_CRIAttributesToAsn1(csr) |
|
]); |
|
return cri; |
|
}; |
|
/** |
|
* Converts a DistinguishedName (subject or issuer) to an ASN.1 object. |
|
* |
|
* @param dn the DistinguishedName. |
|
* |
|
* @return the asn1 representation of a DistinguishedName. |
|
*/ $f71d929f259208f7$var$pki.distinguishedNameToAsn1 = function(dn) { |
|
return $f71d929f259208f7$var$_dnToAsn1(dn); |
|
}; |
|
/** |
|
* Converts an X.509v3 RSA certificate to an ASN.1 object. |
|
* |
|
* @param cert the certificate. |
|
* |
|
* @return the asn1 representation of an X.509v3 RSA certificate. |
|
*/ $f71d929f259208f7$var$pki.certificateToAsn1 = function(cert) { |
|
// prefer cached TBSCertificate over generating one |
|
var tbsCertificate = cert.tbsCertificate || $f71d929f259208f7$var$pki.getTBSCertificate(cert); |
|
// Certificate |
|
return $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
// TBSCertificate |
|
tbsCertificate, |
|
// AlgorithmIdentifier (signature algorithm) |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
// algorithm |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(cert.signatureOid).getBytes()), |
|
// parameters |
|
$f71d929f259208f7$var$_signatureParametersToAsn1(cert.signatureOid, cert.signatureParameters) |
|
]), |
|
// SignatureValue |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.BITSTRING, false, String.fromCharCode(0) + cert.signature) |
|
]); |
|
}; |
|
/** |
|
* Converts X.509v3 certificate extensions to ASN.1. |
|
* |
|
* @param exts the extensions to convert. |
|
* |
|
* @return the extensions in ASN.1 format. |
|
*/ $f71d929f259208f7$var$pki.certificateExtensionsToAsn1 = function(exts) { |
|
// create top-level extension container |
|
var rval = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.CONTEXT_SPECIFIC, 3, true, []); |
|
// create extension sequence (stores a sequence for each extension) |
|
var seq = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, []); |
|
rval.value.push(seq); |
|
for(var i = 0; i < exts.length; ++i)seq.value.push($f71d929f259208f7$var$pki.certificateExtensionToAsn1(exts[i])); |
|
return rval; |
|
}; |
|
/** |
|
* Converts a single certificate extension to ASN.1. |
|
* |
|
* @param ext the extension to convert. |
|
* |
|
* @return the extension in ASN.1 format. |
|
*/ $f71d929f259208f7$var$pki.certificateExtensionToAsn1 = function(ext) { |
|
// create a sequence for each extension |
|
var extseq = $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, []); |
|
// extnID (OID) |
|
extseq.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(ext.id).getBytes())); |
|
// critical defaults to false |
|
if (ext.critical) // critical BOOLEAN DEFAULT FALSE |
|
extseq.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.BOOLEAN, false, String.fromCharCode(255))); |
|
var value = ext.value; |
|
if (typeof ext.value !== 'string') // value is asn.1 |
|
value = $f71d929f259208f7$var$asn1.toDer(value).getBytes(); |
|
// extnValue (OCTET STRING) |
|
extseq.value.push($f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OCTETSTRING, false, value)); |
|
return extseq; |
|
}; |
|
/** |
|
* Converts a PKCS#10 certification request to an ASN.1 object. |
|
* |
|
* @param csr the certification request. |
|
* |
|
* @return the asn1 representation of a certification request. |
|
*/ $f71d929f259208f7$var$pki.certificationRequestToAsn1 = function(csr) { |
|
// prefer cached CertificationRequestInfo over generating one |
|
var cri = csr.certificationRequestInfo || $f71d929f259208f7$var$pki.getCertificationRequestInfo(csr); |
|
// Certificate |
|
return $f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
// CertificationRequestInfo |
|
cri, |
|
// AlgorithmIdentifier (signature algorithm) |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.SEQUENCE, true, [ |
|
// algorithm |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.OID, false, $f71d929f259208f7$var$asn1.oidToDer(csr.signatureOid).getBytes()), |
|
// parameters |
|
$f71d929f259208f7$var$_signatureParametersToAsn1(csr.signatureOid, csr.signatureParameters) |
|
]), |
|
// signature |
|
$f71d929f259208f7$var$asn1.create($f71d929f259208f7$var$asn1.Class.UNIVERSAL, $f71d929f259208f7$var$asn1.Type.BITSTRING, false, String.fromCharCode(0) + csr.signature) |
|
]); |
|
}; |
|
/** |
|
* Creates a CA store. |
|
* |
|
* @param certs an optional array of certificate objects or PEM-formatted |
|
* certificate strings to add to the CA store. |
|
* |
|
* @return the CA store. |
|
*/ $f71d929f259208f7$var$pki.createCaStore = function(certs) { |
|
// create CA store |
|
var caStore = { |
|
// stored certificates |
|
certs: { |
|
} |
|
}; |
|
/** |
|
* Gets the certificate that issued the passed certificate or its |
|
* 'parent'. |
|
* |
|
* @param cert the certificate to get the parent for. |
|
* |
|
* @return the parent certificate or null if none was found. |
|
*/ caStore.getIssuer = function(cert) { |
|
var rval = getBySubject(cert.issuer); |
|
// see if there are multiple matches |
|
/*if(forge.util.isArray(rval)) { |
|
// TODO: resolve multiple matches by checking |
|
// authorityKey/subjectKey/issuerUniqueID/other identifiers, etc. |
|
// FIXME: or alternatively do authority key mapping |
|
// if possible (X.509v1 certs can't work?) |
|
throw new Error('Resolving multiple issuer matches not implemented yet.'); |
|
}*/ return rval; |
|
}; |
|
/** |
|
* Adds a trusted certificate to the store. |
|
* |
|
* @param cert the certificate to add as a trusted certificate (either a |
|
* pki.certificate object or a PEM-formatted certificate). |
|
*/ caStore.addCertificate = function(cert) { |
|
// convert from pem if necessary |
|
if (typeof cert === 'string') cert = $iGlOy.pki.certificateFromPem(cert); |
|
ensureSubjectHasHash(cert.subject); |
|
if (!caStore.hasCertificate(cert)) { |
|
if (cert.subject.hash in caStore.certs) { |
|
// subject hash already exists, append to array |
|
var tmp = caStore.certs[cert.subject.hash]; |
|
if (!$iGlOy.util.isArray(tmp)) tmp = [ |
|
tmp |
|
]; |
|
tmp.push(cert); |
|
caStore.certs[cert.subject.hash] = tmp; |
|
} else caStore.certs[cert.subject.hash] = cert; |
|
} |
|
}; |
|
/** |
|
* Checks to see if the given certificate is in the store. |
|
* |
|
* @param cert the certificate to check (either a pki.certificate or a |
|
* PEM-formatted certificate). |
|
* |
|
* @return true if the certificate is in the store, false if not. |
|
*/ caStore.hasCertificate = function(cert) { |
|
// convert from pem if necessary |
|
if (typeof cert === 'string') cert = $iGlOy.pki.certificateFromPem(cert); |
|
var match = getBySubject(cert.subject); |
|
if (!match) return false; |
|
if (!$iGlOy.util.isArray(match)) match = [ |
|
match |
|
]; |
|
// compare DER-encoding of certificates |
|
var der1 = $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.certificateToAsn1(cert)).getBytes(); |
|
for(var i = 0; i < match.length; ++i){ |
|
var der2 = $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.certificateToAsn1(match[i])).getBytes(); |
|
if (der1 === der2) return true; |
|
} |
|
return false; |
|
}; |
|
/** |
|
* Lists all of the certificates kept in the store. |
|
* |
|
* @return an array of all of the pki.certificate objects in the store. |
|
*/ caStore.listAllCertificates = function() { |
|
var certList = []; |
|
for(var hash in caStore.certs)if (caStore.certs.hasOwnProperty(hash)) { |
|
var value = caStore.certs[hash]; |
|
if (!$iGlOy.util.isArray(value)) certList.push(value); |
|
else for(var i = 0; i < value.length; ++i)certList.push(value[i]); |
|
} |
|
return certList; |
|
}; |
|
/** |
|
* Removes a certificate from the store. |
|
* |
|
* @param cert the certificate to remove (either a pki.certificate or a |
|
* PEM-formatted certificate). |
|
* |
|
* @return the certificate that was removed or null if the certificate |
|
* wasn't in store. |
|
*/ caStore.removeCertificate = function(cert) { |
|
var result; |
|
// convert from pem if necessary |
|
if (typeof cert === 'string') cert = $iGlOy.pki.certificateFromPem(cert); |
|
ensureSubjectHasHash(cert.subject); |
|
if (!caStore.hasCertificate(cert)) return null; |
|
var match = getBySubject(cert.subject); |
|
if (!$iGlOy.util.isArray(match)) { |
|
result = caStore.certs[cert.subject.hash]; |
|
delete caStore.certs[cert.subject.hash]; |
|
return result; |
|
} |
|
// compare DER-encoding of certificates |
|
var der1 = $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.certificateToAsn1(cert)).getBytes(); |
|
for(var i = 0; i < match.length; ++i){ |
|
var der2 = $f71d929f259208f7$var$asn1.toDer($f71d929f259208f7$var$pki.certificateToAsn1(match[i])).getBytes(); |
|
if (der1 === der2) { |
|
result = match[i]; |
|
match.splice(i, 1); |
|
} |
|
} |
|
if (match.length === 0) delete caStore.certs[cert.subject.hash]; |
|
return result; |
|
}; |
|
function getBySubject(subject) { |
|
ensureSubjectHasHash(subject); |
|
return caStore.certs[subject.hash] || null; |
|
} |
|
function ensureSubjectHasHash(subject) { |
|
// produce subject hash if it doesn't exist |
|
if (!subject.hash) { |
|
var md = $iGlOy.md.sha1.create(); |
|
subject.attributes = $f71d929f259208f7$var$pki.RDNAttributesAsArray($f71d929f259208f7$var$_dnToAsn1(subject), md); |
|
subject.hash = md.digest().toHex(); |
|
} |
|
} |
|
// auto-add passed in certs |
|
if (certs) // parse PEM-formatted certificates as necessary |
|
for(var i1 = 0; i1 < certs.length; ++i1){ |
|
var cert1 = certs[i1]; |
|
caStore.addCertificate(cert1); |
|
} |
|
return caStore; |
|
}; |
|
/** |
|
* Certificate verification errors, based on TLS. |
|
*/ $f71d929f259208f7$var$pki.certificateError = { |
|
bad_certificate: 'forge.pki.BadCertificate', |
|
unsupported_certificate: 'forge.pki.UnsupportedCertificate', |
|
certificate_revoked: 'forge.pki.CertificateRevoked', |
|
certificate_expired: 'forge.pki.CertificateExpired', |
|
certificate_unknown: 'forge.pki.CertificateUnknown', |
|
unknown_ca: 'forge.pki.UnknownCertificateAuthority' |
|
}; |
|
/** |
|
* Verifies a certificate chain against the given Certificate Authority store |
|
* with an optional custom verify callback. |
|
* |
|
* @param caStore a certificate store to verify against. |
|
* @param chain the certificate chain to verify, with the root or highest |
|
* authority at the end (an array of certificates). |
|
* @param options a callback to be called for every certificate in the chain or |
|
* an object with: |
|
* verify a callback to be called for every certificate in the |
|
* chain |
|
* validityCheckDate the date against which the certificate |
|
* validity period should be checked. Pass null to not check |
|
* the validity period. By default, the current date is used. |
|
* |
|
* The verify callback has the following signature: |
|
* |
|
* verified - Set to true if certificate was verified, otherwise the |
|
* pki.certificateError for why the certificate failed. |
|
* depth - The current index in the chain, where 0 is the end point's cert. |
|
* certs - The certificate chain, *NOTE* an empty chain indicates an anonymous |
|
* end point. |
|
* |
|
* The function returns true on success and on failure either the appropriate |
|
* pki.certificateError or an object with 'error' set to the appropriate |
|
* pki.certificateError and 'message' set to a custom error message. |
|
* |
|
* @return true if successful, error thrown if not. |
|
*/ $f71d929f259208f7$var$pki.verifyCertificateChain = function(caStore, chain, options) { |
|
/* From: RFC3280 - Internet X.509 Public Key Infrastructure Certificate |
|
Section 6: Certification Path Validation |
|
See inline parentheticals related to this particular implementation. |
|
|
|
The primary goal of path validation is to verify the binding between |
|
a subject distinguished name or a subject alternative name and subject |
|
public key, as represented in the end entity certificate, based on the |
|
public key of the trust anchor. This requires obtaining a sequence of |
|
certificates that support that binding. That sequence should be provided |
|
in the passed 'chain'. The trust anchor should be in the given CA |
|
store. The 'end entity' certificate is the certificate provided by the |
|
end point (typically a server) and is the first in the chain. |
|
|
|
To meet this goal, the path validation process verifies, among other |
|
things, that a prospective certification path (a sequence of n |
|
certificates or a 'chain') satisfies the following conditions: |
|
|
|
(a) for all x in {1, ..., n-1}, the subject of certificate x is |
|
the issuer of certificate x+1; |
|
|
|
(b) certificate 1 is issued by the trust anchor; |
|
|
|
(c) certificate n is the certificate to be validated; and |
|
|
|
(d) for all x in {1, ..., n}, the certificate was valid at the |
|
time in question. |
|
|
|
Note that here 'n' is index 0 in the chain and 1 is the last certificate |
|
in the chain and it must be signed by a certificate in the connection's |
|
CA store. |
|
|
|
The path validation process also determines the set of certificate |
|
policies that are valid for this path, based on the certificate policies |
|
extension, policy mapping extension, policy constraints extension, and |
|
inhibit any-policy extension. |
|
|
|
Note: Policy mapping extension not supported (Not Required). |
|
|
|
Note: If the certificate has an unsupported critical extension, then it |
|
must be rejected. |
|
|
|
Note: A certificate is self-issued if the DNs that appear in the subject |
|
and issuer fields are identical and are not empty. |
|
|
|
The path validation algorithm assumes the following seven inputs are |
|
provided to the path processing logic. What this specific implementation |
|
will use is provided parenthetically: |
|
|
|
(a) a prospective certification path of length n (the 'chain') |
|
(b) the current date/time: ('now'). |
|
(c) user-initial-policy-set: A set of certificate policy identifiers |
|
naming the policies that are acceptable to the certificate user. |
|
The user-initial-policy-set contains the special value any-policy |
|
if the user is not concerned about certificate policy |
|
(Not implemented. Any policy is accepted). |
|
(d) trust anchor information, describing a CA that serves as a trust |
|
anchor for the certification path. The trust anchor information |
|
includes: |
|
|
|
(1) the trusted issuer name, |
|
(2) the trusted public key algorithm, |
|
(3) the trusted public key, and |
|
(4) optionally, the trusted public key parameters associated |
|
with the public key. |
|
|
|
(Trust anchors are provided via certificates in the CA store). |
|
|
|
The trust anchor information may be provided to the path processing |
|
procedure in the form of a self-signed certificate. The trusted anchor |
|
information is trusted because it was delivered to the path processing |
|
procedure by some trustworthy out-of-band procedure. If the trusted |
|
public key algorithm requires parameters, then the parameters are |
|
provided along with the trusted public key (No parameters used in this |
|
implementation). |
|
|
|
(e) initial-policy-mapping-inhibit, which indicates if policy mapping is |
|
allowed in the certification path. |
|
(Not implemented, no policy checking) |
|
|
|
(f) initial-explicit-policy, which indicates if the path must be valid |
|
for at least one of the certificate policies in the user-initial- |
|
policy-set. |
|
(Not implemented, no policy checking) |
|
|
|
(g) initial-any-policy-inhibit, which indicates whether the |
|
anyPolicy OID should be processed if it is included in a |
|
certificate. |
|
(Not implemented, so any policy is valid provided that it is |
|
not marked as critical) */ /* Basic Path Processing: |
|
|
|
For each certificate in the 'chain', the following is checked: |
|
|
|
1. The certificate validity period includes the current time. |
|
2. The certificate was signed by its parent (where the parent is either |
|
the next in the chain or from the CA store). Allow processing to |
|
continue to the next step if no parent is found but the certificate is |
|
in the CA store. |
|
3. TODO: The certificate has not been revoked. |
|
4. The certificate issuer name matches the parent's subject name. |
|
5. TODO: If the certificate is self-issued and not the final certificate |
|
in the chain, skip this step, otherwise verify that the subject name |
|
is within one of the permitted subtrees of X.500 distinguished names |
|
and that each of the alternative names in the subjectAltName extension |
|
(critical or non-critical) is within one of the permitted subtrees for |
|
that name type. |
|
6. TODO: If the certificate is self-issued and not the final certificate |
|
in the chain, skip this step, otherwise verify that the subject name |
|
is not within one of the excluded subtrees for X.500 distinguished |
|
names and none of the subjectAltName extension names are excluded for |
|
that name type. |
|
7. The other steps in the algorithm for basic path processing involve |
|
handling the policy extension which is not presently supported in this |
|
implementation. Instead, if a critical policy extension is found, the |
|
certificate is rejected as not supported. |
|
8. If the certificate is not the first or if its the only certificate in |
|
the chain (having no parent from the CA store or is self-signed) and it |
|
has a critical key usage extension, verify that the keyCertSign bit is |
|
set. If the key usage extension exists, verify that the basic |
|
constraints extension exists. If the basic constraints extension exists, |
|
verify that the cA flag is set. If pathLenConstraint is set, ensure that |
|
the number of certificates that precede in the chain (come earlier |
|
in the chain as implemented below), excluding the very first in the |
|
chain (typically the end-entity one), isn't greater than the |
|
pathLenConstraint. This constraint limits the number of intermediate |
|
CAs that may appear below a CA before only end-entity certificates |
|
may be issued. */ // if a verify callback is passed as the third parameter, package it within |
|
// the options object. This is to support a legacy function signature that |
|
// expected the verify callback as the third parameter. |
|
if (typeof options === 'function') options = { |
|
verify: options |
|
}; |
|
options = options || { |
|
}; |
|
// copy cert chain references to another array to protect against changes |
|
// in verify callback |
|
chain = chain.slice(0); |
|
var certs = chain.slice(0); |
|
var validityCheckDate = options.validityCheckDate; |
|
// if no validityCheckDate is specified, default to the current date. Make |
|
// sure to maintain the value null because it indicates that the validity |
|
// period should not be checked. |
|
if (typeof validityCheckDate === 'undefined') validityCheckDate = new Date(); |
|
// verify each cert in the chain using its parent, where the parent |
|
// is either the next in the chain or from the CA store |
|
var first = true; |
|
var error = null; |
|
var depth = 0; |
|
do { |
|
var cert = chain.shift(); |
|
var parent = null; |
|
var selfSigned = false; |
|
if (validityCheckDate) // 1. check valid time |
|
{ |
|
if (validityCheckDate < cert.validity.notBefore || validityCheckDate > cert.validity.notAfter) error = { |
|
message: 'Certificate is not valid yet or has expired.', |
|
error: $f71d929f259208f7$var$pki.certificateError.certificate_expired, |
|
notBefore: cert.validity.notBefore, |
|
notAfter: cert.validity.notAfter, |
|
// TODO: we might want to reconsider renaming 'now' to |
|
// 'validityCheckDate' should this API be changed in the future. |
|
now: validityCheckDate |
|
}; |
|
} |
|
// 2. verify with parent from chain or CA store |
|
if (error === null) { |
|
parent = chain[0] || caStore.getIssuer(cert); |
|
if (parent === null) // check for self-signed cert |
|
{ |
|
if (cert.isIssuer(cert)) { |
|
selfSigned = true; |
|
parent = cert; |
|
} |
|
} |
|
if (parent) { |
|
// FIXME: current CA store implementation might have multiple |
|
// certificates where the issuer can't be determined from the |
|
// certificate (happens rarely with, eg: old certificates) so normalize |
|
// by always putting parents into an array |
|
// TODO: there's may be an extreme degenerate case currently uncovered |
|
// where an old intermediate certificate seems to have a matching parent |
|
// but none of the parents actually verify ... but the intermediate |
|
// is in the CA and it should pass this check; needs investigation |
|
var parents = parent; |
|
if (!$iGlOy.util.isArray(parents)) parents = [ |
|
parents |
|
]; |
|
// try to verify with each possible parent (typically only one) |
|
var verified = false; |
|
while(!verified && parents.length > 0){ |
|
parent = parents.shift(); |
|
try { |
|
verified = parent.verify(cert); |
|
} catch (ex) { |
|
// failure to verify, don't care why, try next one |
|
} |
|
} |
|
if (!verified) error = { |
|
message: 'Certificate signature is invalid.', |
|
error: $f71d929f259208f7$var$pki.certificateError.bad_certificate |
|
}; |
|
} |
|
if (error === null && (!parent || selfSigned) && !caStore.hasCertificate(cert)) // no parent issuer and certificate itself is not trusted |
|
error = { |
|
message: 'Certificate is not trusted.', |
|
error: $f71d929f259208f7$var$pki.certificateError.unknown_ca |
|
}; |
|
} |
|
// TODO: 3. check revoked |
|
// 4. check for matching issuer/subject |
|
if (error === null && parent && !cert.isIssuer(parent)) // parent is not issuer |
|
error = { |
|
message: 'Certificate issuer is invalid.', |
|
error: $f71d929f259208f7$var$pki.certificateError.bad_certificate |
|
}; |
|
// 5. TODO: check names with permitted names tree |
|
// 6. TODO: check names against excluded names tree |
|
// 7. check for unsupported critical extensions |
|
if (error === null) { |
|
// supported extensions |
|
var se = { |
|
keyUsage: true, |
|
basicConstraints: true |
|
}; |
|
for(var i = 0; error === null && i < cert.extensions.length; ++i){ |
|
var ext = cert.extensions[i]; |
|
if (ext.critical && !(ext.name in se)) error = { |
|
message: 'Certificate has an unsupported critical extension.', |
|
error: $f71d929f259208f7$var$pki.certificateError.unsupported_certificate |
|
}; |
|
} |
|
} |
|
// 8. check for CA if cert is not first or is the only certificate |
|
// remaining in chain with no parent or is self-signed |
|
if (error === null && (!first || chain.length === 0 && (!parent || selfSigned))) { |
|
// first check keyUsage extension and then basic constraints |
|
var bcExt = cert.getExtension('basicConstraints'); |
|
var keyUsageExt = cert.getExtension('keyUsage'); |
|
if (keyUsageExt !== null) // keyCertSign must be true and there must be a basic |
|
// constraints extension |
|
{ |
|
if (!keyUsageExt.keyCertSign || bcExt === null) // bad certificate |
|
error = { |
|
message: "Certificate keyUsage or basicConstraints conflict or indicate that the certificate is not a CA. If the certificate is the only one in the chain or isn't the first then the certificate must be a valid CA.", |
|
error: $f71d929f259208f7$var$pki.certificateError.bad_certificate |
|
}; |
|
} |
|
// basic constraints cA flag must be set |
|
if (error === null && bcExt !== null && !bcExt.cA) // bad certificate |
|
error = { |
|
message: "Certificate basicConstraints indicates the certificate is not a CA.", |
|
error: $f71d929f259208f7$var$pki.certificateError.bad_certificate |
|
}; |
|
// if error is not null and keyUsage is available, then we know it |
|
// has keyCertSign and there is a basic constraints extension too, |
|
// which means we can check pathLenConstraint (if it exists) |
|
if (error === null && keyUsageExt !== null && 'pathLenConstraint' in bcExt) { |
|
// pathLen is the maximum # of intermediate CA certs that can be |
|
// found between the current certificate and the end-entity (depth 0) |
|
// certificate; this number does not include the end-entity (depth 0, |
|
// last in the chain) even if it happens to be a CA certificate itself |
|
var pathLen = depth - 1; |
|
if (pathLen > bcExt.pathLenConstraint) // pathLenConstraint violated, bad certificate |
|
error = { |
|
message: 'Certificate basicConstraints pathLenConstraint violated.', |
|
error: $f71d929f259208f7$var$pki.certificateError.bad_certificate |
|
}; |
|
} |
|
} |
|
// call application callback |
|
var vfd = error === null ? true : error.error; |
|
var ret = options.verify ? options.verify(vfd, depth, certs) : vfd; |
|
if (ret === true) // clear any set error |
|
error = null; |
|
else { |
|
// if passed basic tests, set default message and alert |
|
if (vfd === true) error = { |
|
message: 'The application rejected the certificate.', |
|
error: $f71d929f259208f7$var$pki.certificateError.bad_certificate |
|
}; |
|
// check for custom error info |
|
if (ret || ret === 0) { |
|
// set custom message and error |
|
if (typeof ret === 'object' && !$iGlOy.util.isArray(ret)) { |
|
if (ret.message) error.message = ret.message; |
|
if (ret.error) error.error = ret.error; |
|
} else if (typeof ret === 'string') // set custom error |
|
error.error = ret; |
|
} |
|
// throw error |
|
throw error; |
|
} |
|
// no longer first cert in chain |
|
first = false; |
|
++depth; |
|
}while (chain.length > 0) |
|
return true; |
|
}; |
|
|
|
|
|
// shortcut for asn.1 & PKI API |
|
var $6fcb727b03413917$var$asn1 = $iGlOy.asn1; |
|
var $6fcb727b03413917$var$pki = $iGlOy.pki; |
|
// shortcut for PKCS#12 API |
|
var $6fcb727b03413917$var$p12 = $6fcb727b03413917$exports = $iGlOy.pkcs12 = $iGlOy.pkcs12 || { |
|
}; |
|
var $6fcb727b03413917$var$contentInfoValidator = { |
|
name: 'ContentInfo', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'ContentInfo.contentType', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'contentType' |
|
}, |
|
{ |
|
name: 'ContentInfo.content', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, |
|
constructed: true, |
|
captureAsn1: 'content' |
|
} |
|
] |
|
}; |
|
var $6fcb727b03413917$var$pfxValidator = { |
|
name: 'PFX', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'PFX.version', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'version' |
|
}, |
|
$6fcb727b03413917$var$contentInfoValidator, |
|
{ |
|
name: 'PFX.macData', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
optional: true, |
|
captureAsn1: 'mac', |
|
value: [ |
|
{ |
|
name: 'PFX.macData.mac', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'PFX.macData.mac.digestAlgorithm', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'PFX.macData.mac.digestAlgorithm.algorithm', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'macAlgorithm' |
|
}, |
|
{ |
|
name: 'PFX.macData.mac.digestAlgorithm.parameters', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
captureAsn1: 'macAlgorithmParameters' |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'PFX.macData.mac.digest', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'macDigest' |
|
} |
|
] |
|
}, |
|
{ |
|
name: 'PFX.macData.macSalt', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'macSalt' |
|
}, |
|
{ |
|
name: 'PFX.macData.iterations', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
optional: true, |
|
capture: 'macIterations' |
|
} |
|
] |
|
} |
|
] |
|
}; |
|
var $6fcb727b03413917$var$safeBagValidator = { |
|
name: 'SafeBag', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'SafeBag.bagId', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'bagId' |
|
}, |
|
{ |
|
name: 'SafeBag.bagValue', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, |
|
constructed: true, |
|
captureAsn1: 'bagValue' |
|
}, |
|
{ |
|
name: 'SafeBag.bagAttributes', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SET, |
|
constructed: true, |
|
optional: true, |
|
capture: 'bagAttributes' |
|
} |
|
] |
|
}; |
|
var $6fcb727b03413917$var$attributeValidator = { |
|
name: 'Attribute', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'Attribute.attrId', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'oid' |
|
}, |
|
{ |
|
name: 'Attribute.attrValues', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SET, |
|
constructed: true, |
|
capture: 'values' |
|
} |
|
] |
|
}; |
|
var $6fcb727b03413917$var$certBagValidator = { |
|
name: 'CertBag', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'CertBag.certId', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'certId' |
|
}, |
|
{ |
|
name: 'CertBag.certValue', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, |
|
constructed: true, |
|
/* So far we only support X.509 certificates (which are wrapped in |
|
an OCTET STRING, hence hard code that here). */ value: [ |
|
{ |
|
name: 'CertBag.certValue[0]', |
|
tagClass: $6fcb727b03413917$var$asn1.Class.UNIVERSAL, |
|
type: $6fcb727b03413917$var$asn1.Class.OCTETSTRING, |
|
constructed: false, |
|
capture: 'cert' |
|
} |
|
] |
|
} |
|
] |
|
}; |
|
/** |
|
* Search SafeContents structure for bags with matching attributes. |
|
* |
|
* The search can optionally be narrowed by a certain bag type. |
|
* |
|
* @param safeContents the SafeContents structure to search in. |
|
* @param attrName the name of the attribute to compare against. |
|
* @param attrValue the attribute value to search for. |
|
* @param [bagType] bag type to narrow search by. |
|
* |
|
* @return an array of matching bags. |
|
*/ function $6fcb727b03413917$var$_getBagsByAttribute(safeContents, attrName, attrValue, bagType) { |
|
var result = []; |
|
for(var i = 0; i < safeContents.length; i++)for(var j = 0; j < safeContents[i].safeBags.length; j++){ |
|
var bag = safeContents[i].safeBags[j]; |
|
if (bagType !== undefined && bag.type !== bagType) continue; |
|
// only filter by bag type, no attribute specified |
|
if (attrName === null) { |
|
result.push(bag); |
|
continue; |
|
} |
|
if (bag.attributes[attrName] !== undefined && bag.attributes[attrName].indexOf(attrValue) >= 0) result.push(bag); |
|
} |
|
return result; |
|
} |
|
/** |
|
* Converts a PKCS#12 PFX in ASN.1 notation into a PFX object. |
|
* |
|
* @param obj The PKCS#12 PFX in ASN.1 notation. |
|
* @param strict true to use strict DER decoding, false not to (default: true). |
|
* @param {String} password Password to decrypt with (optional). |
|
* |
|
* @return PKCS#12 PFX object. |
|
*/ $6fcb727b03413917$var$p12.pkcs12FromAsn1 = function(obj, strict, password) { |
|
// handle args |
|
if (typeof strict === 'string') { |
|
password = strict; |
|
strict = true; |
|
} else if (strict === undefined) strict = true; |
|
// validate PFX and capture data |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$6fcb727b03413917$var$asn1.validate(obj, $6fcb727b03413917$var$pfxValidator, capture, errors)) { |
|
var error = new Error("Cannot read PKCS#12 PFX. ASN.1 object is not an PKCS#12 PFX."); |
|
error.errors = error; |
|
throw error; |
|
} |
|
var pfx = { |
|
version: capture.version.charCodeAt(0), |
|
safeContents: [], |
|
/** |
|
* Gets bags with matching attributes. |
|
* |
|
* @param filter the attributes to filter by: |
|
* [localKeyId] the localKeyId to search for. |
|
* [localKeyIdHex] the localKeyId in hex to search for. |
|
* [friendlyName] the friendly name to search for. |
|
* [bagType] bag type to narrow each attribute search by. |
|
* |
|
* @return a map of attribute type to an array of matching bags or, if no |
|
* attribute was given but a bag type, the map key will be the |
|
* bag type. |
|
*/ getBags: function(filter) { |
|
var rval = { |
|
}; |
|
var localKeyId; |
|
if ('localKeyId' in filter) localKeyId = filter.localKeyId; |
|
else if ('localKeyIdHex' in filter) localKeyId = $iGlOy.util.hexToBytes(filter.localKeyIdHex); |
|
// filter on bagType only |
|
if (localKeyId === undefined && !('friendlyName' in filter) && 'bagType' in filter) rval[filter.bagType] = $6fcb727b03413917$var$_getBagsByAttribute(pfx.safeContents, null, null, filter.bagType); |
|
if (localKeyId !== undefined) rval.localKeyId = $6fcb727b03413917$var$_getBagsByAttribute(pfx.safeContents, 'localKeyId', localKeyId, filter.bagType); |
|
if ('friendlyName' in filter) rval.friendlyName = $6fcb727b03413917$var$_getBagsByAttribute(pfx.safeContents, 'friendlyName', filter.friendlyName, filter.bagType); |
|
return rval; |
|
}, |
|
/** |
|
* DEPRECATED: use getBags() instead. |
|
* |
|
* Get bags with matching friendlyName attribute. |
|
* |
|
* @param friendlyName the friendly name to search for. |
|
* @param [bagType] bag type to narrow search by. |
|
* |
|
* @return an array of bags with matching friendlyName attribute. |
|
*/ getBagsByFriendlyName: function(friendlyName, bagType) { |
|
return $6fcb727b03413917$var$_getBagsByAttribute(pfx.safeContents, 'friendlyName', friendlyName, bagType); |
|
}, |
|
/** |
|
* DEPRECATED: use getBags() instead. |
|
* |
|
* Get bags with matching localKeyId attribute. |
|
* |
|
* @param localKeyId the localKeyId to search for. |
|
* @param [bagType] bag type to narrow search by. |
|
* |
|
* @return an array of bags with matching localKeyId attribute. |
|
*/ getBagsByLocalKeyId: function(localKeyId, bagType) { |
|
return $6fcb727b03413917$var$_getBagsByAttribute(pfx.safeContents, 'localKeyId', localKeyId, bagType); |
|
} |
|
}; |
|
if (capture.version.charCodeAt(0) !== 3) { |
|
var error = new Error('PKCS#12 PFX of version other than 3 not supported.'); |
|
error.version = capture.version.charCodeAt(0); |
|
throw error; |
|
} |
|
if ($6fcb727b03413917$var$asn1.derToOid(capture.contentType) !== $6fcb727b03413917$var$pki.oids.data) { |
|
var error = new Error('Only PKCS#12 PFX in password integrity mode supported.'); |
|
error.oid = $6fcb727b03413917$var$asn1.derToOid(capture.contentType); |
|
throw error; |
|
} |
|
var data = capture.content.value[0]; |
|
if (data.tagClass !== $6fcb727b03413917$var$asn1.Class.UNIVERSAL || data.type !== $6fcb727b03413917$var$asn1.Type.OCTETSTRING) throw new Error('PKCS#12 authSafe content data is not an OCTET STRING.'); |
|
data = $6fcb727b03413917$var$_decodePkcs7Data(data); |
|
// check for MAC |
|
if (capture.mac) { |
|
var md = null; |
|
var macKeyBytes = 0; |
|
var macAlgorithm = $6fcb727b03413917$var$asn1.derToOid(capture.macAlgorithm); |
|
switch(macAlgorithm){ |
|
case $6fcb727b03413917$var$pki.oids.sha1: |
|
md = $iGlOy.md.sha1.create(); |
|
macKeyBytes = 20; |
|
break; |
|
case $6fcb727b03413917$var$pki.oids.sha256: |
|
md = $iGlOy.md.sha256.create(); |
|
macKeyBytes = 32; |
|
break; |
|
case $6fcb727b03413917$var$pki.oids.sha384: |
|
md = $iGlOy.md.sha384.create(); |
|
macKeyBytes = 48; |
|
break; |
|
case $6fcb727b03413917$var$pki.oids.sha512: |
|
md = $iGlOy.md.sha512.create(); |
|
macKeyBytes = 64; |
|
break; |
|
case $6fcb727b03413917$var$pki.oids.md5: |
|
md = $iGlOy.md.md5.create(); |
|
macKeyBytes = 16; |
|
break; |
|
} |
|
if (md === null) throw new Error('PKCS#12 uses unsupported MAC algorithm: ' + macAlgorithm); |
|
// verify MAC (iterations default to 1) |
|
var macSalt = new $iGlOy.util.ByteBuffer(capture.macSalt); |
|
var macIterations = 'macIterations' in capture ? parseInt($iGlOy.util.bytesToHex(capture.macIterations), 16) : 1; |
|
var macKey = $6fcb727b03413917$var$p12.generateKey(password, macSalt, 3, macIterations, macKeyBytes, md); |
|
var mac = $iGlOy.hmac.create(); |
|
mac.start(md, macKey); |
|
mac.update(data.value); |
|
var macValue = mac.getMac(); |
|
if (macValue.getBytes() !== capture.macDigest) throw new Error('PKCS#12 MAC could not be verified. Invalid password?'); |
|
} |
|
$6fcb727b03413917$var$_decodeAuthenticatedSafe(pfx, data.value, strict, password); |
|
return pfx; |
|
}; |
|
/** |
|
* Decodes PKCS#7 Data. PKCS#7 (RFC 2315) defines "Data" as an OCTET STRING, |
|
* but it is sometimes an OCTET STRING that is composed/constructed of chunks, |
|
* each its own OCTET STRING. This is BER-encoding vs. DER-encoding. This |
|
* function transforms this corner-case into the usual simple, |
|
* non-composed/constructed OCTET STRING. |
|
* |
|
* This function may be moved to ASN.1 at some point to better deal with |
|
* more BER-encoding issues, should they arise. |
|
* |
|
* @param data the ASN.1 Data object to transform. |
|
*/ function $6fcb727b03413917$var$_decodePkcs7Data(data) { |
|
// handle special case of "chunked" data content: an octet string composed |
|
// of other octet strings |
|
if (data.composed || data.constructed) { |
|
var value = $iGlOy.util.createBuffer(); |
|
for(var i = 0; i < data.value.length; ++i)value.putBytes(data.value[i].value); |
|
data.composed = data.constructed = false; |
|
data.value = value.getBytes(); |
|
} |
|
return data; |
|
} |
|
/** |
|
* Decode PKCS#12 AuthenticatedSafe (BER encoded) into PFX object. |
|
* |
|
* The AuthenticatedSafe is a BER-encoded SEQUENCE OF ContentInfo. |
|
* |
|
* @param pfx The PKCS#12 PFX object to fill. |
|
* @param {String} authSafe BER-encoded AuthenticatedSafe. |
|
* @param strict true to use strict DER decoding, false not to. |
|
* @param {String} password Password to decrypt with (optional). |
|
*/ function $6fcb727b03413917$var$_decodeAuthenticatedSafe(pfx, authSafe, strict, password) { |
|
authSafe = $6fcb727b03413917$var$asn1.fromDer(authSafe, strict); /* actually it's BER encoded */ |
|
if (authSafe.tagClass !== $6fcb727b03413917$var$asn1.Class.UNIVERSAL || authSafe.type !== $6fcb727b03413917$var$asn1.Type.SEQUENCE || authSafe.constructed !== true) throw new Error("PKCS#12 AuthenticatedSafe expected to be a SEQUENCE OF ContentInfo"); |
|
for(var i = 0; i < authSafe.value.length; i++){ |
|
var contentInfo = authSafe.value[i]; |
|
// validate contentInfo and capture data |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$6fcb727b03413917$var$asn1.validate(contentInfo, $6fcb727b03413917$var$contentInfoValidator, capture, errors)) { |
|
var error = new Error('Cannot read ContentInfo.'); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
var obj = { |
|
encrypted: false |
|
}; |
|
var safeContents = null; |
|
var data = capture.content.value[0]; |
|
switch($6fcb727b03413917$var$asn1.derToOid(capture.contentType)){ |
|
case $6fcb727b03413917$var$pki.oids.data: |
|
if (data.tagClass !== $6fcb727b03413917$var$asn1.Class.UNIVERSAL || data.type !== $6fcb727b03413917$var$asn1.Type.OCTETSTRING) throw new Error('PKCS#12 SafeContents Data is not an OCTET STRING.'); |
|
safeContents = $6fcb727b03413917$var$_decodePkcs7Data(data).value; |
|
break; |
|
case $6fcb727b03413917$var$pki.oids.encryptedData: |
|
safeContents = $6fcb727b03413917$var$_decryptSafeContents(data, password); |
|
obj.encrypted = true; |
|
break; |
|
default: |
|
var error = new Error('Unsupported PKCS#12 contentType.'); |
|
error.contentType = $6fcb727b03413917$var$asn1.derToOid(capture.contentType); |
|
throw error; |
|
} |
|
obj.safeBags = $6fcb727b03413917$var$_decodeSafeContents(safeContents, strict, password); |
|
pfx.safeContents.push(obj); |
|
} |
|
} |
|
/** |
|
* Decrypt PKCS#7 EncryptedData structure. |
|
* |
|
* @param data ASN.1 encoded EncryptedContentInfo object. |
|
* @param password The user-provided password. |
|
* |
|
* @return The decrypted SafeContents (ASN.1 object). |
|
*/ function $6fcb727b03413917$var$_decryptSafeContents(data, password) { |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$6fcb727b03413917$var$asn1.validate(data, $iGlOy.pkcs7.asn1.encryptedDataValidator, capture, errors)) { |
|
var error = new Error('Cannot read EncryptedContentInfo.'); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
var oid = $6fcb727b03413917$var$asn1.derToOid(capture.contentType); |
|
if (oid !== $6fcb727b03413917$var$pki.oids.data) { |
|
var error = new Error('PKCS#12 EncryptedContentInfo ContentType is not Data.'); |
|
error.oid = oid; |
|
throw error; |
|
} |
|
// get cipher |
|
oid = $6fcb727b03413917$var$asn1.derToOid(capture.encAlgorithm); |
|
var cipher = $6fcb727b03413917$var$pki.pbe.getCipher(oid, capture.encParameter, password); |
|
// get encrypted data |
|
var encryptedContentAsn1 = $6fcb727b03413917$var$_decodePkcs7Data(capture.encryptedContentAsn1); |
|
var encrypted = $iGlOy.util.createBuffer(encryptedContentAsn1.value); |
|
cipher.update(encrypted); |
|
if (!cipher.finish()) throw new Error('Failed to decrypt PKCS#12 SafeContents.'); |
|
return cipher.output.getBytes(); |
|
} |
|
/** |
|
* Decode PKCS#12 SafeContents (BER-encoded) into array of Bag objects. |
|
* |
|
* The safeContents is a BER-encoded SEQUENCE OF SafeBag. |
|
* |
|
* @param {String} safeContents BER-encoded safeContents. |
|
* @param strict true to use strict DER decoding, false not to. |
|
* @param {String} password Password to decrypt with (optional). |
|
* |
|
* @return {Array} Array of Bag objects. |
|
*/ function $6fcb727b03413917$var$_decodeSafeContents(safeContents, strict, password) { |
|
// if strict and no safe contents, return empty safes |
|
if (!strict && safeContents.length === 0) return []; |
|
// actually it's BER-encoded |
|
safeContents = $6fcb727b03413917$var$asn1.fromDer(safeContents, strict); |
|
if (safeContents.tagClass !== $6fcb727b03413917$var$asn1.Class.UNIVERSAL || safeContents.type !== $6fcb727b03413917$var$asn1.Type.SEQUENCE || safeContents.constructed !== true) throw new Error('PKCS#12 SafeContents expected to be a SEQUENCE OF SafeBag.'); |
|
var res = []; |
|
for(var i = 0; i < safeContents.value.length; i++){ |
|
var safeBag = safeContents.value[i]; |
|
// validate SafeBag and capture data |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$6fcb727b03413917$var$asn1.validate(safeBag, $6fcb727b03413917$var$safeBagValidator, capture, errors)) { |
|
var error = new Error('Cannot read SafeBag.'); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
/* Create bag object and push to result array. */ var bag = { |
|
type: $6fcb727b03413917$var$asn1.derToOid(capture.bagId), |
|
attributes: $6fcb727b03413917$var$_decodeBagAttributes(capture.bagAttributes) |
|
}; |
|
res.push(bag); |
|
var validator, decoder; |
|
var bagAsn1 = capture.bagValue.value[0]; |
|
switch(bag.type){ |
|
case $6fcb727b03413917$var$pki.oids.pkcs8ShroudedKeyBag: |
|
/* bagAsn1 has a EncryptedPrivateKeyInfo, which we need to decrypt. |
|
Afterwards we can handle it like a keyBag, |
|
which is a PrivateKeyInfo. */ bagAsn1 = $6fcb727b03413917$var$pki.decryptPrivateKeyInfo(bagAsn1, password); |
|
if (bagAsn1 === null) throw new Error('Unable to decrypt PKCS#8 ShroudedKeyBag, wrong password?'); |
|
/* fall through */ case $6fcb727b03413917$var$pki.oids.keyBag: |
|
/* A PKCS#12 keyBag is a simple PrivateKeyInfo as understood by our |
|
PKI module, hence we don't have to do validation/capturing here, |
|
just pass what we already got. */ try { |
|
bag.key = $6fcb727b03413917$var$pki.privateKeyFromAsn1(bagAsn1); |
|
} catch (e) { |
|
// ignore unknown key type, pass asn1 value |
|
bag.key = null; |
|
bag.asn1 = bagAsn1; |
|
} |
|
continue; /* Nothing more to do. */ |
|
case $6fcb727b03413917$var$pki.oids.certBag: |
|
/* A PKCS#12 certBag can wrap both X.509 and sdsi certificates. |
|
Therefore put the SafeBag content through another validator to |
|
capture the fields. Afterwards check & store the results. */ validator = $6fcb727b03413917$var$certBagValidator; |
|
decoder = function() { |
|
if ($6fcb727b03413917$var$asn1.derToOid(capture.certId) !== $6fcb727b03413917$var$pki.oids.x509Certificate) { |
|
var error = new Error('Unsupported certificate type, only X.509 supported.'); |
|
error.oid = $6fcb727b03413917$var$asn1.derToOid(capture.certId); |
|
throw error; |
|
} |
|
// true=produce cert hash |
|
var certAsn1 = $6fcb727b03413917$var$asn1.fromDer(capture.cert, strict); |
|
try { |
|
bag.cert = $6fcb727b03413917$var$pki.certificateFromAsn1(certAsn1, true); |
|
} catch (e) { |
|
// ignore unknown cert type, pass asn1 value |
|
bag.cert = null; |
|
bag.asn1 = certAsn1; |
|
} |
|
}; |
|
break; |
|
default: |
|
var error = new Error('Unsupported PKCS#12 SafeBag type.'); |
|
error.oid = bag.type; |
|
throw error; |
|
} |
|
/* Validate SafeBag value (i.e. CertBag, etc.) and capture data if needed. */ if (validator !== undefined && !$6fcb727b03413917$var$asn1.validate(bagAsn1, validator, capture, errors)) { |
|
var error = new Error('Cannot read PKCS#12 ' + validator.name); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
/* Call decoder function from above to store the results. */ decoder(); |
|
} |
|
return res; |
|
} |
|
/** |
|
* Decode PKCS#12 SET OF PKCS12Attribute into JavaScript object. |
|
* |
|
* @param attributes SET OF PKCS12Attribute (ASN.1 object). |
|
* |
|
* @return the decoded attributes. |
|
*/ function $6fcb727b03413917$var$_decodeBagAttributes(attributes) { |
|
var decodedAttrs = { |
|
}; |
|
if (attributes !== undefined) for(var i = 0; i < attributes.length; ++i){ |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$6fcb727b03413917$var$asn1.validate(attributes[i], $6fcb727b03413917$var$attributeValidator, capture, errors)) { |
|
var error = new Error('Cannot read PKCS#12 BagAttribute.'); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
var oid = $6fcb727b03413917$var$asn1.derToOid(capture.oid); |
|
if ($6fcb727b03413917$var$pki.oids[oid] === undefined) continue; |
|
decodedAttrs[$6fcb727b03413917$var$pki.oids[oid]] = []; |
|
for(var j = 0; j < capture.values.length; ++j)decodedAttrs[$6fcb727b03413917$var$pki.oids[oid]].push(capture.values[j].value); |
|
} |
|
return decodedAttrs; |
|
} |
|
/** |
|
* Wraps a private key and certificate in a PKCS#12 PFX wrapper. If a |
|
* password is provided then the private key will be encrypted. |
|
* |
|
* An entire certificate chain may also be included. To do this, pass |
|
* an array for the "cert" parameter where the first certificate is |
|
* the one that is paired with the private key and each subsequent one |
|
* verifies the previous one. The certificates may be in PEM format or |
|
* have been already parsed by Forge. |
|
* |
|
* @todo implement password-based-encryption for the whole package |
|
* |
|
* @param key the private key. |
|
* @param cert the certificate (may be an array of certificates in order |
|
* to specify a certificate chain). |
|
* @param password the password to use, null for none. |
|
* @param options: |
|
* algorithm the encryption algorithm to use |
|
* ('aes128', 'aes192', 'aes256', '3des'), defaults to 'aes128'. |
|
* count the iteration count to use. |
|
* saltSize the salt size to use. |
|
* useMac true to include a MAC, false not to, defaults to true. |
|
* localKeyId the local key ID to use, in hex. |
|
* friendlyName the friendly name to use. |
|
* generateLocalKeyId true to generate a random local key ID, |
|
* false not to, defaults to true. |
|
* |
|
* @return the PKCS#12 PFX ASN.1 object. |
|
*/ $6fcb727b03413917$var$p12.toPkcs12Asn1 = function(key, cert, password, options) { |
|
// set default options |
|
options = options || { |
|
}; |
|
options.saltSize = options.saltSize || 8; |
|
options.count = options.count || 2048; |
|
options.algorithm = options.algorithm || options.encAlgorithm || 'aes128'; |
|
if (!('useMac' in options)) options.useMac = true; |
|
if (!('localKeyId' in options)) options.localKeyId = null; |
|
if (!('generateLocalKeyId' in options)) options.generateLocalKeyId = true; |
|
var localKeyId = options.localKeyId; |
|
var bagAttrs; |
|
if (localKeyId !== null) localKeyId = $iGlOy.util.hexToBytes(localKeyId); |
|
else if (options.generateLocalKeyId) { |
|
// use SHA-1 of paired cert, if available |
|
if (cert) { |
|
var pairedCert = $iGlOy.util.isArray(cert) ? cert[0] : cert; |
|
if (typeof pairedCert === 'string') pairedCert = $6fcb727b03413917$var$pki.certificateFromPem(pairedCert); |
|
var sha1 = $iGlOy.md.sha1.create(); |
|
sha1.update($6fcb727b03413917$var$asn1.toDer($6fcb727b03413917$var$pki.certificateToAsn1(pairedCert)).getBytes()); |
|
localKeyId = sha1.digest().getBytes(); |
|
} else // FIXME: consider using SHA-1 of public key (which can be generated |
|
// from private key components), see: cert.generateSubjectKeyIdentifier |
|
// generate random bytes |
|
localKeyId = $iGlOy.random.getBytes(20); |
|
} |
|
var attrs = []; |
|
if (localKeyId !== null) attrs.push(// localKeyID |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// attrId |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, $6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.localKeyId).getBytes()), |
|
// attrValues |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SET, true, [ |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OCTETSTRING, false, localKeyId) |
|
]) |
|
])); |
|
if ('friendlyName' in options) attrs.push(// friendlyName |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// attrId |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, $6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.friendlyName).getBytes()), |
|
// attrValues |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SET, true, [ |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.BMPSTRING, false, options.friendlyName) |
|
]) |
|
])); |
|
if (attrs.length > 0) bagAttrs = $6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SET, true, attrs); |
|
// collect contents for AuthenticatedSafe |
|
var contents = []; |
|
// create safe bag(s) for certificate chain |
|
var chain = []; |
|
if (cert !== null) { |
|
if ($iGlOy.util.isArray(cert)) chain = cert; |
|
else chain = [ |
|
cert |
|
]; |
|
} |
|
var certSafeBags = []; |
|
for(var i = 0; i < chain.length; ++i){ |
|
// convert cert from PEM as necessary |
|
cert = chain[i]; |
|
if (typeof cert === 'string') cert = $6fcb727b03413917$var$pki.certificateFromPem(cert); |
|
// SafeBag |
|
var certBagAttrs = i === 0 ? bagAttrs : undefined; |
|
var certAsn1 = $6fcb727b03413917$var$pki.certificateToAsn1(cert); |
|
var certSafeBag = $6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// bagId |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, $6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.certBag).getBytes()), |
|
// bagValue |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
// CertBag |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// certId |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, $6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.x509Certificate).getBytes()), |
|
// certValue (x509Certificate) |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OCTETSTRING, false, $6fcb727b03413917$var$asn1.toDer(certAsn1).getBytes()) |
|
]) |
|
]) |
|
]), |
|
// bagAttributes (OPTIONAL) |
|
certBagAttrs |
|
]); |
|
certSafeBags.push(certSafeBag); |
|
} |
|
if (certSafeBags.length > 0) { |
|
// SafeContents |
|
var certSafeContents = $6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, certSafeBags); |
|
// ContentInfo |
|
var certCI = // PKCS#7 ContentInfo |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// contentType |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, // OID for the content type is 'data' |
|
$6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.data).getBytes()), |
|
// content |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OCTETSTRING, false, $6fcb727b03413917$var$asn1.toDer(certSafeContents).getBytes()) |
|
]) |
|
]); |
|
contents.push(certCI); |
|
} |
|
// create safe contents for private key |
|
var keyBag = null; |
|
if (key !== null) { |
|
// SafeBag |
|
var pkAsn1 = $6fcb727b03413917$var$pki.wrapRsaPrivateKey($6fcb727b03413917$var$pki.privateKeyToAsn1(key)); |
|
if (password === null) // no encryption |
|
keyBag = $6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// bagId |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, $6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.keyBag).getBytes()), |
|
// bagValue |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
// PrivateKeyInfo |
|
pkAsn1 |
|
]), |
|
// bagAttributes (OPTIONAL) |
|
bagAttrs |
|
]); |
|
else // encrypted PrivateKeyInfo |
|
keyBag = $6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// bagId |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, $6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.pkcs8ShroudedKeyBag).getBytes()), |
|
// bagValue |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
// EncryptedPrivateKeyInfo |
|
$6fcb727b03413917$var$pki.encryptPrivateKeyInfo(pkAsn1, password, options) |
|
]), |
|
// bagAttributes (OPTIONAL) |
|
bagAttrs |
|
]); |
|
// SafeContents |
|
var keySafeContents = $6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
keyBag |
|
]); |
|
// ContentInfo |
|
var keyCI = // PKCS#7 ContentInfo |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// contentType |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, // OID for the content type is 'data' |
|
$6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.data).getBytes()), |
|
// content |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OCTETSTRING, false, $6fcb727b03413917$var$asn1.toDer(keySafeContents).getBytes()) |
|
]) |
|
]); |
|
contents.push(keyCI); |
|
} |
|
// create AuthenticatedSafe by stringing together the contents |
|
var safe = $6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, contents); |
|
var macData; |
|
if (options.useMac) { |
|
// MacData |
|
var sha1 = $iGlOy.md.sha1.create(); |
|
var macSalt = new $iGlOy.util.ByteBuffer($iGlOy.random.getBytes(options.saltSize)); |
|
var count = options.count; |
|
// 160-bit key |
|
var key = $6fcb727b03413917$var$p12.generateKey(password, macSalt, 3, count, 20); |
|
var mac = $iGlOy.hmac.create(); |
|
mac.start(sha1, key); |
|
mac.update($6fcb727b03413917$var$asn1.toDer(safe).getBytes()); |
|
var macValue = mac.getMac(); |
|
macData = $6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// mac DigestInfo |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// digestAlgorithm |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// algorithm = SHA-1 |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, $6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.sha1).getBytes()), |
|
// parameters = Null |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.NULL, false, '') |
|
]), |
|
// digest |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OCTETSTRING, false, macValue.getBytes()) |
|
]), |
|
// macSalt OCTET STRING |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OCTETSTRING, false, macSalt.getBytes()), |
|
// iterations INTEGER (XXX: Only support count < 65536) |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.INTEGER, false, $6fcb727b03413917$var$asn1.integerToDer(count).getBytes()) |
|
]); |
|
} |
|
// PFX |
|
return $6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// version (3) |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.INTEGER, false, $6fcb727b03413917$var$asn1.integerToDer(3).getBytes()), |
|
// PKCS#7 ContentInfo |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.SEQUENCE, true, [ |
|
// contentType |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OID, false, // OID for the content type is 'data' |
|
$6fcb727b03413917$var$asn1.oidToDer($6fcb727b03413917$var$pki.oids.data).getBytes()), |
|
// content |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
$6fcb727b03413917$var$asn1.create($6fcb727b03413917$var$asn1.Class.UNIVERSAL, $6fcb727b03413917$var$asn1.Type.OCTETSTRING, false, $6fcb727b03413917$var$asn1.toDer(safe).getBytes()) |
|
]) |
|
]), |
|
macData |
|
]); |
|
}; |
|
/** |
|
* Derives a PKCS#12 key. |
|
* |
|
* @param password the password to derive the key material from, null or |
|
* undefined for none. |
|
* @param salt the salt, as a ByteBuffer, to use. |
|
* @param id the PKCS#12 ID byte (1 = key material, 2 = IV, 3 = MAC). |
|
* @param iter the iteration count. |
|
* @param n the number of bytes to derive from the password. |
|
* @param md the message digest to use, defaults to SHA-1. |
|
* |
|
* @return a ByteBuffer with the bytes derived from the password. |
|
*/ $6fcb727b03413917$var$p12.generateKey = $iGlOy.pbe.generatePkcs12Key; |
|
|
|
|
|
|
|
|
|
|
|
|
|
// shortcut for asn.1 API |
|
var $71c5302ef2ea3950$var$asn1 = $iGlOy.asn1; |
|
/* Public Key Infrastructure (PKI) implementation. */ var $71c5302ef2ea3950$var$pki = $71c5302ef2ea3950$exports = $iGlOy.pki = $iGlOy.pki || { |
|
}; |
|
/** |
|
* NOTE: THIS METHOD IS DEPRECATED. Use pem.decode() instead. |
|
* |
|
* Converts PEM-formatted data to DER. |
|
* |
|
* @param pem the PEM-formatted data. |
|
* |
|
* @return the DER-formatted data. |
|
*/ $71c5302ef2ea3950$var$pki.pemToDer = function(pem) { |
|
var msg = $iGlOy.pem.decode(pem)[0]; |
|
if (msg.procType && msg.procType.type === 'ENCRYPTED') throw new Error('Could not convert PEM to DER; PEM is encrypted.'); |
|
return $iGlOy.util.createBuffer(msg.body); |
|
}; |
|
/** |
|
* Converts an RSA private key from PEM format. |
|
* |
|
* @param pem the PEM-formatted private key. |
|
* |
|
* @return the private key. |
|
*/ $71c5302ef2ea3950$var$pki.privateKeyFromPem = function(pem) { |
|
var msg = $iGlOy.pem.decode(pem)[0]; |
|
if (msg.type !== 'PRIVATE KEY' && msg.type !== 'RSA PRIVATE KEY') { |
|
var error = new Error("Could not convert private key from PEM; PEM header type is not \"PRIVATE KEY\" or \"RSA PRIVATE KEY\"."); |
|
error.headerType = msg.type; |
|
throw error; |
|
} |
|
if (msg.procType && msg.procType.type === 'ENCRYPTED') throw new Error('Could not convert private key from PEM; PEM is encrypted.'); |
|
// convert DER to ASN.1 object |
|
var obj = $71c5302ef2ea3950$var$asn1.fromDer(msg.body); |
|
return $71c5302ef2ea3950$var$pki.privateKeyFromAsn1(obj); |
|
}; |
|
/** |
|
* Converts an RSA private key to PEM format. |
|
* |
|
* @param key the private key. |
|
* @param maxline the maximum characters per line, defaults to 64. |
|
* |
|
* @return the PEM-formatted private key. |
|
*/ $71c5302ef2ea3950$var$pki.privateKeyToPem = function(key, maxline) { |
|
// convert to ASN.1, then DER, then PEM-encode |
|
var msg = { |
|
type: 'RSA PRIVATE KEY', |
|
body: $71c5302ef2ea3950$var$asn1.toDer($71c5302ef2ea3950$var$pki.privateKeyToAsn1(key)).getBytes() |
|
}; |
|
return $iGlOy.pem.encode(msg, { |
|
maxline: maxline |
|
}); |
|
}; |
|
/** |
|
* Converts a PrivateKeyInfo to PEM format. |
|
* |
|
* @param pki the PrivateKeyInfo. |
|
* @param maxline the maximum characters per line, defaults to 64. |
|
* |
|
* @return the PEM-formatted private key. |
|
*/ $71c5302ef2ea3950$var$pki.privateKeyInfoToPem = function(pki, maxline) { |
|
// convert to DER, then PEM-encode |
|
var msg = { |
|
type: 'PRIVATE KEY', |
|
body: $71c5302ef2ea3950$var$asn1.toDer(pki).getBytes() |
|
}; |
|
return $iGlOy.pem.encode(msg, { |
|
maxline: maxline |
|
}); |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
* Generates pseudo random bytes by mixing the result of two hash functions, |
|
* MD5 and SHA-1. |
|
* |
|
* prf_TLS1(secret, label, seed) = |
|
* P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed); |
|
* |
|
* Each P_hash function functions as follows: |
|
* |
|
* P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + |
|
* HMAC_hash(secret, A(2) + seed) + |
|
* HMAC_hash(secret, A(3) + seed) + ... |
|
* A() is defined as: |
|
* A(0) = seed |
|
* A(i) = HMAC_hash(secret, A(i-1)) |
|
* |
|
* The '+' operator denotes concatenation. |
|
* |
|
* As many iterations A(N) as are needed are performed to generate enough |
|
* pseudo random byte output. If an iteration creates more data than is |
|
* necessary, then it is truncated. |
|
* |
|
* Therefore: |
|
* A(1) = HMAC_hash(secret, A(0)) |
|
* = HMAC_hash(secret, seed) |
|
* A(2) = HMAC_hash(secret, A(1)) |
|
* = HMAC_hash(secret, HMAC_hash(secret, seed)) |
|
* |
|
* Therefore: |
|
* P_hash(secret, seed) = |
|
* HMAC_hash(secret, HMAC_hash(secret, A(0)) + seed) + |
|
* HMAC_hash(secret, HMAC_hash(secret, A(1)) + seed) + |
|
* ... |
|
* |
|
* Therefore: |
|
* P_hash(secret, seed) = |
|
* HMAC_hash(secret, HMAC_hash(secret, seed) + seed) + |
|
* HMAC_hash(secret, HMAC_hash(secret, HMAC_hash(secret, seed)) + seed) + |
|
* ... |
|
* |
|
* @param secret the secret to use. |
|
* @param label the label to use. |
|
* @param seed the seed value to use. |
|
* @param length the number of bytes to generate. |
|
* |
|
* @return the pseudo random bytes in a byte buffer. |
|
*/ var $e55982d45da68b81$var$prf_TLS1 = function(secret, label, seed, length) { |
|
var rval = $iGlOy.util.createBuffer(); |
|
/* For TLS 1.0, the secret is split in half, into two secrets of equal |
|
length. If the secret has an odd length then the last byte of the first |
|
half will be the same as the first byte of the second. The length of the |
|
two secrets is half of the secret rounded up. */ var idx = secret.length >> 1; |
|
var slen = idx + (secret.length & 1); |
|
var s1 = secret.substr(0, slen); |
|
var s2 = secret.substr(idx, slen); |
|
var ai = $iGlOy.util.createBuffer(); |
|
var hmac = $iGlOy.hmac.create(); |
|
seed = label + seed; |
|
// determine the number of iterations that must be performed to generate |
|
// enough output bytes, md5 creates 16 byte hashes, sha1 creates 20 |
|
var md5itr = Math.ceil(length / 16); |
|
var sha1itr = Math.ceil(length / 20); |
|
// do md5 iterations |
|
hmac.start('MD5', s1); |
|
var md5bytes = $iGlOy.util.createBuffer(); |
|
ai.putBytes(seed); |
|
for(var i = 0; i < md5itr; ++i){ |
|
// HMAC_hash(secret, A(i-1)) |
|
hmac.start(null, null); |
|
hmac.update(ai.getBytes()); |
|
ai.putBuffer(hmac.digest()); |
|
// HMAC_hash(secret, A(i) + seed) |
|
hmac.start(null, null); |
|
hmac.update(ai.bytes() + seed); |
|
md5bytes.putBuffer(hmac.digest()); |
|
} |
|
// do sha1 iterations |
|
hmac.start('SHA1', s2); |
|
var sha1bytes = $iGlOy.util.createBuffer(); |
|
ai.clear(); |
|
ai.putBytes(seed); |
|
for(var i = 0; i < sha1itr; ++i){ |
|
// HMAC_hash(secret, A(i-1)) |
|
hmac.start(null, null); |
|
hmac.update(ai.getBytes()); |
|
ai.putBuffer(hmac.digest()); |
|
// HMAC_hash(secret, A(i) + seed) |
|
hmac.start(null, null); |
|
hmac.update(ai.bytes() + seed); |
|
sha1bytes.putBuffer(hmac.digest()); |
|
} |
|
// XOR the md5 bytes with the sha1 bytes |
|
rval.putBytes($iGlOy.util.xorBytes(md5bytes.getBytes(), sha1bytes.getBytes(), length)); |
|
return rval; |
|
}; |
|
/** |
|
* Generates pseudo random bytes using a SHA256 algorithm. For TLS 1.2. |
|
* |
|
* @param secret the secret to use. |
|
* @param label the label to use. |
|
* @param seed the seed value to use. |
|
* @param length the number of bytes to generate. |
|
* |
|
* @return the pseudo random bytes in a byte buffer. |
|
*/ var $e55982d45da68b81$var$prf_sha256 = function(secret, label, seed, length) { |
|
// FIXME: implement me for TLS 1.2 |
|
}; |
|
/** |
|
* Gets a MAC for a record using the SHA-1 hash algorithm. |
|
* |
|
* @param key the mac key. |
|
* @param state the sequence number (array of two 32-bit integers). |
|
* @param record the record. |
|
* |
|
* @return the sha-1 hash (20 bytes) for the given record. |
|
*/ var $e55982d45da68b81$var$hmac_sha1 = function(key, seqNum, record) { |
|
/* MAC is computed like so: |
|
HMAC_hash( |
|
key, seqNum + |
|
TLSCompressed.type + |
|
TLSCompressed.version + |
|
TLSCompressed.length + |
|
TLSCompressed.fragment) |
|
*/ var hmac = $iGlOy.hmac.create(); |
|
hmac.start('SHA1', key); |
|
var b = $iGlOy.util.createBuffer(); |
|
b.putInt32(seqNum[0]); |
|
b.putInt32(seqNum[1]); |
|
b.putByte(record.type); |
|
b.putByte(record.version.major); |
|
b.putByte(record.version.minor); |
|
b.putInt16(record.length); |
|
b.putBytes(record.fragment.bytes()); |
|
hmac.update(b.getBytes()); |
|
return hmac.digest().getBytes(); |
|
}; |
|
/** |
|
* Compresses the TLSPlaintext record into a TLSCompressed record using the |
|
* deflate algorithm. |
|
* |
|
* @param c the TLS connection. |
|
* @param record the TLSPlaintext record to compress. |
|
* @param s the ConnectionState to use. |
|
* |
|
* @return true on success, false on failure. |
|
*/ var $e55982d45da68b81$var$deflate = function(c, record, s) { |
|
var rval = false; |
|
try { |
|
var bytes = c.deflate(record.fragment.getBytes()); |
|
record.fragment = $iGlOy.util.createBuffer(bytes); |
|
record.length = bytes.length; |
|
rval = true; |
|
} catch (ex) { |
|
// deflate error, fail out |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Decompresses the TLSCompressed record into a TLSPlaintext record using the |
|
* deflate algorithm. |
|
* |
|
* @param c the TLS connection. |
|
* @param record the TLSCompressed record to decompress. |
|
* @param s the ConnectionState to use. |
|
* |
|
* @return true on success, false on failure. |
|
*/ var $e55982d45da68b81$var$inflate = function(c, record, s) { |
|
var rval = false; |
|
try { |
|
var bytes = c.inflate(record.fragment.getBytes()); |
|
record.fragment = $iGlOy.util.createBuffer(bytes); |
|
record.length = bytes.length; |
|
rval = true; |
|
} catch (ex) { |
|
// inflate error, fail out |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Reads a TLS variable-length vector from a byte buffer. |
|
* |
|
* Variable-length vectors are defined by specifying a subrange of legal |
|
* lengths, inclusively, using the notation <floor..ceiling>. When these are |
|
* encoded, the actual length precedes the vector's contents in the byte |
|
* stream. The length will be in the form of a number consuming as many bytes |
|
* as required to hold the vector's specified maximum (ceiling) length. A |
|
* variable-length vector with an actual length field of zero is referred to |
|
* as an empty vector. |
|
* |
|
* @param b the byte buffer. |
|
* @param lenBytes the number of bytes required to store the length. |
|
* |
|
* @return the resulting byte buffer. |
|
*/ var $e55982d45da68b81$var$readVector = function(b, lenBytes) { |
|
var len = 0; |
|
switch(lenBytes){ |
|
case 1: |
|
len = b.getByte(); |
|
break; |
|
case 2: |
|
len = b.getInt16(); |
|
break; |
|
case 3: |
|
len = b.getInt24(); |
|
break; |
|
case 4: |
|
len = b.getInt32(); |
|
break; |
|
} |
|
// read vector bytes into a new buffer |
|
return $iGlOy.util.createBuffer(b.getBytes(len)); |
|
}; |
|
/** |
|
* Writes a TLS variable-length vector to a byte buffer. |
|
* |
|
* @param b the byte buffer. |
|
* @param lenBytes the number of bytes required to store the length. |
|
* @param v the byte buffer vector. |
|
*/ var $e55982d45da68b81$var$writeVector = function(b, lenBytes, v) { |
|
// encode length at the start of the vector, where the number of bytes for |
|
// the length is the maximum number of bytes it would take to encode the |
|
// vector's ceiling |
|
b.putInt(v.length(), lenBytes << 3); |
|
b.putBuffer(v); |
|
}; |
|
/** |
|
* The tls implementation. |
|
*/ var $e55982d45da68b81$var$tls = { |
|
}; |
|
/** |
|
* Version: TLS 1.2 = 3.3, TLS 1.1 = 3.2, TLS 1.0 = 3.1. Both TLS 1.1 and |
|
* TLS 1.2 were still too new (ie: openSSL didn't implement them) at the time |
|
* of this implementation so TLS 1.0 was implemented instead. |
|
*/ $e55982d45da68b81$var$tls.Versions = { |
|
TLS_1_0: { |
|
major: 3, |
|
minor: 1 |
|
}, |
|
TLS_1_1: { |
|
major: 3, |
|
minor: 2 |
|
}, |
|
TLS_1_2: { |
|
major: 3, |
|
minor: 3 |
|
} |
|
}; |
|
$e55982d45da68b81$var$tls.SupportedVersions = [ |
|
$e55982d45da68b81$var$tls.Versions.TLS_1_1, |
|
$e55982d45da68b81$var$tls.Versions.TLS_1_0 |
|
]; |
|
$e55982d45da68b81$var$tls.Version = $e55982d45da68b81$var$tls.SupportedVersions[0]; |
|
/** |
|
* Maximum fragment size. True maximum is 16384, but we fragment before that |
|
* to allow for unusual small increases during compression. |
|
*/ $e55982d45da68b81$var$tls.MaxFragment = 15360; |
|
/** |
|
* Whether this entity is considered the "client" or "server". |
|
* enum { server, client } ConnectionEnd; |
|
*/ $e55982d45da68b81$var$tls.ConnectionEnd = { |
|
server: 0, |
|
client: 1 |
|
}; |
|
/** |
|
* Pseudo-random function algorithm used to generate keys from the master |
|
* secret. |
|
* enum { tls_prf_sha256 } PRFAlgorithm; |
|
*/ $e55982d45da68b81$var$tls.PRFAlgorithm = { |
|
tls_prf_sha256: 0 |
|
}; |
|
/** |
|
* Bulk encryption algorithms. |
|
* enum { null, rc4, des3, aes } BulkCipherAlgorithm; |
|
*/ $e55982d45da68b81$var$tls.BulkCipherAlgorithm = { |
|
none: null, |
|
rc4: 0, |
|
des3: 1, |
|
aes: 2 |
|
}; |
|
/** |
|
* Cipher types. |
|
* enum { stream, block, aead } CipherType; |
|
*/ $e55982d45da68b81$var$tls.CipherType = { |
|
stream: 0, |
|
block: 1, |
|
aead: 2 |
|
}; |
|
/** |
|
* MAC (Message Authentication Code) algorithms. |
|
* enum { null, hmac_md5, hmac_sha1, hmac_sha256, |
|
* hmac_sha384, hmac_sha512} MACAlgorithm; |
|
*/ $e55982d45da68b81$var$tls.MACAlgorithm = { |
|
none: null, |
|
hmac_md5: 0, |
|
hmac_sha1: 1, |
|
hmac_sha256: 2, |
|
hmac_sha384: 3, |
|
hmac_sha512: 4 |
|
}; |
|
/** |
|
* Compression algorithms. |
|
* enum { null(0), deflate(1), (255) } CompressionMethod; |
|
*/ $e55982d45da68b81$var$tls.CompressionMethod = { |
|
none: 0, |
|
deflate: 1 |
|
}; |
|
/** |
|
* TLS record content types. |
|
* enum { |
|
* change_cipher_spec(20), alert(21), handshake(22), |
|
* application_data(23), (255) |
|
* } ContentType; |
|
*/ $e55982d45da68b81$var$tls.ContentType = { |
|
change_cipher_spec: 20, |
|
alert: 21, |
|
handshake: 22, |
|
application_data: 23, |
|
heartbeat: 24 |
|
}; |
|
/** |
|
* TLS handshake types. |
|
* enum { |
|
* hello_request(0), client_hello(1), server_hello(2), |
|
* certificate(11), server_key_exchange (12), |
|
* certificate_request(13), server_hello_done(14), |
|
* certificate_verify(15), client_key_exchange(16), |
|
* finished(20), (255) |
|
* } HandshakeType; |
|
*/ $e55982d45da68b81$var$tls.HandshakeType = { |
|
hello_request: 0, |
|
client_hello: 1, |
|
server_hello: 2, |
|
certificate: 11, |
|
server_key_exchange: 12, |
|
certificate_request: 13, |
|
server_hello_done: 14, |
|
certificate_verify: 15, |
|
client_key_exchange: 16, |
|
finished: 20 |
|
}; |
|
/** |
|
* TLS Alert Protocol. |
|
* |
|
* enum { warning(1), fatal(2), (255) } AlertLevel; |
|
* |
|
* enum { |
|
* close_notify(0), |
|
* unexpected_message(10), |
|
* bad_record_mac(20), |
|
* decryption_failed(21), |
|
* record_overflow(22), |
|
* decompression_failure(30), |
|
* handshake_failure(40), |
|
* bad_certificate(42), |
|
* unsupported_certificate(43), |
|
* certificate_revoked(44), |
|
* certificate_expired(45), |
|
* certificate_unknown(46), |
|
* illegal_parameter(47), |
|
* unknown_ca(48), |
|
* access_denied(49), |
|
* decode_error(50), |
|
* decrypt_error(51), |
|
* export_restriction(60), |
|
* protocol_version(70), |
|
* insufficient_security(71), |
|
* internal_error(80), |
|
* user_canceled(90), |
|
* no_renegotiation(100), |
|
* (255) |
|
* } AlertDescription; |
|
* |
|
* struct { |
|
* AlertLevel level; |
|
* AlertDescription description; |
|
* } Alert; |
|
*/ $e55982d45da68b81$var$tls.Alert = { |
|
}; |
|
$e55982d45da68b81$var$tls.Alert.Level = { |
|
warning: 1, |
|
fatal: 2 |
|
}; |
|
$e55982d45da68b81$var$tls.Alert.Description = { |
|
close_notify: 0, |
|
unexpected_message: 10, |
|
bad_record_mac: 20, |
|
decryption_failed: 21, |
|
record_overflow: 22, |
|
decompression_failure: 30, |
|
handshake_failure: 40, |
|
bad_certificate: 42, |
|
unsupported_certificate: 43, |
|
certificate_revoked: 44, |
|
certificate_expired: 45, |
|
certificate_unknown: 46, |
|
illegal_parameter: 47, |
|
unknown_ca: 48, |
|
access_denied: 49, |
|
decode_error: 50, |
|
decrypt_error: 51, |
|
export_restriction: 60, |
|
protocol_version: 70, |
|
insufficient_security: 71, |
|
internal_error: 80, |
|
user_canceled: 90, |
|
no_renegotiation: 100 |
|
}; |
|
/** |
|
* TLS Heartbeat Message types. |
|
* enum { |
|
* heartbeat_request(1), |
|
* heartbeat_response(2), |
|
* (255) |
|
* } HeartbeatMessageType; |
|
*/ $e55982d45da68b81$var$tls.HeartbeatMessageType = { |
|
heartbeat_request: 1, |
|
heartbeat_response: 2 |
|
}; |
|
/** |
|
* Supported cipher suites. |
|
*/ $e55982d45da68b81$var$tls.CipherSuites = { |
|
}; |
|
/** |
|
* Gets a supported cipher suite from its 2 byte ID. |
|
* |
|
* @param twoBytes two bytes in a string. |
|
* |
|
* @return the matching supported cipher suite or null. |
|
*/ $e55982d45da68b81$var$tls.getCipherSuite = function(twoBytes) { |
|
var rval = null; |
|
for(var key in $e55982d45da68b81$var$tls.CipherSuites){ |
|
var cs = $e55982d45da68b81$var$tls.CipherSuites[key]; |
|
if (cs.id[0] === twoBytes.charCodeAt(0) && cs.id[1] === twoBytes.charCodeAt(1)) { |
|
rval = cs; |
|
break; |
|
} |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Called when an unexpected record is encountered. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
*/ $e55982d45da68b81$var$tls.handleUnexpected = function(c, record) { |
|
// if connection is client and closed, ignore unexpected messages |
|
var ignore = !c.open && c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
if (!ignore) c.error(c, { |
|
message: 'Unexpected message. Received TLS record out of order.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.unexpected_message |
|
} |
|
}); |
|
}; |
|
/** |
|
* Called when a client receives a HelloRequest record. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleHelloRequest = function(c, record, length) { |
|
// ignore renegotiation requests from the server during a handshake, but |
|
// if handshaking, send a warning alert that renegotation is denied |
|
if (!c.handshaking && c.handshakes > 0) { |
|
// send alert warning |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createAlert(c, { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.warning, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.no_renegotiation |
|
})); |
|
$e55982d45da68b81$var$tls.flush(c); |
|
} |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Parses a hello message from a ClientHello or ServerHello record. |
|
* |
|
* @param record the record to parse. |
|
* |
|
* @return the parsed message. |
|
*/ $e55982d45da68b81$var$tls.parseHelloMessage = function(c, record, length) { |
|
var msg = null; |
|
var client = c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
// minimum of 38 bytes in message |
|
if (length < 38) c.error(c, { |
|
message: client ? 'Invalid ServerHello message. Message too short.' : 'Invalid ClientHello message. Message too short.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.illegal_parameter |
|
} |
|
}); |
|
else { |
|
// use 'remaining' to calculate # of remaining bytes in the message |
|
var b = record.fragment; |
|
var remaining = b.length(); |
|
msg = { |
|
version: { |
|
major: b.getByte(), |
|
minor: b.getByte() |
|
}, |
|
random: $iGlOy.util.createBuffer(b.getBytes(32)), |
|
session_id: $e55982d45da68b81$var$readVector(b, 1), |
|
extensions: [] |
|
}; |
|
if (client) { |
|
msg.cipher_suite = b.getBytes(2); |
|
msg.compression_method = b.getByte(); |
|
} else { |
|
msg.cipher_suites = $e55982d45da68b81$var$readVector(b, 2); |
|
msg.compression_methods = $e55982d45da68b81$var$readVector(b, 1); |
|
} |
|
// read extensions if there are any bytes left in the message |
|
remaining = length - (remaining - b.length()); |
|
if (remaining > 0) { |
|
// parse extensions |
|
var exts = $e55982d45da68b81$var$readVector(b, 2); |
|
while(exts.length() > 0)msg.extensions.push({ |
|
type: [ |
|
exts.getByte(), |
|
exts.getByte() |
|
], |
|
data: $e55982d45da68b81$var$readVector(exts, 2) |
|
}); |
|
// TODO: make extension support modular |
|
if (!client) for(var i = 0; i < msg.extensions.length; ++i){ |
|
var ext = msg.extensions[i]; |
|
// support SNI extension |
|
if (ext.type[0] === 0 && ext.type[1] === 0) { |
|
// get server name list |
|
var snl = $e55982d45da68b81$var$readVector(ext.data, 2); |
|
while(snl.length() > 0){ |
|
// read server name type |
|
var snType = snl.getByte(); |
|
// only HostName type (0x00) is known, break out if |
|
// another type is detected |
|
if (snType !== 0) break; |
|
// add host name to server name list |
|
c.session.extensions.server_name.serverNameList.push($e55982d45da68b81$var$readVector(snl, 2).getBytes()); |
|
} |
|
} |
|
} |
|
} |
|
// version already set, do not allow version change |
|
if (c.session.version) { |
|
if (msg.version.major !== c.session.version.major || msg.version.minor !== c.session.version.minor) return c.error(c, { |
|
message: 'TLS version change is disallowed during renegotiation.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.protocol_version |
|
} |
|
}); |
|
} |
|
// get the chosen (ServerHello) cipher suite |
|
if (client) // FIXME: should be checking configured acceptable cipher suites |
|
c.session.cipherSuite = $e55982d45da68b81$var$tls.getCipherSuite(msg.cipher_suite); |
|
else { |
|
// get a supported preferred (ClientHello) cipher suite |
|
// choose the first supported cipher suite |
|
var tmp = $iGlOy.util.createBuffer(msg.cipher_suites.bytes()); |
|
while(tmp.length() > 0){ |
|
// FIXME: should be checking configured acceptable suites |
|
// cipher suites take up 2 bytes |
|
c.session.cipherSuite = $e55982d45da68b81$var$tls.getCipherSuite(tmp.getBytes(2)); |
|
if (c.session.cipherSuite !== null) break; |
|
} |
|
} |
|
// cipher suite not supported |
|
if (c.session.cipherSuite === null) return c.error(c, { |
|
message: 'No cipher suites in common.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.handshake_failure |
|
}, |
|
cipherSuite: $iGlOy.util.bytesToHex(msg.cipher_suite) |
|
}); |
|
// TODO: handle compression methods |
|
if (client) c.session.compressionMethod = msg.compression_method; |
|
else // no compression |
|
c.session.compressionMethod = $e55982d45da68b81$var$tls.CompressionMethod.none; |
|
} |
|
return msg; |
|
}; |
|
/** |
|
* Creates security parameters for the given connection based on the given |
|
* hello message. |
|
* |
|
* @param c the TLS connection. |
|
* @param msg the hello message. |
|
*/ $e55982d45da68b81$var$tls.createSecurityParameters = function(c, msg) { |
|
/* Note: security params are from TLS 1.2, some values like prf_algorithm |
|
are ignored for TLS 1.0/1.1 and the builtin as specified in the spec is |
|
used. */ // TODO: handle other options from server when more supported |
|
// get client and server randoms |
|
var client = c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
var msgRandom = msg.random.bytes(); |
|
var cRandom = client ? c.session.sp.client_random : msgRandom; |
|
var sRandom = client ? msgRandom : $e55982d45da68b81$var$tls.createRandom().getBytes(); |
|
// create new security parameters |
|
c.session.sp = { |
|
entity: c.entity, |
|
prf_algorithm: $e55982d45da68b81$var$tls.PRFAlgorithm.tls_prf_sha256, |
|
bulk_cipher_algorithm: null, |
|
cipher_type: null, |
|
enc_key_length: null, |
|
block_length: null, |
|
fixed_iv_length: null, |
|
record_iv_length: null, |
|
mac_algorithm: null, |
|
mac_length: null, |
|
mac_key_length: null, |
|
compression_algorithm: c.session.compressionMethod, |
|
pre_master_secret: null, |
|
master_secret: null, |
|
client_random: cRandom, |
|
server_random: sRandom |
|
}; |
|
}; |
|
/** |
|
* Called when a client receives a ServerHello record. |
|
* |
|
* When a ServerHello message will be sent: |
|
* The server will send this message in response to a client hello message |
|
* when it was able to find an acceptable set of algorithms. If it cannot |
|
* find such a match, it will respond with a handshake failure alert. |
|
* |
|
* uint24 length; |
|
* struct { |
|
* ProtocolVersion server_version; |
|
* Random random; |
|
* SessionID session_id; |
|
* CipherSuite cipher_suite; |
|
* CompressionMethod compression_method; |
|
* select(extensions_present) { |
|
* case false: |
|
* struct {}; |
|
* case true: |
|
* Extension extensions<0..2^16-1>; |
|
* }; |
|
* } ServerHello; |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleServerHello = function(c, record, length) { |
|
var msg = $e55982d45da68b81$var$tls.parseHelloMessage(c, record, length); |
|
if (c.fail) return; |
|
// ensure server version is compatible |
|
if (msg.version.minor <= c.version.minor) c.version.minor = msg.version.minor; |
|
else return c.error(c, { |
|
message: 'Incompatible TLS version.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.protocol_version |
|
} |
|
}); |
|
// indicate session version has been set |
|
c.session.version = c.version; |
|
// get the session ID from the message |
|
var sessionId = msg.session_id.bytes(); |
|
// if the session ID is not blank and matches the cached one, resume |
|
// the session |
|
if (sessionId.length > 0 && sessionId === c.session.id) { |
|
// resuming session, expect a ChangeCipherSpec next |
|
c.expect = $e55982d45da68b81$var$SCC; |
|
c.session.resuming = true; |
|
// get new server random |
|
c.session.sp.server_random = msg.random.bytes(); |
|
} else { |
|
// not resuming, expect a server Certificate message next |
|
c.expect = $e55982d45da68b81$var$SCE; |
|
c.session.resuming = false; |
|
// create new security parameters |
|
$e55982d45da68b81$var$tls.createSecurityParameters(c, msg); |
|
} |
|
// set new session ID |
|
c.session.id = sessionId; |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a server receives a ClientHello record. |
|
* |
|
* When a ClientHello message will be sent: |
|
* When a client first connects to a server it is required to send the |
|
* client hello as its first message. The client can also send a client |
|
* hello in response to a hello request or on its own initiative in order |
|
* to renegotiate the security parameters in an existing connection. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleClientHello = function(c, record, length) { |
|
var msg = $e55982d45da68b81$var$tls.parseHelloMessage(c, record, length); |
|
if (c.fail) return; |
|
// get the session ID from the message |
|
var sessionId = msg.session_id.bytes(); |
|
// see if the given session ID is in the cache |
|
var session = null; |
|
if (c.sessionCache) { |
|
session = c.sessionCache.getSession(sessionId); |
|
if (session === null) // session ID not found |
|
sessionId = ''; |
|
else if (session.version.major !== msg.version.major || session.version.minor > msg.version.minor) { |
|
// if session version is incompatible with client version, do not resume |
|
session = null; |
|
sessionId = ''; |
|
} |
|
} |
|
// no session found to resume, generate a new session ID |
|
if (sessionId.length === 0) sessionId = $iGlOy.random.getBytes(32); |
|
// update session |
|
c.session.id = sessionId; |
|
c.session.clientHelloVersion = msg.version; |
|
c.session.sp = { |
|
}; |
|
if (session) { |
|
// use version and security parameters from resumed session |
|
c.version = c.session.version = session.version; |
|
c.session.sp = session.sp; |
|
} else { |
|
// use highest compatible minor version |
|
var version; |
|
for(var i = 1; i < $e55982d45da68b81$var$tls.SupportedVersions.length; ++i){ |
|
version = $e55982d45da68b81$var$tls.SupportedVersions[i]; |
|
if (version.minor <= msg.version.minor) break; |
|
} |
|
c.version = { |
|
major: version.major, |
|
minor: version.minor |
|
}; |
|
c.session.version = c.version; |
|
} |
|
// if a session is set, resume it |
|
if (session !== null) { |
|
// resuming session, expect a ChangeCipherSpec next |
|
c.expect = $e55982d45da68b81$var$CCC; |
|
c.session.resuming = true; |
|
// get new client random |
|
c.session.sp.client_random = msg.random.bytes(); |
|
} else { |
|
// not resuming, expect a Certificate or ClientKeyExchange |
|
c.expect = c.verifyClient !== false ? $e55982d45da68b81$var$CCE : $e55982d45da68b81$var$CKE; |
|
c.session.resuming = false; |
|
// create new security parameters |
|
$e55982d45da68b81$var$tls.createSecurityParameters(c, msg); |
|
} |
|
// connection now open |
|
c.open = true; |
|
// queue server hello |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createServerHello(c) |
|
})); |
|
if (c.session.resuming) { |
|
// queue change cipher spec message |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.change_cipher_spec, |
|
data: $e55982d45da68b81$var$tls.createChangeCipherSpec() |
|
})); |
|
// create pending state |
|
c.state.pending = $e55982d45da68b81$var$tls.createConnectionState(c); |
|
// change current write state to pending write state |
|
c.state.current.write = c.state.pending.write; |
|
// queue finished |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createFinished(c) |
|
})); |
|
} else { |
|
// queue server certificate |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createCertificate(c) |
|
})); |
|
if (!c.fail) { |
|
// queue server key exchange |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createServerKeyExchange(c) |
|
})); |
|
// request client certificate if set |
|
if (c.verifyClient !== false) // queue certificate request |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createCertificateRequest(c) |
|
})); |
|
// queue server hello done |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createServerHelloDone(c) |
|
})); |
|
} |
|
} |
|
// send records |
|
$e55982d45da68b81$var$tls.flush(c); |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a client receives a Certificate record. |
|
* |
|
* When this message will be sent: |
|
* The server must send a certificate whenever the agreed-upon key exchange |
|
* method is not an anonymous one. This message will always immediately |
|
* follow the server hello message. |
|
* |
|
* Meaning of this message: |
|
* The certificate type must be appropriate for the selected cipher suite's |
|
* key exchange algorithm, and is generally an X.509v3 certificate. It must |
|
* contain a key which matches the key exchange method, as follows. Unless |
|
* otherwise specified, the signing algorithm for the certificate must be |
|
* the same as the algorithm for the certificate key. Unless otherwise |
|
* specified, the public key may be of any length. |
|
* |
|
* opaque ASN.1Cert<1..2^24-1>; |
|
* struct { |
|
* ASN.1Cert certificate_list<1..2^24-1>; |
|
* } Certificate; |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleCertificate = function(c, record, length) { |
|
// minimum of 3 bytes in message |
|
if (length < 3) return c.error(c, { |
|
message: 'Invalid Certificate message. Message too short.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.illegal_parameter |
|
} |
|
}); |
|
var b = record.fragment; |
|
var msg = { |
|
certificate_list: $e55982d45da68b81$var$readVector(b, 3) |
|
}; |
|
/* The sender's certificate will be first in the list (chain), each |
|
subsequent one that follows will certify the previous one, but root |
|
certificates (self-signed) that specify the certificate authority may |
|
be omitted under the assumption that clients must already possess it. */ var cert, asn1; |
|
var certs = []; |
|
try { |
|
while(msg.certificate_list.length() > 0){ |
|
// each entry in msg.certificate_list is a vector with 3 len bytes |
|
cert = $e55982d45da68b81$var$readVector(msg.certificate_list, 3); |
|
asn1 = $iGlOy.asn1.fromDer(cert); |
|
cert = $iGlOy.pki.certificateFromAsn1(asn1, true); |
|
certs.push(cert); |
|
} |
|
} catch (ex) { |
|
return c.error(c, { |
|
message: 'Could not parse certificate list.', |
|
cause: ex, |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.bad_certificate |
|
} |
|
}); |
|
} |
|
// ensure at least 1 certificate was provided if in client-mode |
|
// or if verifyClient was set to true to require a certificate |
|
// (as opposed to 'optional') |
|
var client = c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
if ((client || c.verifyClient === true) && certs.length === 0) // error, no certificate |
|
c.error(c, { |
|
message: client ? 'No server certificate provided.' : 'No client certificate provided.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.illegal_parameter |
|
} |
|
}); |
|
else if (certs.length === 0) // no certs to verify |
|
// expect a ServerKeyExchange or ClientKeyExchange message next |
|
c.expect = client ? $e55982d45da68b81$var$SKE : $e55982d45da68b81$var$CKE; |
|
else { |
|
// save certificate in session |
|
if (client) c.session.serverCertificate = certs[0]; |
|
else c.session.clientCertificate = certs[0]; |
|
if ($e55982d45da68b81$var$tls.verifyCertificateChain(c, certs)) // expect a ServerKeyExchange or ClientKeyExchange message next |
|
c.expect = client ? $e55982d45da68b81$var$SKE : $e55982d45da68b81$var$CKE; |
|
} |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a client receives a ServerKeyExchange record. |
|
* |
|
* When this message will be sent: |
|
* This message will be sent immediately after the server certificate |
|
* message (or the server hello message, if this is an anonymous |
|
* negotiation). |
|
* |
|
* The server key exchange message is sent by the server only when the |
|
* server certificate message (if sent) does not contain enough data to |
|
* allow the client to exchange a premaster secret. |
|
* |
|
* Meaning of this message: |
|
* This message conveys cryptographic information to allow the client to |
|
* communicate the premaster secret: either an RSA public key to encrypt |
|
* the premaster secret with, or a Diffie-Hellman public key with which the |
|
* client can complete a key exchange (with the result being the premaster |
|
* secret.) |
|
* |
|
* enum { |
|
* dhe_dss, dhe_rsa, dh_anon, rsa, dh_dss, dh_rsa |
|
* } KeyExchangeAlgorithm; |
|
* |
|
* struct { |
|
* opaque dh_p<1..2^16-1>; |
|
* opaque dh_g<1..2^16-1>; |
|
* opaque dh_Ys<1..2^16-1>; |
|
* } ServerDHParams; |
|
* |
|
* struct { |
|
* select(KeyExchangeAlgorithm) { |
|
* case dh_anon: |
|
* ServerDHParams params; |
|
* case dhe_dss: |
|
* case dhe_rsa: |
|
* ServerDHParams params; |
|
* digitally-signed struct { |
|
* opaque client_random[32]; |
|
* opaque server_random[32]; |
|
* ServerDHParams params; |
|
* } signed_params; |
|
* case rsa: |
|
* case dh_dss: |
|
* case dh_rsa: |
|
* struct {}; |
|
* }; |
|
* } ServerKeyExchange; |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleServerKeyExchange = function(c, record, length) { |
|
// this implementation only supports RSA, no Diffie-Hellman support |
|
// so any length > 0 is invalid |
|
if (length > 0) return c.error(c, { |
|
message: 'Invalid key parameters. Only RSA is supported.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.unsupported_certificate |
|
} |
|
}); |
|
// expect an optional CertificateRequest message next |
|
c.expect = $e55982d45da68b81$var$SCR; |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a client receives a ClientKeyExchange record. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleClientKeyExchange = function(c, record, length) { |
|
// this implementation only supports RSA, no Diffie-Hellman support |
|
// so any length < 48 is invalid |
|
if (length < 48) return c.error(c, { |
|
message: 'Invalid key parameters. Only RSA is supported.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.unsupported_certificate |
|
} |
|
}); |
|
var b = record.fragment; |
|
var msg = { |
|
enc_pre_master_secret: $e55982d45da68b81$var$readVector(b, 2).getBytes() |
|
}; |
|
// do rsa decryption |
|
var privateKey = null; |
|
if (c.getPrivateKey) try { |
|
privateKey = c.getPrivateKey(c, c.session.serverCertificate); |
|
privateKey = $iGlOy.pki.privateKeyFromPem(privateKey); |
|
} catch (ex) { |
|
c.error(c, { |
|
message: 'Could not get private key.', |
|
cause: ex, |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.internal_error |
|
} |
|
}); |
|
} |
|
if (privateKey === null) return c.error(c, { |
|
message: 'No private key set.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.internal_error |
|
} |
|
}); |
|
try { |
|
// decrypt 48-byte pre-master secret |
|
var sp = c.session.sp; |
|
sp.pre_master_secret = privateKey.decrypt(msg.enc_pre_master_secret); |
|
// ensure client hello version matches first 2 bytes |
|
var version = c.session.clientHelloVersion; |
|
if (version.major !== sp.pre_master_secret.charCodeAt(0) || version.minor !== sp.pre_master_secret.charCodeAt(1)) // error, do not send alert (see BLEI attack below) |
|
throw new Error('TLS version rollback attack detected.'); |
|
} catch (ex1) { |
|
/* Note: Daniel Bleichenbacher [BLEI] can be used to attack a |
|
TLS server which is using PKCS#1 encoded RSA, so instead of |
|
failing here, we generate 48 random bytes and use that as |
|
the pre-master secret. */ sp.pre_master_secret = $iGlOy.random.getBytes(48); |
|
} |
|
// expect a CertificateVerify message if a Certificate was received that |
|
// does not have fixed Diffie-Hellman params, otherwise expect |
|
// ChangeCipherSpec |
|
c.expect = $e55982d45da68b81$var$CCC; |
|
if (c.session.clientCertificate !== null) // only RSA support, so expect CertificateVerify |
|
// TODO: support Diffie-Hellman |
|
c.expect = $e55982d45da68b81$var$CCV; |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a client receives a CertificateRequest record. |
|
* |
|
* When this message will be sent: |
|
* A non-anonymous server can optionally request a certificate from the |
|
* client, if appropriate for the selected cipher suite. This message, if |
|
* sent, will immediately follow the Server Key Exchange message (if it is |
|
* sent; otherwise, the Server Certificate message). |
|
* |
|
* enum { |
|
* rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), |
|
* rsa_ephemeral_dh_RESERVED(5), dss_ephemeral_dh_RESERVED(6), |
|
* fortezza_dms_RESERVED(20), (255) |
|
* } ClientCertificateType; |
|
* |
|
* opaque DistinguishedName<1..2^16-1>; |
|
* |
|
* struct { |
|
* ClientCertificateType certificate_types<1..2^8-1>; |
|
* SignatureAndHashAlgorithm supported_signature_algorithms<2^16-1>; |
|
* DistinguishedName certificate_authorities<0..2^16-1>; |
|
* } CertificateRequest; |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleCertificateRequest = function(c, record, length) { |
|
// minimum of 3 bytes in message |
|
if (length < 3) return c.error(c, { |
|
message: 'Invalid CertificateRequest. Message too short.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.illegal_parameter |
|
} |
|
}); |
|
// TODO: TLS 1.2+ has different format including |
|
// SignatureAndHashAlgorithm after cert types |
|
var b = record.fragment; |
|
var msg = { |
|
certificate_types: $e55982d45da68b81$var$readVector(b, 1), |
|
certificate_authorities: $e55982d45da68b81$var$readVector(b, 2) |
|
}; |
|
// save certificate request in session |
|
c.session.certificateRequest = msg; |
|
// expect a ServerHelloDone message next |
|
c.expect = $e55982d45da68b81$var$SHD; |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a server receives a CertificateVerify record. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleCertificateVerify = function(c, record, length) { |
|
if (length < 2) return c.error(c, { |
|
message: 'Invalid CertificateVerify. Message too short.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.illegal_parameter |
|
} |
|
}); |
|
// rewind to get full bytes for message so it can be manually |
|
// digested below (special case for CertificateVerify messages because |
|
// they must be digested *after* handling as opposed to all others) |
|
var b = record.fragment; |
|
b.read -= 4; |
|
var msgBytes = b.bytes(); |
|
b.read += 4; |
|
var msg = { |
|
signature: $e55982d45da68b81$var$readVector(b, 2).getBytes() |
|
}; |
|
// TODO: add support for DSA |
|
// generate data to verify |
|
var verify = $iGlOy.util.createBuffer(); |
|
verify.putBuffer(c.session.md5.digest()); |
|
verify.putBuffer(c.session.sha1.digest()); |
|
verify = verify.getBytes(); |
|
try { |
|
var cert = c.session.clientCertificate; |
|
/*b = forge.pki.rsa.decrypt( |
|
msg.signature, cert.publicKey, true, verify.length); |
|
if(b !== verify) {*/ if (!cert.publicKey.verify(verify, msg.signature, 'NONE')) throw new Error('CertificateVerify signature does not match.'); |
|
// digest message now that it has been handled |
|
c.session.md5.update(msgBytes); |
|
c.session.sha1.update(msgBytes); |
|
} catch (ex) { |
|
return c.error(c, { |
|
message: 'Bad signature in CertificateVerify.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.handshake_failure |
|
} |
|
}); |
|
} |
|
// expect ChangeCipherSpec |
|
c.expect = $e55982d45da68b81$var$CCC; |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a client receives a ServerHelloDone record. |
|
* |
|
* When this message will be sent: |
|
* The server hello done message is sent by the server to indicate the end |
|
* of the server hello and associated messages. After sending this message |
|
* the server will wait for a client response. |
|
* |
|
* Meaning of this message: |
|
* This message means that the server is done sending messages to support |
|
* the key exchange, and the client can proceed with its phase of the key |
|
* exchange. |
|
* |
|
* Upon receipt of the server hello done message the client should verify |
|
* that the server provided a valid certificate if required and check that |
|
* the server hello parameters are acceptable. |
|
* |
|
* struct {} ServerHelloDone; |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleServerHelloDone = function(c1, record, length) { |
|
// len must be 0 bytes |
|
if (length > 0) return c1.error(c1, { |
|
message: 'Invalid ServerHelloDone message. Invalid length.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.record_overflow |
|
} |
|
}); |
|
if (c1.serverCertificate === null) { |
|
// no server certificate was provided |
|
var error = { |
|
message: 'No server certificate provided. Not enough security.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.insufficient_security |
|
} |
|
}; |
|
// call application callback |
|
var depth = 0; |
|
var ret = c1.verify(c1, error.alert.description, depth, []); |
|
if (ret !== true) { |
|
// check for custom alert info |
|
if (ret || ret === 0) { |
|
// set custom message and alert description |
|
if (typeof ret === 'object' && !$iGlOy.util.isArray(ret)) { |
|
if (ret.message) error.message = ret.message; |
|
if (ret.alert) error.alert.description = ret.alert; |
|
} else if (typeof ret === 'number') // set custom alert description |
|
error.alert.description = ret; |
|
} |
|
// send error |
|
return c1.error(c1, error); |
|
} |
|
} |
|
// create client certificate message if requested |
|
if (c1.session.certificateRequest !== null) { |
|
record = $e55982d45da68b81$var$tls.createRecord(c1, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createCertificate(c1) |
|
}); |
|
$e55982d45da68b81$var$tls.queue(c1, record); |
|
} |
|
// create client key exchange message |
|
record = $e55982d45da68b81$var$tls.createRecord(c1, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createClientKeyExchange(c1) |
|
}); |
|
$e55982d45da68b81$var$tls.queue(c1, record); |
|
// expect no messages until the following callback has been called |
|
c1.expect = $e55982d45da68b81$var$SER; |
|
// create callback to handle client signature (for client-certs) |
|
var callback = function(c, signature) { |
|
if (c.session.certificateRequest !== null && c.session.clientCertificate !== null) // create certificate verify message |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createCertificateVerify(c, signature) |
|
})); |
|
// create change cipher spec message |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.change_cipher_spec, |
|
data: $e55982d45da68b81$var$tls.createChangeCipherSpec() |
|
})); |
|
// create pending state |
|
c.state.pending = $e55982d45da68b81$var$tls.createConnectionState(c); |
|
// change current write state to pending write state |
|
c.state.current.write = c.state.pending.write; |
|
// create finished message |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createFinished(c) |
|
})); |
|
// expect a server ChangeCipherSpec message next |
|
c.expect = $e55982d45da68b81$var$SCC; |
|
// send records |
|
$e55982d45da68b81$var$tls.flush(c); |
|
// continue |
|
c.process(); |
|
}; |
|
// if there is no certificate request or no client certificate, do |
|
// callback immediately |
|
if (c1.session.certificateRequest === null || c1.session.clientCertificate === null) return callback(c1, null); |
|
// otherwise get the client signature |
|
$e55982d45da68b81$var$tls.getClientSignature(c1, callback); |
|
}; |
|
/** |
|
* Called when a ChangeCipherSpec record is received. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
*/ $e55982d45da68b81$var$tls.handleChangeCipherSpec = function(c, record) { |
|
if (record.fragment.getByte() !== 1) return c.error(c, { |
|
message: 'Invalid ChangeCipherSpec message received.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.illegal_parameter |
|
} |
|
}); |
|
// create pending state if: |
|
// 1. Resuming session in client mode OR |
|
// 2. NOT resuming session in server mode |
|
var client = c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
if (c.session.resuming && client || !c.session.resuming && !client) c.state.pending = $e55982d45da68b81$var$tls.createConnectionState(c); |
|
// change current read state to pending read state |
|
c.state.current.read = c.state.pending.read; |
|
// clear pending state if: |
|
// 1. NOT resuming session in client mode OR |
|
// 2. resuming a session in server mode |
|
if (!c.session.resuming && client || c.session.resuming && !client) c.state.pending = null; |
|
// expect a Finished record next |
|
c.expect = client ? $e55982d45da68b81$var$SFI : $e55982d45da68b81$var$CFI; |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a Finished record is received. |
|
* |
|
* When this message will be sent: |
|
* A finished message is always sent immediately after a change |
|
* cipher spec message to verify that the key exchange and |
|
* authentication processes were successful. It is essential that a |
|
* change cipher spec message be received between the other |
|
* handshake messages and the Finished message. |
|
* |
|
* Meaning of this message: |
|
* The finished message is the first protected with the just- |
|
* negotiated algorithms, keys, and secrets. Recipients of finished |
|
* messages must verify that the contents are correct. Once a side |
|
* has sent its Finished message and received and validated the |
|
* Finished message from its peer, it may begin to send and receive |
|
* application data over the connection. |
|
* |
|
* struct { |
|
* opaque verify_data[verify_data_length]; |
|
* } Finished; |
|
* |
|
* verify_data |
|
* PRF(master_secret, finished_label, Hash(handshake_messages)) |
|
* [0..verify_data_length-1]; |
|
* |
|
* finished_label |
|
* For Finished messages sent by the client, the string |
|
* "client finished". For Finished messages sent by the server, the |
|
* string "server finished". |
|
* |
|
* verify_data_length depends on the cipher suite. If it is not specified |
|
* by the cipher suite, then it is 12. Versions of TLS < 1.2 always used |
|
* 12 bytes. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
* @param length the length of the handshake message. |
|
*/ $e55982d45da68b81$var$tls.handleFinished = function(c, record, length) { |
|
// rewind to get full bytes for message so it can be manually |
|
// digested below (special case for Finished messages because they |
|
// must be digested *after* handling as opposed to all others) |
|
var b = record.fragment; |
|
b.read -= 4; |
|
var msgBytes = b.bytes(); |
|
b.read += 4; |
|
// message contains only verify_data |
|
var vd = record.fragment.getBytes(); |
|
// ensure verify data is correct |
|
b = $iGlOy.util.createBuffer(); |
|
b.putBuffer(c.session.md5.digest()); |
|
b.putBuffer(c.session.sha1.digest()); |
|
// set label based on entity type |
|
var client = c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
var label = client ? 'server finished' : 'client finished'; |
|
// TODO: determine prf function and verify length for TLS 1.2 |
|
var sp = c.session.sp; |
|
var vdl = 12; |
|
var prf = $e55982d45da68b81$var$prf_TLS1; |
|
b = prf(sp.master_secret, label, b.getBytes(), vdl); |
|
if (b.getBytes() !== vd) return c.error(c, { |
|
message: 'Invalid verify_data in Finished message.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.decrypt_error |
|
} |
|
}); |
|
// digest finished message now that it has been handled |
|
c.session.md5.update(msgBytes); |
|
c.session.sha1.update(msgBytes); |
|
// resuming session as client or NOT resuming session as server |
|
if (c.session.resuming && client || !c.session.resuming && !client) { |
|
// create change cipher spec message |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.change_cipher_spec, |
|
data: $e55982d45da68b81$var$tls.createChangeCipherSpec() |
|
})); |
|
// change current write state to pending write state, clear pending |
|
c.state.current.write = c.state.pending.write; |
|
c.state.pending = null; |
|
// create finished message |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createFinished(c) |
|
})); |
|
} |
|
// expect application data next |
|
c.expect = client ? $e55982d45da68b81$var$SAD : $e55982d45da68b81$var$CAD; |
|
// handshake complete |
|
c.handshaking = false; |
|
++c.handshakes; |
|
// save access to peer certificate |
|
c.peerCertificate = client ? c.session.serverCertificate : c.session.clientCertificate; |
|
// send records |
|
$e55982d45da68b81$var$tls.flush(c); |
|
// now connected |
|
c.isConnected = true; |
|
c.connected(c); |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when an Alert record is received. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
*/ $e55982d45da68b81$var$tls.handleAlert = function(c, record) { |
|
// read alert |
|
var b = record.fragment; |
|
var alert = { |
|
level: b.getByte(), |
|
description: b.getByte() |
|
}; |
|
// TODO: consider using a table? |
|
// get appropriate message |
|
var msg; |
|
switch(alert.description){ |
|
case $e55982d45da68b81$var$tls.Alert.Description.close_notify: |
|
msg = 'Connection closed.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.unexpected_message: |
|
msg = 'Unexpected message.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.bad_record_mac: |
|
msg = 'Bad record MAC.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.decryption_failed: |
|
msg = 'Decryption failed.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.record_overflow: |
|
msg = 'Record overflow.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.decompression_failure: |
|
msg = 'Decompression failed.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.handshake_failure: |
|
msg = 'Handshake failure.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.bad_certificate: |
|
msg = 'Bad certificate.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.unsupported_certificate: |
|
msg = 'Unsupported certificate.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.certificate_revoked: |
|
msg = 'Certificate revoked.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.certificate_expired: |
|
msg = 'Certificate expired.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.certificate_unknown: |
|
msg = 'Certificate unknown.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.illegal_parameter: |
|
msg = 'Illegal parameter.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.unknown_ca: |
|
msg = 'Unknown certificate authority.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.access_denied: |
|
msg = 'Access denied.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.decode_error: |
|
msg = 'Decode error.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.decrypt_error: |
|
msg = 'Decrypt error.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.export_restriction: |
|
msg = 'Export restriction.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.protocol_version: |
|
msg = 'Unsupported protocol version.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.insufficient_security: |
|
msg = 'Insufficient security.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.internal_error: |
|
msg = 'Internal error.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.user_canceled: |
|
msg = 'User canceled.'; |
|
break; |
|
case $e55982d45da68b81$var$tls.Alert.Description.no_renegotiation: |
|
msg = 'Renegotiation not supported.'; |
|
break; |
|
default: |
|
msg = 'Unknown error.'; |
|
break; |
|
} |
|
// close connection on close_notify, not an error |
|
if (alert.description === $e55982d45da68b81$var$tls.Alert.Description.close_notify) return c.close(); |
|
// call error handler |
|
c.error(c, { |
|
message: msg, |
|
send: false, |
|
// origin is the opposite end |
|
origin: c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client ? 'server' : 'client', |
|
alert: alert |
|
}); |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a Handshake record is received. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
*/ $e55982d45da68b81$var$tls.handleHandshake = function(c, record) { |
|
// get the handshake type and message length |
|
var b = record.fragment; |
|
var type = b.getByte(); |
|
var length = b.getInt24(); |
|
// see if the record fragment doesn't yet contain the full message |
|
if (length > b.length()) { |
|
// cache the record, clear its fragment, and reset the buffer read |
|
// pointer before the type and length were read |
|
c.fragmented = record; |
|
record.fragment = $iGlOy.util.createBuffer(); |
|
b.read -= 4; |
|
// continue |
|
return c.process(); |
|
} |
|
// full message now available, clear cache, reset read pointer to |
|
// before type and length |
|
c.fragmented = null; |
|
b.read -= 4; |
|
// save the handshake bytes for digestion after handler is found |
|
// (include type and length of handshake msg) |
|
var bytes = b.bytes(length + 4); |
|
// restore read pointer |
|
b.read += 4; |
|
// handle expected message |
|
if (type in $e55982d45da68b81$var$hsTable[c.entity][c.expect]) { |
|
// initialize server session |
|
if (c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.server && !c.open && !c.fail) { |
|
c.handshaking = true; |
|
c.session = { |
|
version: null, |
|
extensions: { |
|
server_name: { |
|
serverNameList: [] |
|
} |
|
}, |
|
cipherSuite: null, |
|
compressionMethod: null, |
|
serverCertificate: null, |
|
clientCertificate: null, |
|
md5: $iGlOy.md.md5.create(), |
|
sha1: $iGlOy.md.sha1.create() |
|
}; |
|
} |
|
/* Update handshake messages digest. Finished and CertificateVerify |
|
messages are not digested here. They can't be digested as part of |
|
the verify_data that they contain. These messages are manually |
|
digested in their handlers. HelloRequest messages are simply never |
|
included in the handshake message digest according to spec. */ if (type !== $e55982d45da68b81$var$tls.HandshakeType.hello_request && type !== $e55982d45da68b81$var$tls.HandshakeType.certificate_verify && type !== $e55982d45da68b81$var$tls.HandshakeType.finished) { |
|
c.session.md5.update(bytes); |
|
c.session.sha1.update(bytes); |
|
} |
|
// handle specific handshake type record |
|
$e55982d45da68b81$var$hsTable[c.entity][c.expect][type](c, record, length); |
|
} else // unexpected record |
|
$e55982d45da68b81$var$tls.handleUnexpected(c, record); |
|
}; |
|
/** |
|
* Called when an ApplicationData record is received. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
*/ $e55982d45da68b81$var$tls.handleApplicationData = function(c, record) { |
|
// buffer data, notify that its ready |
|
c.data.putBuffer(record.fragment); |
|
c.dataReady(c); |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* Called when a Heartbeat record is received. |
|
* |
|
* @param c the connection. |
|
* @param record the record. |
|
*/ $e55982d45da68b81$var$tls.handleHeartbeat = function(c, record) { |
|
// get the heartbeat type and payload |
|
var b = record.fragment; |
|
var type = b.getByte(); |
|
var length = b.getInt16(); |
|
var payload = b.getBytes(length); |
|
if (type === $e55982d45da68b81$var$tls.HeartbeatMessageType.heartbeat_request) { |
|
// discard request during handshake or if length is too large |
|
if (c.handshaking || length > payload.length) // continue |
|
return c.process(); |
|
// retransmit payload |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.heartbeat, |
|
data: $e55982d45da68b81$var$tls.createHeartbeat($e55982d45da68b81$var$tls.HeartbeatMessageType.heartbeat_response, payload) |
|
})); |
|
$e55982d45da68b81$var$tls.flush(c); |
|
} else if (type === $e55982d45da68b81$var$tls.HeartbeatMessageType.heartbeat_response) { |
|
// check payload against expected payload, discard heartbeat if no match |
|
if (payload !== c.expectedHeartbeatPayload) // continue |
|
return c.process(); |
|
// notify that a valid heartbeat was received |
|
if (c.heartbeatReceived) c.heartbeatReceived(c, $iGlOy.util.createBuffer(payload)); |
|
} |
|
// continue |
|
c.process(); |
|
}; |
|
/** |
|
* The transistional state tables for receiving TLS records. It maps the |
|
* current TLS engine state and a received record to a function to handle the |
|
* record and update the state. |
|
* |
|
* For instance, if the current state is SHE, then the TLS engine is expecting |
|
* a ServerHello record. Once a record is received, the handler function is |
|
* looked up using the state SHE and the record's content type. |
|
* |
|
* The resulting function will either be an error handler or a record handler. |
|
* The function will take whatever action is appropriate and update the state |
|
* for the next record. |
|
* |
|
* The states are all based on possible server record types. Note that the |
|
* client will never specifically expect to receive a HelloRequest or an alert |
|
* from the server so there is no state that reflects this. These messages may |
|
* occur at any time. |
|
* |
|
* There are two tables for mapping states because there is a second tier of |
|
* types for handshake messages. Once a record with a content type of handshake |
|
* is received, the handshake record handler will look up the handshake type in |
|
* the secondary map to get its appropriate handler. |
|
* |
|
* Valid message orders are as follows: |
|
* |
|
* =======================FULL HANDSHAKE====================== |
|
* Client Server |
|
* |
|
* ClientHello --------> |
|
* ServerHello |
|
* Certificate* |
|
* ServerKeyExchange* |
|
* CertificateRequest* |
|
* <-------- ServerHelloDone |
|
* Certificate* |
|
* ClientKeyExchange |
|
* CertificateVerify* |
|
* [ChangeCipherSpec] |
|
* Finished --------> |
|
* [ChangeCipherSpec] |
|
* <-------- Finished |
|
* Application Data <-------> Application Data |
|
* |
|
* =====================SESSION RESUMPTION===================== |
|
* Client Server |
|
* |
|
* ClientHello --------> |
|
* ServerHello |
|
* [ChangeCipherSpec] |
|
* <-------- Finished |
|
* [ChangeCipherSpec] |
|
* Finished --------> |
|
* Application Data <-------> Application Data |
|
*/ // client expect states (indicate which records are expected to be received) |
|
var $e55982d45da68b81$var$SHE = 0; // rcv server hello |
|
var $e55982d45da68b81$var$SCE = 1; // rcv server certificate |
|
var $e55982d45da68b81$var$SKE = 2; // rcv server key exchange |
|
var $e55982d45da68b81$var$SCR = 3; // rcv certificate request |
|
var $e55982d45da68b81$var$SHD = 4; // rcv server hello done |
|
var $e55982d45da68b81$var$SCC = 5; // rcv change cipher spec |
|
var $e55982d45da68b81$var$SFI = 6; // rcv finished |
|
var $e55982d45da68b81$var$SAD = 7; // rcv application data |
|
var $e55982d45da68b81$var$SER = 8; // not expecting any messages at this point |
|
// server expect states |
|
var $e55982d45da68b81$var$CHE = 0; // rcv client hello |
|
var $e55982d45da68b81$var$CCE = 1; // rcv client certificate |
|
var $e55982d45da68b81$var$CKE = 2; // rcv client key exchange |
|
var $e55982d45da68b81$var$CCV = 3; // rcv certificate verify |
|
var $e55982d45da68b81$var$CCC = 4; // rcv change cipher spec |
|
var $e55982d45da68b81$var$CFI = 5; // rcv finished |
|
var $e55982d45da68b81$var$CAD = 6; // rcv application data |
|
var $e55982d45da68b81$var$CER = 7; // not expecting any messages at this point |
|
// map client current expect state and content type to function |
|
var $e55982d45da68b81$var$__ = $e55982d45da68b81$var$tls.handleUnexpected; |
|
var $e55982d45da68b81$var$R0 = $e55982d45da68b81$var$tls.handleChangeCipherSpec; |
|
var $e55982d45da68b81$var$R1 = $e55982d45da68b81$var$tls.handleAlert; |
|
var $e55982d45da68b81$var$R2 = $e55982d45da68b81$var$tls.handleHandshake; |
|
var $e55982d45da68b81$var$R3 = $e55982d45da68b81$var$tls.handleApplicationData; |
|
var $e55982d45da68b81$var$R4 = $e55982d45da68b81$var$tls.handleHeartbeat; |
|
var $e55982d45da68b81$var$ctTable = []; |
|
$e55982d45da68b81$var$ctTable[$e55982d45da68b81$var$tls.ConnectionEnd.client] = [ |
|
// CC,AL,HS,AD,HB |
|
/*SHE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*SCE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*SKE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*SCR*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*SHD*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*SCC*/ [ |
|
$e55982d45da68b81$var$R0, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*SFI*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*SAD*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$R3, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*SER*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
] |
|
]; |
|
// map server current expect state and content type to function |
|
$e55982d45da68b81$var$ctTable[$e55982d45da68b81$var$tls.ConnectionEnd.server] = [ |
|
// CC,AL,HS,AD |
|
/*CHE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*CCE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*CKE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*CCV*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*CCC*/ [ |
|
$e55982d45da68b81$var$R0, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*CFI*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*CAD*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$R3, |
|
$e55982d45da68b81$var$R4 |
|
], |
|
/*CER*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R1, |
|
$e55982d45da68b81$var$R2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$R4 |
|
] |
|
]; |
|
// map client current expect state and handshake type to function |
|
var $e55982d45da68b81$var$H0 = $e55982d45da68b81$var$tls.handleHelloRequest; |
|
var $e55982d45da68b81$var$H1 = $e55982d45da68b81$var$tls.handleServerHello; |
|
var $e55982d45da68b81$var$H2 = $e55982d45da68b81$var$tls.handleCertificate; |
|
var $e55982d45da68b81$var$H3 = $e55982d45da68b81$var$tls.handleServerKeyExchange; |
|
var $e55982d45da68b81$var$H4 = $e55982d45da68b81$var$tls.handleCertificateRequest; |
|
var $e55982d45da68b81$var$H5 = $e55982d45da68b81$var$tls.handleServerHelloDone; |
|
var $e55982d45da68b81$var$H6 = $e55982d45da68b81$var$tls.handleFinished; |
|
var $e55982d45da68b81$var$hsTable = []; |
|
$e55982d45da68b81$var$hsTable[$e55982d45da68b81$var$tls.ConnectionEnd.client] = [ |
|
// HR,01,SH,03,04,05,06,07,08,09,10,SC,SK,CR,HD,15,CK,17,18,19,FI |
|
/*SHE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H1, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*SCE*/ [ |
|
$e55982d45da68b81$var$H0, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H2, |
|
$e55982d45da68b81$var$H3, |
|
$e55982d45da68b81$var$H4, |
|
$e55982d45da68b81$var$H5, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*SKE*/ [ |
|
$e55982d45da68b81$var$H0, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H3, |
|
$e55982d45da68b81$var$H4, |
|
$e55982d45da68b81$var$H5, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*SCR*/ [ |
|
$e55982d45da68b81$var$H0, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H4, |
|
$e55982d45da68b81$var$H5, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*SHD*/ [ |
|
$e55982d45da68b81$var$H0, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H5, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*SCC*/ [ |
|
$e55982d45da68b81$var$H0, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*SFI*/ [ |
|
$e55982d45da68b81$var$H0, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H6 |
|
], |
|
/*SAD*/ [ |
|
$e55982d45da68b81$var$H0, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*SER*/ [ |
|
$e55982d45da68b81$var$H0, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
] |
|
]; |
|
// map server current expect state and handshake type to function |
|
// Note: CAD[CH] does not map to FB because renegotation is prohibited |
|
var $e55982d45da68b81$var$H7 = $e55982d45da68b81$var$tls.handleClientHello; |
|
var $e55982d45da68b81$var$H8 = $e55982d45da68b81$var$tls.handleClientKeyExchange; |
|
var $e55982d45da68b81$var$H9 = $e55982d45da68b81$var$tls.handleCertificateVerify; |
|
$e55982d45da68b81$var$hsTable[$e55982d45da68b81$var$tls.ConnectionEnd.server] = [ |
|
// 01,CH,02,03,04,05,06,07,08,09,10,CC,12,13,14,CV,CK,17,18,19,FI |
|
/*CHE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H7, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*CCE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H2, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*CKE*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H8, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*CCV*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H9, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*CCC*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*CFI*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$H6 |
|
], |
|
/*CAD*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
], |
|
/*CER*/ [ |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__, |
|
$e55982d45da68b81$var$__ |
|
] |
|
]; |
|
/** |
|
* Generates the master_secret and keys using the given security parameters. |
|
* |
|
* The security parameters for a TLS connection state are defined as such: |
|
* |
|
* struct { |
|
* ConnectionEnd entity; |
|
* PRFAlgorithm prf_algorithm; |
|
* BulkCipherAlgorithm bulk_cipher_algorithm; |
|
* CipherType cipher_type; |
|
* uint8 enc_key_length; |
|
* uint8 block_length; |
|
* uint8 fixed_iv_length; |
|
* uint8 record_iv_length; |
|
* MACAlgorithm mac_algorithm; |
|
* uint8 mac_length; |
|
* uint8 mac_key_length; |
|
* CompressionMethod compression_algorithm; |
|
* opaque master_secret[48]; |
|
* opaque client_random[32]; |
|
* opaque server_random[32]; |
|
* } SecurityParameters; |
|
* |
|
* Note that this definition is from TLS 1.2. In TLS 1.0 some of these |
|
* parameters are ignored because, for instance, the PRFAlgorithm is a |
|
* builtin-fixed algorithm combining iterations of MD5 and SHA-1 in TLS 1.0. |
|
* |
|
* The Record Protocol requires an algorithm to generate keys required by the |
|
* current connection state. |
|
* |
|
* The master secret is expanded into a sequence of secure bytes, which is then |
|
* split to a client write MAC key, a server write MAC key, a client write |
|
* encryption key, and a server write encryption key. In TLS 1.0 a client write |
|
* IV and server write IV are also generated. Each of these is generated from |
|
* the byte sequence in that order. Unused values are empty. In TLS 1.2, some |
|
* AEAD ciphers may additionally require a client write IV and a server write |
|
* IV (see Section 6.2.3.3). |
|
* |
|
* When keys, MAC keys, and IVs are generated, the master secret is used as an |
|
* entropy source. |
|
* |
|
* To generate the key material, compute: |
|
* |
|
* master_secret = PRF(pre_master_secret, "master secret", |
|
* ClientHello.random + ServerHello.random) |
|
* |
|
* key_block = PRF(SecurityParameters.master_secret, |
|
* "key expansion", |
|
* SecurityParameters.server_random + |
|
* SecurityParameters.client_random); |
|
* |
|
* until enough output has been generated. Then, the key_block is |
|
* partitioned as follows: |
|
* |
|
* client_write_MAC_key[SecurityParameters.mac_key_length] |
|
* server_write_MAC_key[SecurityParameters.mac_key_length] |
|
* client_write_key[SecurityParameters.enc_key_length] |
|
* server_write_key[SecurityParameters.enc_key_length] |
|
* client_write_IV[SecurityParameters.fixed_iv_length] |
|
* server_write_IV[SecurityParameters.fixed_iv_length] |
|
* |
|
* In TLS 1.2, the client_write_IV and server_write_IV are only generated for |
|
* implicit nonce techniques as described in Section 3.2.1 of [AEAD]. This |
|
* implementation uses TLS 1.0 so IVs are generated. |
|
* |
|
* Implementation note: The currently defined cipher suite which requires the |
|
* most material is AES_256_CBC_SHA256. It requires 2 x 32 byte keys and 2 x 32 |
|
* byte MAC keys, for a total 128 bytes of key material. In TLS 1.0 it also |
|
* requires 2 x 16 byte IVs, so it actually takes 160 bytes of key material. |
|
* |
|
* @param c the connection. |
|
* @param sp the security parameters to use. |
|
* |
|
* @return the security keys. |
|
*/ $e55982d45da68b81$var$tls.generateKeys = function(c, sp) { |
|
// TLS_RSA_WITH_AES_128_CBC_SHA (required to be compliant with TLS 1.2) & |
|
// TLS_RSA_WITH_AES_256_CBC_SHA are the only cipher suites implemented |
|
// at present |
|
// TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA is required to be compliant with |
|
// TLS 1.0 but we don't care right now because AES is better and we have |
|
// an implementation for it |
|
// TODO: TLS 1.2 implementation |
|
/* |
|
// determine the PRF |
|
var prf; |
|
switch(sp.prf_algorithm) { |
|
case tls.PRFAlgorithm.tls_prf_sha256: |
|
prf = prf_sha256; |
|
break; |
|
default: |
|
// should never happen |
|
throw new Error('Invalid PRF'); |
|
} |
|
*/ // TLS 1.0/1.1 implementation |
|
var prf = $e55982d45da68b81$var$prf_TLS1; |
|
// concatenate server and client random |
|
var random = sp.client_random + sp.server_random; |
|
// only create master secret if session is new |
|
if (!c.session.resuming) { |
|
// create master secret, clean up pre-master secret |
|
sp.master_secret = prf(sp.pre_master_secret, 'master secret', random, 48).bytes(); |
|
sp.pre_master_secret = null; |
|
} |
|
// generate the amount of key material needed |
|
random = sp.server_random + sp.client_random; |
|
var length = 2 * sp.mac_key_length + 2 * sp.enc_key_length; |
|
// include IV for TLS/1.0 |
|
var tls10 = c.version.major === $e55982d45da68b81$var$tls.Versions.TLS_1_0.major && c.version.minor === $e55982d45da68b81$var$tls.Versions.TLS_1_0.minor; |
|
if (tls10) length += 2 * sp.fixed_iv_length; |
|
var km = prf(sp.master_secret, 'key expansion', random, length); |
|
// split the key material into the MAC and encryption keys |
|
var rval = { |
|
client_write_MAC_key: km.getBytes(sp.mac_key_length), |
|
server_write_MAC_key: km.getBytes(sp.mac_key_length), |
|
client_write_key: km.getBytes(sp.enc_key_length), |
|
server_write_key: km.getBytes(sp.enc_key_length) |
|
}; |
|
// include TLS 1.0 IVs |
|
if (tls10) { |
|
rval.client_write_IV = km.getBytes(sp.fixed_iv_length); |
|
rval.server_write_IV = km.getBytes(sp.fixed_iv_length); |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Creates a new initialized TLS connection state. A connection state has |
|
* a read mode and a write mode. |
|
* |
|
* compression state: |
|
* The current state of the compression algorithm. |
|
* |
|
* cipher state: |
|
* The current state of the encryption algorithm. This will consist of the |
|
* scheduled key for that connection. For stream ciphers, this will also |
|
* contain whatever state information is necessary to allow the stream to |
|
* continue to encrypt or decrypt data. |
|
* |
|
* MAC key: |
|
* The MAC key for the connection. |
|
* |
|
* sequence number: |
|
* Each connection state contains a sequence number, which is maintained |
|
* separately for read and write states. The sequence number MUST be set to |
|
* zero whenever a connection state is made the active state. Sequence |
|
* numbers are of type uint64 and may not exceed 2^64-1. Sequence numbers do |
|
* not wrap. If a TLS implementation would need to wrap a sequence number, |
|
* it must renegotiate instead. A sequence number is incremented after each |
|
* record: specifically, the first record transmitted under a particular |
|
* connection state MUST use sequence number 0. |
|
* |
|
* @param c the connection. |
|
* |
|
* @return the new initialized TLS connection state. |
|
*/ $e55982d45da68b81$var$tls.createConnectionState = function(c2) { |
|
var client = c2.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
var createMode = function() { |
|
var mode = { |
|
// two 32-bit numbers, first is most significant |
|
sequenceNumber: [ |
|
0, |
|
0 |
|
], |
|
macKey: null, |
|
macLength: 0, |
|
macFunction: null, |
|
cipherState: null, |
|
cipherFunction: function(record) { |
|
return true; |
|
}, |
|
compressionState: null, |
|
compressFunction: function(record) { |
|
return true; |
|
}, |
|
updateSequenceNumber: function() { |
|
if (mode.sequenceNumber[1] === 4294967295) { |
|
mode.sequenceNumber[1] = 0; |
|
++mode.sequenceNumber[0]; |
|
} else ++mode.sequenceNumber[1]; |
|
} |
|
}; |
|
return mode; |
|
}; |
|
var state = { |
|
read: createMode(), |
|
write: createMode() |
|
}; |
|
// update function in read mode will decrypt then decompress a record |
|
state.read.update = function(c, record) { |
|
if (!state.read.cipherFunction(record, state.read)) c.error(c, { |
|
message: 'Could not decrypt record or bad MAC.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
// doesn't matter if decryption failed or MAC was |
|
// invalid, return the same error so as not to reveal |
|
// which one occurred |
|
description: $e55982d45da68b81$var$tls.Alert.Description.bad_record_mac |
|
} |
|
}); |
|
else if (!state.read.compressFunction(c, record, state.read)) c.error(c, { |
|
message: 'Could not decompress record.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.decompression_failure |
|
} |
|
}); |
|
return !c.fail; |
|
}; |
|
// update function in write mode will compress then encrypt a record |
|
state.write.update = function(c, record) { |
|
if (!state.write.compressFunction(c, record, state.write)) // error, but do not send alert since it would require |
|
// compression as well |
|
c.error(c, { |
|
message: 'Could not compress record.', |
|
send: false, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.internal_error |
|
} |
|
}); |
|
else if (!state.write.cipherFunction(record, state.write)) // error, but do not send alert since it would require |
|
// encryption as well |
|
c.error(c, { |
|
message: 'Could not encrypt record.', |
|
send: false, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.internal_error |
|
} |
|
}); |
|
return !c.fail; |
|
}; |
|
// handle security parameters |
|
if (c2.session) { |
|
var sp = c2.session.sp; |
|
c2.session.cipherSuite.initSecurityParameters(sp); |
|
// generate keys |
|
sp.keys = $e55982d45da68b81$var$tls.generateKeys(c2, sp); |
|
state.read.macKey = client ? sp.keys.server_write_MAC_key : sp.keys.client_write_MAC_key; |
|
state.write.macKey = client ? sp.keys.client_write_MAC_key : sp.keys.server_write_MAC_key; |
|
// cipher suite setup |
|
c2.session.cipherSuite.initConnectionState(state, c2, sp); |
|
// compression setup |
|
switch(sp.compression_algorithm){ |
|
case $e55982d45da68b81$var$tls.CompressionMethod.none: |
|
break; |
|
case $e55982d45da68b81$var$tls.CompressionMethod.deflate: |
|
state.read.compressFunction = $e55982d45da68b81$var$inflate; |
|
state.write.compressFunction = $e55982d45da68b81$var$deflate; |
|
break; |
|
default: |
|
throw new Error('Unsupported compression algorithm.'); |
|
} |
|
} |
|
return state; |
|
}; |
|
/** |
|
* Creates a Random structure. |
|
* |
|
* struct { |
|
* uint32 gmt_unix_time; |
|
* opaque random_bytes[28]; |
|
* } Random; |
|
* |
|
* gmt_unix_time: |
|
* The current time and date in standard UNIX 32-bit format (seconds since |
|
* the midnight starting Jan 1, 1970, UTC, ignoring leap seconds) according |
|
* to the sender's internal clock. Clocks are not required to be set |
|
* correctly by the basic TLS protocol; higher-level or application |
|
* protocols may define additional requirements. Note that, for historical |
|
* reasons, the data element is named using GMT, the predecessor of the |
|
* current worldwide time base, UTC. |
|
* random_bytes: |
|
* 28 bytes generated by a secure random number generator. |
|
* |
|
* @return the Random structure as a byte array. |
|
*/ $e55982d45da68b81$var$tls.createRandom = function() { |
|
// get UTC milliseconds |
|
var d = new Date(); |
|
var utc = +d + d.getTimezoneOffset() * 60000; |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putInt32(utc); |
|
rval.putBytes($iGlOy.random.getBytes(28)); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a TLS record with the given type and data. |
|
* |
|
* @param c the connection. |
|
* @param options: |
|
* type: the record type. |
|
* data: the plain text data in a byte buffer. |
|
* |
|
* @return the created record. |
|
*/ $e55982d45da68b81$var$tls.createRecord = function(c, options) { |
|
if (!options.data) return null; |
|
var record = { |
|
type: options.type, |
|
version: { |
|
major: c.version.major, |
|
minor: c.version.minor |
|
}, |
|
length: options.data.length(), |
|
fragment: options.data |
|
}; |
|
return record; |
|
}; |
|
/** |
|
* Creates a TLS alert record. |
|
* |
|
* @param c the connection. |
|
* @param alert: |
|
* level: the TLS alert level. |
|
* description: the TLS alert description. |
|
* |
|
* @return the created alert record. |
|
*/ $e55982d45da68b81$var$tls.createAlert = function(c, alert) { |
|
var b = $iGlOy.util.createBuffer(); |
|
b.putByte(alert.level); |
|
b.putByte(alert.description); |
|
return $e55982d45da68b81$var$tls.createRecord(c, { |
|
type: $e55982d45da68b81$var$tls.ContentType.alert, |
|
data: b |
|
}); |
|
}; |
|
/* The structure of a TLS handshake message. |
|
* |
|
* struct { |
|
* HandshakeType msg_type; // handshake type |
|
* uint24 length; // bytes in message |
|
* select(HandshakeType) { |
|
* case hello_request: HelloRequest; |
|
* case client_hello: ClientHello; |
|
* case server_hello: ServerHello; |
|
* case certificate: Certificate; |
|
* case server_key_exchange: ServerKeyExchange; |
|
* case certificate_request: CertificateRequest; |
|
* case server_hello_done: ServerHelloDone; |
|
* case certificate_verify: CertificateVerify; |
|
* case client_key_exchange: ClientKeyExchange; |
|
* case finished: Finished; |
|
* } body; |
|
* } Handshake; |
|
*/ /** |
|
* Creates a ClientHello message. |
|
* |
|
* opaque SessionID<0..32>; |
|
* enum { null(0), deflate(1), (255) } CompressionMethod; |
|
* uint8 CipherSuite[2]; |
|
* |
|
* struct { |
|
* ProtocolVersion client_version; |
|
* Random random; |
|
* SessionID session_id; |
|
* CipherSuite cipher_suites<2..2^16-2>; |
|
* CompressionMethod compression_methods<1..2^8-1>; |
|
* select(extensions_present) { |
|
* case false: |
|
* struct {}; |
|
* case true: |
|
* Extension extensions<0..2^16-1>; |
|
* }; |
|
* } ClientHello; |
|
* |
|
* The extension format for extended client hellos and server hellos is: |
|
* |
|
* struct { |
|
* ExtensionType extension_type; |
|
* opaque extension_data<0..2^16-1>; |
|
* } Extension; |
|
* |
|
* Here: |
|
* |
|
* - "extension_type" identifies the particular extension type. |
|
* - "extension_data" contains information specific to the particular |
|
* extension type. |
|
* |
|
* The extension types defined in this document are: |
|
* |
|
* enum { |
|
* server_name(0), max_fragment_length(1), |
|
* client_certificate_url(2), trusted_ca_keys(3), |
|
* truncated_hmac(4), status_request(5), (65535) |
|
* } ExtensionType; |
|
* |
|
* @param c the connection. |
|
* |
|
* @return the ClientHello byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createClientHello = function(c) { |
|
// save hello version |
|
c.session.clientHelloVersion = { |
|
major: c.version.major, |
|
minor: c.version.minor |
|
}; |
|
// create supported cipher suites |
|
var cipherSuites = $iGlOy.util.createBuffer(); |
|
for(var i = 0; i < c.cipherSuites.length; ++i){ |
|
var cs = c.cipherSuites[i]; |
|
cipherSuites.putByte(cs.id[0]); |
|
cipherSuites.putByte(cs.id[1]); |
|
} |
|
var cSuites = cipherSuites.length(); |
|
// create supported compression methods, null always supported, but |
|
// also support deflate if connection has inflate and deflate methods |
|
var compressionMethods = $iGlOy.util.createBuffer(); |
|
compressionMethods.putByte($e55982d45da68b81$var$tls.CompressionMethod.none); |
|
// FIXME: deflate support disabled until issues with raw deflate data |
|
// without zlib headers are resolved |
|
/* |
|
if(c.inflate !== null && c.deflate !== null) { |
|
compressionMethods.putByte(tls.CompressionMethod.deflate); |
|
} |
|
*/ var cMethods = compressionMethods.length(); |
|
// create TLS SNI (server name indication) extension if virtual host |
|
// has been specified, see RFC 3546 |
|
var extensions = $iGlOy.util.createBuffer(); |
|
if (c.virtualHost) { |
|
// create extension struct |
|
var ext = $iGlOy.util.createBuffer(); |
|
ext.putByte(0); // type server_name (ExtensionType is 2 bytes) |
|
ext.putByte(0); |
|
/* In order to provide the server name, clients MAY include an |
|
* extension of type "server_name" in the (extended) client hello. |
|
* The "extension_data" field of this extension SHALL contain |
|
* "ServerNameList" where: |
|
* |
|
* struct { |
|
* NameType name_type; |
|
* select(name_type) { |
|
* case host_name: HostName; |
|
* } name; |
|
* } ServerName; |
|
* |
|
* enum { |
|
* host_name(0), (255) |
|
* } NameType; |
|
* |
|
* opaque HostName<1..2^16-1>; |
|
* |
|
* struct { |
|
* ServerName server_name_list<1..2^16-1> |
|
* } ServerNameList; |
|
*/ var serverName = $iGlOy.util.createBuffer(); |
|
serverName.putByte(0); // type host_name |
|
$e55982d45da68b81$var$writeVector(serverName, 2, $iGlOy.util.createBuffer(c.virtualHost)); |
|
// ServerNameList is in extension_data |
|
var snList = $iGlOy.util.createBuffer(); |
|
$e55982d45da68b81$var$writeVector(snList, 2, serverName); |
|
$e55982d45da68b81$var$writeVector(ext, 2, snList); |
|
extensions.putBuffer(ext); |
|
} |
|
var extLength = extensions.length(); |
|
if (extLength > 0) // add extension vector length |
|
extLength += 2; |
|
// determine length of the handshake message |
|
// cipher suites and compression methods size will need to be |
|
// updated if more get added to the list |
|
var sessionId = c.session.id; |
|
var length = sessionId.length + 1 + 2 + 4 + 28 + 2 + cSuites + 1 + cMethods + extLength; // extensions vector |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte($e55982d45da68b81$var$tls.HandshakeType.client_hello); |
|
rval.putInt24(length); // handshake length |
|
rval.putByte(c.version.major); // major version |
|
rval.putByte(c.version.minor); // minor version |
|
rval.putBytes(c.session.sp.client_random); // random time + bytes |
|
$e55982d45da68b81$var$writeVector(rval, 1, $iGlOy.util.createBuffer(sessionId)); |
|
$e55982d45da68b81$var$writeVector(rval, 2, cipherSuites); |
|
$e55982d45da68b81$var$writeVector(rval, 1, compressionMethods); |
|
if (extLength > 0) $e55982d45da68b81$var$writeVector(rval, 2, extensions); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a ServerHello message. |
|
* |
|
* @param c the connection. |
|
* |
|
* @return the ServerHello byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createServerHello = function(c) { |
|
// determine length of the handshake message |
|
var sessionId = c.session.id; |
|
var length = sessionId.length + 1 + 2 + 4 + 28 + 2 + 1; // chosen compression method |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte($e55982d45da68b81$var$tls.HandshakeType.server_hello); |
|
rval.putInt24(length); // handshake length |
|
rval.putByte(c.version.major); // major version |
|
rval.putByte(c.version.minor); // minor version |
|
rval.putBytes(c.session.sp.server_random); // random time + bytes |
|
$e55982d45da68b81$var$writeVector(rval, 1, $iGlOy.util.createBuffer(sessionId)); |
|
rval.putByte(c.session.cipherSuite.id[0]); |
|
rval.putByte(c.session.cipherSuite.id[1]); |
|
rval.putByte(c.session.compressionMethod); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a Certificate message. |
|
* |
|
* When this message will be sent: |
|
* This is the first message the client can send after receiving a server |
|
* hello done message and the first message the server can send after |
|
* sending a ServerHello. This client message is only sent if the server |
|
* requests a certificate. If no suitable certificate is available, the |
|
* client should send a certificate message containing no certificates. If |
|
* client authentication is required by the server for the handshake to |
|
* continue, it may respond with a fatal handshake failure alert. |
|
* |
|
* opaque ASN.1Cert<1..2^24-1>; |
|
* |
|
* struct { |
|
* ASN.1Cert certificate_list<0..2^24-1>; |
|
* } Certificate; |
|
* |
|
* @param c the connection. |
|
* |
|
* @return the Certificate byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createCertificate = function(c) { |
|
// TODO: check certificate request to ensure types are supported |
|
// get a certificate (a certificate as a PEM string) |
|
var client = c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
var cert = null; |
|
if (c.getCertificate) { |
|
var hint; |
|
if (client) hint = c.session.certificateRequest; |
|
else hint = c.session.extensions.server_name.serverNameList; |
|
cert = c.getCertificate(c, hint); |
|
} |
|
// buffer to hold certificate list |
|
var certList = $iGlOy.util.createBuffer(); |
|
if (cert !== null) try { |
|
// normalize cert to a chain of certificates |
|
if (!$iGlOy.util.isArray(cert)) cert = [ |
|
cert |
|
]; |
|
var asn1 = null; |
|
for(var i = 0; i < cert.length; ++i){ |
|
var msg = $iGlOy.pem.decode(cert[i])[0]; |
|
if (msg.type !== 'CERTIFICATE' && msg.type !== 'X509 CERTIFICATE' && msg.type !== 'TRUSTED CERTIFICATE') { |
|
var error = new Error("Could not convert certificate from PEM; PEM header type is not \"CERTIFICATE\", \"X509 CERTIFICATE\", or \"TRUSTED CERTIFICATE\"."); |
|
error.headerType = msg.type; |
|
throw error; |
|
} |
|
if (msg.procType && msg.procType.type === 'ENCRYPTED') throw new Error('Could not convert certificate from PEM; PEM is encrypted.'); |
|
var der = $iGlOy.util.createBuffer(msg.body); |
|
if (asn1 === null) asn1 = $iGlOy.asn1.fromDer(der.bytes(), false); |
|
// certificate entry is itself a vector with 3 length bytes |
|
var certBuffer = $iGlOy.util.createBuffer(); |
|
$e55982d45da68b81$var$writeVector(certBuffer, 3, der); |
|
// add cert vector to cert list vector |
|
certList.putBuffer(certBuffer); |
|
} |
|
// save certificate |
|
cert = $iGlOy.pki.certificateFromAsn1(asn1); |
|
if (client) c.session.clientCertificate = cert; |
|
else c.session.serverCertificate = cert; |
|
} catch (ex) { |
|
return c.error(c, { |
|
message: 'Could not send certificate list.', |
|
cause: ex, |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.bad_certificate |
|
} |
|
}); |
|
} |
|
// determine length of the handshake message |
|
var length = 3 + certList.length(); // cert list vector |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte($e55982d45da68b81$var$tls.HandshakeType.certificate); |
|
rval.putInt24(length); |
|
$e55982d45da68b81$var$writeVector(rval, 3, certList); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a ClientKeyExchange message. |
|
* |
|
* When this message will be sent: |
|
* This message is always sent by the client. It will immediately follow the |
|
* client certificate message, if it is sent. Otherwise it will be the first |
|
* message sent by the client after it receives the server hello done |
|
* message. |
|
* |
|
* Meaning of this message: |
|
* With this message, the premaster secret is set, either though direct |
|
* transmission of the RSA-encrypted secret, or by the transmission of |
|
* Diffie-Hellman parameters which will allow each side to agree upon the |
|
* same premaster secret. When the key exchange method is DH_RSA or DH_DSS, |
|
* client certification has been requested, and the client was able to |
|
* respond with a certificate which contained a Diffie-Hellman public key |
|
* whose parameters (group and generator) matched those specified by the |
|
* server in its certificate, this message will not contain any data. |
|
* |
|
* Meaning of this message: |
|
* If RSA is being used for key agreement and authentication, the client |
|
* generates a 48-byte premaster secret, encrypts it using the public key |
|
* from the server's certificate or the temporary RSA key provided in a |
|
* server key exchange message, and sends the result in an encrypted |
|
* premaster secret message. This structure is a variant of the client |
|
* key exchange message, not a message in itself. |
|
* |
|
* struct { |
|
* select(KeyExchangeAlgorithm) { |
|
* case rsa: EncryptedPreMasterSecret; |
|
* case diffie_hellman: ClientDiffieHellmanPublic; |
|
* } exchange_keys; |
|
* } ClientKeyExchange; |
|
* |
|
* struct { |
|
* ProtocolVersion client_version; |
|
* opaque random[46]; |
|
* } PreMasterSecret; |
|
* |
|
* struct { |
|
* public-key-encrypted PreMasterSecret pre_master_secret; |
|
* } EncryptedPreMasterSecret; |
|
* |
|
* A public-key-encrypted element is encoded as a vector <0..2^16-1>. |
|
* |
|
* @param c the connection. |
|
* |
|
* @return the ClientKeyExchange byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createClientKeyExchange = function(c) { |
|
// create buffer to encrypt |
|
var b = $iGlOy.util.createBuffer(); |
|
// add highest client-supported protocol to help server avoid version |
|
// rollback attacks |
|
b.putByte(c.session.clientHelloVersion.major); |
|
b.putByte(c.session.clientHelloVersion.minor); |
|
// generate and add 46 random bytes |
|
b.putBytes($iGlOy.random.getBytes(46)); |
|
// save pre-master secret |
|
var sp = c.session.sp; |
|
sp.pre_master_secret = b.getBytes(); |
|
// RSA-encrypt the pre-master secret |
|
var key = c.session.serverCertificate.publicKey; |
|
b = key.encrypt(sp.pre_master_secret); |
|
/* Note: The encrypted pre-master secret will be stored in a |
|
public-key-encrypted opaque vector that has the length prefixed using |
|
2 bytes, so include those 2 bytes in the handshake message length. This |
|
is done as a minor optimization instead of calling writeVector(). */ // determine length of the handshake message |
|
var length = b.length + 2; |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte($e55982d45da68b81$var$tls.HandshakeType.client_key_exchange); |
|
rval.putInt24(length); |
|
// add vector length bytes |
|
rval.putInt16(b.length); |
|
rval.putBytes(b); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a ServerKeyExchange message. |
|
* |
|
* @param c the connection. |
|
* |
|
* @return the ServerKeyExchange byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createServerKeyExchange = function(c) { |
|
// this implementation only supports RSA, no Diffie-Hellman support, |
|
// so this record is empty |
|
// determine length of the handshake message |
|
var length = 0; |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
if (length > 0) { |
|
rval.putByte($e55982d45da68b81$var$tls.HandshakeType.server_key_exchange); |
|
rval.putInt24(length); |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Gets the signed data used to verify a client-side certificate. See |
|
* tls.createCertificateVerify() for details. |
|
* |
|
* @param c the connection. |
|
* @param callback the callback to call once the signed data is ready. |
|
*/ $e55982d45da68b81$var$tls.getClientSignature = function(c3, callback1) { |
|
// generate data to RSA encrypt |
|
var b1 = $iGlOy.util.createBuffer(); |
|
b1.putBuffer(c3.session.md5.digest()); |
|
b1.putBuffer(c3.session.sha1.digest()); |
|
b1 = b1.getBytes(); |
|
// create default signing function as necessary |
|
c3.getSignature = c3.getSignature || function(c, b, callback) { |
|
// do rsa encryption, call callback |
|
var privateKey = null; |
|
if (c.getPrivateKey) try { |
|
privateKey = c.getPrivateKey(c, c.session.clientCertificate); |
|
privateKey = $iGlOy.pki.privateKeyFromPem(privateKey); |
|
} catch (ex) { |
|
c.error(c, { |
|
message: 'Could not get private key.', |
|
cause: ex, |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.internal_error |
|
} |
|
}); |
|
} |
|
if (privateKey === null) c.error(c, { |
|
message: 'No private key set.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.internal_error |
|
} |
|
}); |
|
else b = privateKey.sign(b, null); |
|
callback(c, b); |
|
}; |
|
// get client signature |
|
c3.getSignature(c3, b1, callback1); |
|
}; |
|
/** |
|
* Creates a CertificateVerify message. |
|
* |
|
* Meaning of this message: |
|
* This structure conveys the client's Diffie-Hellman public value |
|
* (Yc) if it was not already included in the client's certificate. |
|
* The encoding used for Yc is determined by the enumerated |
|
* PublicValueEncoding. This structure is a variant of the client |
|
* key exchange message, not a message in itself. |
|
* |
|
* When this message will be sent: |
|
* This message is used to provide explicit verification of a client |
|
* certificate. This message is only sent following a client |
|
* certificate that has signing capability (i.e. all certificates |
|
* except those containing fixed Diffie-Hellman parameters). When |
|
* sent, it will immediately follow the client key exchange message. |
|
* |
|
* struct { |
|
* Signature signature; |
|
* } CertificateVerify; |
|
* |
|
* CertificateVerify.signature.md5_hash |
|
* MD5(handshake_messages); |
|
* |
|
* Certificate.signature.sha_hash |
|
* SHA(handshake_messages); |
|
* |
|
* Here handshake_messages refers to all handshake messages sent or |
|
* received starting at client hello up to but not including this |
|
* message, including the type and length fields of the handshake |
|
* messages. |
|
* |
|
* select(SignatureAlgorithm) { |
|
* case anonymous: struct { }; |
|
* case rsa: |
|
* digitally-signed struct { |
|
* opaque md5_hash[16]; |
|
* opaque sha_hash[20]; |
|
* }; |
|
* case dsa: |
|
* digitally-signed struct { |
|
* opaque sha_hash[20]; |
|
* }; |
|
* } Signature; |
|
* |
|
* In digital signing, one-way hash functions are used as input for a |
|
* signing algorithm. A digitally-signed element is encoded as an opaque |
|
* vector <0..2^16-1>, where the length is specified by the signing |
|
* algorithm and key. |
|
* |
|
* In RSA signing, a 36-byte structure of two hashes (one SHA and one |
|
* MD5) is signed (encrypted with the private key). It is encoded with |
|
* PKCS #1 block type 0 or type 1 as described in [PKCS1]. |
|
* |
|
* In DSS, the 20 bytes of the SHA hash are run directly through the |
|
* Digital Signing Algorithm with no additional hashing. |
|
* |
|
* @param c the connection. |
|
* @param signature the signature to include in the message. |
|
* |
|
* @return the CertificateVerify byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createCertificateVerify = function(c, signature) { |
|
/* Note: The signature will be stored in a "digitally-signed" opaque |
|
vector that has the length prefixed using 2 bytes, so include those |
|
2 bytes in the handshake message length. This is done as a minor |
|
optimization instead of calling writeVector(). */ // determine length of the handshake message |
|
var length = signature.length + 2; |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte($e55982d45da68b81$var$tls.HandshakeType.certificate_verify); |
|
rval.putInt24(length); |
|
// add vector length bytes |
|
rval.putInt16(signature.length); |
|
rval.putBytes(signature); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a CertificateRequest message. |
|
* |
|
* @param c the connection. |
|
* |
|
* @return the CertificateRequest byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createCertificateRequest = function(c) { |
|
// TODO: support other certificate types |
|
var certTypes = $iGlOy.util.createBuffer(); |
|
// common RSA certificate type |
|
certTypes.putByte(1); |
|
// add distinguished names from CA store |
|
var cAs = $iGlOy.util.createBuffer(); |
|
for(var key in c.caStore.certs){ |
|
var cert = c.caStore.certs[key]; |
|
var dn = $iGlOy.pki.distinguishedNameToAsn1(cert.subject); |
|
var byteBuffer = $iGlOy.asn1.toDer(dn); |
|
cAs.putInt16(byteBuffer.length()); |
|
cAs.putBuffer(byteBuffer); |
|
} |
|
// TODO: TLS 1.2+ has a different format |
|
// determine length of the handshake message |
|
var length = 1 + certTypes.length() + 2 + cAs.length(); |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte($e55982d45da68b81$var$tls.HandshakeType.certificate_request); |
|
rval.putInt24(length); |
|
$e55982d45da68b81$var$writeVector(rval, 1, certTypes); |
|
$e55982d45da68b81$var$writeVector(rval, 2, cAs); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a ServerHelloDone message. |
|
* |
|
* @param c the connection. |
|
* |
|
* @return the ServerHelloDone byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createServerHelloDone = function(c) { |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte($e55982d45da68b81$var$tls.HandshakeType.server_hello_done); |
|
rval.putInt24(0); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a ChangeCipherSpec message. |
|
* |
|
* The change cipher spec protocol exists to signal transitions in |
|
* ciphering strategies. The protocol consists of a single message, |
|
* which is encrypted and compressed under the current (not the pending) |
|
* connection state. The message consists of a single byte of value 1. |
|
* |
|
* struct { |
|
* enum { change_cipher_spec(1), (255) } type; |
|
* } ChangeCipherSpec; |
|
* |
|
* @return the ChangeCipherSpec byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createChangeCipherSpec = function() { |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte(1); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a Finished message. |
|
* |
|
* struct { |
|
* opaque verify_data[12]; |
|
* } Finished; |
|
* |
|
* verify_data |
|
* PRF(master_secret, finished_label, MD5(handshake_messages) + |
|
* SHA-1(handshake_messages)) [0..11]; |
|
* |
|
* finished_label |
|
* For Finished messages sent by the client, the string "client |
|
* finished". For Finished messages sent by the server, the |
|
* string "server finished". |
|
* |
|
* handshake_messages |
|
* All of the data from all handshake messages up to but not |
|
* including this message. This is only data visible at the |
|
* handshake layer and does not include record layer headers. |
|
* This is the concatenation of all the Handshake structures as |
|
* defined in 7.4 exchanged thus far. |
|
* |
|
* @param c the connection. |
|
* |
|
* @return the Finished byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createFinished = function(c) { |
|
// generate verify_data |
|
var b = $iGlOy.util.createBuffer(); |
|
b.putBuffer(c.session.md5.digest()); |
|
b.putBuffer(c.session.sha1.digest()); |
|
// TODO: determine prf function and verify length for TLS 1.2 |
|
var client = c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
var sp = c.session.sp; |
|
var vdl = 12; |
|
var prf = $e55982d45da68b81$var$prf_TLS1; |
|
var label = client ? 'client finished' : 'server finished'; |
|
b = prf(sp.master_secret, label, b.getBytes(), vdl); |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte($e55982d45da68b81$var$tls.HandshakeType.finished); |
|
rval.putInt24(b.length()); |
|
rval.putBuffer(b); |
|
return rval; |
|
}; |
|
/** |
|
* Creates a HeartbeatMessage (See RFC 6520). |
|
* |
|
* struct { |
|
* HeartbeatMessageType type; |
|
* uint16 payload_length; |
|
* opaque payload[HeartbeatMessage.payload_length]; |
|
* opaque padding[padding_length]; |
|
* } HeartbeatMessage; |
|
* |
|
* The total length of a HeartbeatMessage MUST NOT exceed 2^14 or |
|
* max_fragment_length when negotiated as defined in [RFC6066]. |
|
* |
|
* type: The message type, either heartbeat_request or heartbeat_response. |
|
* |
|
* payload_length: The length of the payload. |
|
* |
|
* payload: The payload consists of arbitrary content. |
|
* |
|
* padding: The padding is random content that MUST be ignored by the |
|
* receiver. The length of a HeartbeatMessage is TLSPlaintext.length |
|
* for TLS and DTLSPlaintext.length for DTLS. Furthermore, the |
|
* length of the type field is 1 byte, and the length of the |
|
* payload_length is 2. Therefore, the padding_length is |
|
* TLSPlaintext.length - payload_length - 3 for TLS and |
|
* DTLSPlaintext.length - payload_length - 3 for DTLS. The |
|
* padding_length MUST be at least 16. |
|
* |
|
* The sender of a HeartbeatMessage MUST use a random padding of at |
|
* least 16 bytes. The padding of a received HeartbeatMessage message |
|
* MUST be ignored. |
|
* |
|
* If the payload_length of a received HeartbeatMessage is too large, |
|
* the received HeartbeatMessage MUST be discarded silently. |
|
* |
|
* @param c the connection. |
|
* @param type the tls.HeartbeatMessageType. |
|
* @param payload the heartbeat data to send as the payload. |
|
* @param [payloadLength] the payload length to use, defaults to the |
|
* actual payload length. |
|
* |
|
* @return the HeartbeatRequest byte buffer. |
|
*/ $e55982d45da68b81$var$tls.createHeartbeat = function(type, payload, payloadLength) { |
|
if (typeof payloadLength === 'undefined') payloadLength = payload.length; |
|
// build record fragment |
|
var rval = $iGlOy.util.createBuffer(); |
|
rval.putByte(type); // heartbeat message type |
|
rval.putInt16(payloadLength); // payload length |
|
rval.putBytes(payload); // payload |
|
// padding |
|
var plaintextLength = rval.length(); |
|
var paddingLength = Math.max(16, plaintextLength - payloadLength - 3); |
|
rval.putBytes($iGlOy.random.getBytes(paddingLength)); |
|
return rval; |
|
}; |
|
/** |
|
* Fragments, compresses, encrypts, and queues a record for delivery. |
|
* |
|
* @param c the connection. |
|
* @param record the record to queue. |
|
*/ $e55982d45da68b81$var$tls.queue = function(c, record) { |
|
// error during record creation |
|
if (!record) return; |
|
if (record.fragment.length() === 0) { |
|
if (record.type === $e55982d45da68b81$var$tls.ContentType.handshake || record.type === $e55982d45da68b81$var$tls.ContentType.alert || record.type === $e55982d45da68b81$var$tls.ContentType.change_cipher_spec) // Empty handshake, alert of change cipher spec messages are not allowed per the TLS specification and should not be sent. |
|
return; |
|
} |
|
// if the record is a handshake record, update handshake hashes |
|
if (record.type === $e55982d45da68b81$var$tls.ContentType.handshake) { |
|
var bytes = record.fragment.bytes(); |
|
c.session.md5.update(bytes); |
|
c.session.sha1.update(bytes); |
|
bytes = null; |
|
} |
|
// handle record fragmentation |
|
var records; |
|
if (record.fragment.length() <= $e55982d45da68b81$var$tls.MaxFragment) records = [ |
|
record |
|
]; |
|
else { |
|
// fragment data as long as it is too long |
|
records = []; |
|
var data = record.fragment.bytes(); |
|
while(data.length > $e55982d45da68b81$var$tls.MaxFragment){ |
|
records.push($e55982d45da68b81$var$tls.createRecord(c, { |
|
type: record.type, |
|
data: $iGlOy.util.createBuffer(data.slice(0, $e55982d45da68b81$var$tls.MaxFragment)) |
|
})); |
|
data = data.slice($e55982d45da68b81$var$tls.MaxFragment); |
|
} |
|
// add last record |
|
if (data.length > 0) records.push($e55982d45da68b81$var$tls.createRecord(c, { |
|
type: record.type, |
|
data: $iGlOy.util.createBuffer(data) |
|
})); |
|
} |
|
// compress and encrypt all fragmented records |
|
for(var i = 0; i < records.length && !c.fail; ++i){ |
|
// update the record using current write state |
|
var rec = records[i]; |
|
var s = c.state.current.write; |
|
if (s.update(c, rec)) // store record |
|
c.records.push(rec); |
|
} |
|
}; |
|
/** |
|
* Flushes all queued records to the output buffer and calls the |
|
* tlsDataReady() handler on the given connection. |
|
* |
|
* @param c the connection. |
|
* |
|
* @return true on success, false on failure. |
|
*/ $e55982d45da68b81$var$tls.flush = function(c) { |
|
for(var i = 0; i < c.records.length; ++i){ |
|
var record = c.records[i]; |
|
// add record header and fragment |
|
c.tlsData.putByte(record.type); |
|
c.tlsData.putByte(record.version.major); |
|
c.tlsData.putByte(record.version.minor); |
|
c.tlsData.putInt16(record.fragment.length()); |
|
c.tlsData.putBuffer(c.records[i].fragment); |
|
} |
|
c.records = []; |
|
return c.tlsDataReady(c); |
|
}; |
|
/** |
|
* Maps a pki.certificateError to a tls.Alert.Description. |
|
* |
|
* @param error the error to map. |
|
* |
|
* @return the alert description. |
|
*/ var $e55982d45da68b81$var$_certErrorToAlertDesc = function(error) { |
|
switch(error){ |
|
case true: |
|
return true; |
|
case $iGlOy.pki.certificateError.bad_certificate: |
|
return $e55982d45da68b81$var$tls.Alert.Description.bad_certificate; |
|
case $iGlOy.pki.certificateError.unsupported_certificate: |
|
return $e55982d45da68b81$var$tls.Alert.Description.unsupported_certificate; |
|
case $iGlOy.pki.certificateError.certificate_revoked: |
|
return $e55982d45da68b81$var$tls.Alert.Description.certificate_revoked; |
|
case $iGlOy.pki.certificateError.certificate_expired: |
|
return $e55982d45da68b81$var$tls.Alert.Description.certificate_expired; |
|
case $iGlOy.pki.certificateError.certificate_unknown: |
|
return $e55982d45da68b81$var$tls.Alert.Description.certificate_unknown; |
|
case $iGlOy.pki.certificateError.unknown_ca: |
|
return $e55982d45da68b81$var$tls.Alert.Description.unknown_ca; |
|
default: |
|
return $e55982d45da68b81$var$tls.Alert.Description.bad_certificate; |
|
} |
|
}; |
|
/** |
|
* Maps a tls.Alert.Description to a pki.certificateError. |
|
* |
|
* @param desc the alert description. |
|
* |
|
* @return the certificate error. |
|
*/ var $e55982d45da68b81$var$_alertDescToCertError = function(desc) { |
|
switch(desc){ |
|
case true: |
|
return true; |
|
case $e55982d45da68b81$var$tls.Alert.Description.bad_certificate: |
|
return $iGlOy.pki.certificateError.bad_certificate; |
|
case $e55982d45da68b81$var$tls.Alert.Description.unsupported_certificate: |
|
return $iGlOy.pki.certificateError.unsupported_certificate; |
|
case $e55982d45da68b81$var$tls.Alert.Description.certificate_revoked: |
|
return $iGlOy.pki.certificateError.certificate_revoked; |
|
case $e55982d45da68b81$var$tls.Alert.Description.certificate_expired: |
|
return $iGlOy.pki.certificateError.certificate_expired; |
|
case $e55982d45da68b81$var$tls.Alert.Description.certificate_unknown: |
|
return $iGlOy.pki.certificateError.certificate_unknown; |
|
case $e55982d45da68b81$var$tls.Alert.Description.unknown_ca: |
|
return $iGlOy.pki.certificateError.unknown_ca; |
|
default: |
|
return $iGlOy.pki.certificateError.bad_certificate; |
|
} |
|
}; |
|
/** |
|
* Verifies a certificate chain against the given connection's |
|
* Certificate Authority store. |
|
* |
|
* @param c the TLS connection. |
|
* @param chain the certificate chain to verify, with the root or highest |
|
* authority at the end. |
|
* |
|
* @return true if successful, false if not. |
|
*/ $e55982d45da68b81$var$tls.verifyCertificateChain = function(c, chain1) { |
|
try { |
|
// Make a copy of c.verifyOptions so that we can modify options.verify |
|
// without modifying c.verifyOptions. |
|
var options = { |
|
}; |
|
for(var key in c.verifyOptions)options[key] = c.verifyOptions[key]; |
|
options.verify = function(vfd, depth, chain) { |
|
// convert pki.certificateError to tls alert description |
|
var desc = $e55982d45da68b81$var$_certErrorToAlertDesc(vfd); |
|
// call application callback |
|
var ret = c.verify(c, vfd, depth, chain); |
|
if (ret !== true) { |
|
if (typeof ret === 'object' && !$iGlOy.util.isArray(ret)) { |
|
// throw custom error |
|
var error = new Error('The application rejected the certificate.'); |
|
error.send = true; |
|
error.alert = { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.bad_certificate |
|
}; |
|
if (ret.message) error.message = ret.message; |
|
if (ret.alert) error.alert.description = ret.alert; |
|
throw error; |
|
} |
|
// convert tls alert description to pki.certificateError |
|
if (ret !== vfd) ret = $e55982d45da68b81$var$_alertDescToCertError(ret); |
|
} |
|
return ret; |
|
}; |
|
// verify chain |
|
$iGlOy.pki.verifyCertificateChain(c.caStore, chain1, options); |
|
} catch (ex) { |
|
// build tls error if not already customized |
|
var err = ex; |
|
if (typeof err !== 'object' || $iGlOy.util.isArray(err)) err = { |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$_certErrorToAlertDesc(ex) |
|
} |
|
}; |
|
if (!('send' in err)) err.send = true; |
|
if (!('alert' in err)) err.alert = { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$_certErrorToAlertDesc(err.error) |
|
}; |
|
// send error |
|
c.error(c, err); |
|
} |
|
return !c.fail; |
|
}; |
|
/** |
|
* Creates a new TLS session cache. |
|
* |
|
* @param cache optional map of session ID to cached session. |
|
* @param capacity the maximum size for the cache (default: 100). |
|
* |
|
* @return the new TLS session cache. |
|
*/ $e55982d45da68b81$var$tls.createSessionCache = function(cache, capacity) { |
|
var rval = null; |
|
// assume input is already a session cache object |
|
if (cache && cache.getSession && cache.setSession && cache.order) rval = cache; |
|
else { |
|
// create cache |
|
rval = { |
|
}; |
|
rval.cache = cache || { |
|
}; |
|
rval.capacity = Math.max(capacity || 100, 1); |
|
rval.order = []; |
|
// store order for sessions, delete session overflow |
|
for(var key1 in cache)if (rval.order.length <= capacity) rval.order.push(key1); |
|
else delete cache[key1]; |
|
// get a session from a session ID (or get any session) |
|
rval.getSession = function(sessionId) { |
|
var session = null; |
|
var key = null; |
|
// if session ID provided, use it |
|
if (sessionId) key = $iGlOy.util.bytesToHex(sessionId); |
|
else if (rval.order.length > 0) // get first session from cache |
|
key = rval.order[0]; |
|
if (key !== null && key in rval.cache) { |
|
// get cached session and remove from cache |
|
session = rval.cache[key]; |
|
delete rval.cache[key]; |
|
for(var i in rval.order)if (rval.order[i] === key) { |
|
rval.order.splice(i, 1); |
|
break; |
|
} |
|
} |
|
return session; |
|
}; |
|
// set a session in the cache |
|
rval.setSession = function(sessionId, session) { |
|
// remove session from cache if at capacity |
|
if (rval.order.length === rval.capacity) { |
|
var key = rval.order.shift(); |
|
delete rval.cache[key]; |
|
} |
|
// add session to cache |
|
var key = $iGlOy.util.bytesToHex(sessionId); |
|
rval.order.push(key); |
|
rval.cache[key] = session; |
|
}; |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Creates a new TLS connection. |
|
* |
|
* See public createConnection() docs for more details. |
|
* |
|
* @param options the options for this connection. |
|
* |
|
* @return the new TLS connection. |
|
*/ $e55982d45da68b81$var$tls.createConnection = function(options) { |
|
var caStore = null; |
|
if (options.caStore) { |
|
// if CA store is an array, convert it to a CA store object |
|
if ($iGlOy.util.isArray(options.caStore)) caStore = $iGlOy.pki.createCaStore(options.caStore); |
|
else caStore = options.caStore; |
|
} else // create empty CA store |
|
caStore = $iGlOy.pki.createCaStore(); |
|
// setup default cipher suites |
|
var cipherSuites = options.cipherSuites || null; |
|
if (cipherSuites === null) { |
|
cipherSuites = []; |
|
for(var key in $e55982d45da68b81$var$tls.CipherSuites)cipherSuites.push($e55982d45da68b81$var$tls.CipherSuites[key]); |
|
} |
|
// set default entity |
|
var entity = options.server || false ? $e55982d45da68b81$var$tls.ConnectionEnd.server : $e55982d45da68b81$var$tls.ConnectionEnd.client; |
|
// create session cache if requested |
|
var sessionCache = options.sessionCache ? $e55982d45da68b81$var$tls.createSessionCache(options.sessionCache) : null; |
|
// create TLS connection |
|
var c4 = { |
|
version: { |
|
major: $e55982d45da68b81$var$tls.Version.major, |
|
minor: $e55982d45da68b81$var$tls.Version.minor |
|
}, |
|
entity: entity, |
|
sessionId: options.sessionId, |
|
caStore: caStore, |
|
sessionCache: sessionCache, |
|
cipherSuites: cipherSuites, |
|
connected: options.connected, |
|
virtualHost: options.virtualHost || null, |
|
verifyClient: options.verifyClient || false, |
|
verify: options.verify || function(cn, vfd, dpth, cts) { |
|
return vfd; |
|
}, |
|
verifyOptions: options.verifyOptions || { |
|
}, |
|
getCertificate: options.getCertificate || null, |
|
getPrivateKey: options.getPrivateKey || null, |
|
getSignature: options.getSignature || null, |
|
input: $iGlOy.util.createBuffer(), |
|
tlsData: $iGlOy.util.createBuffer(), |
|
data: $iGlOy.util.createBuffer(), |
|
tlsDataReady: options.tlsDataReady, |
|
dataReady: options.dataReady, |
|
heartbeatReceived: options.heartbeatReceived, |
|
closed: options.closed, |
|
error: function(c, ex) { |
|
// set origin if not set |
|
ex.origin = ex.origin || (c.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client ? 'client' : 'server'); |
|
// send TLS alert |
|
if (ex.send) { |
|
$e55982d45da68b81$var$tls.queue(c, $e55982d45da68b81$var$tls.createAlert(c, ex.alert)); |
|
$e55982d45da68b81$var$tls.flush(c); |
|
} |
|
// error is fatal by default |
|
var fatal = ex.fatal !== false; |
|
if (fatal) // set fail flag |
|
c.fail = true; |
|
// call error handler first |
|
options.error(c, ex); |
|
if (fatal) // fatal error, close connection, do not clear fail |
|
c.close(false); |
|
}, |
|
deflate: options.deflate || null, |
|
inflate: options.inflate || null |
|
}; |
|
/** |
|
* Resets a closed TLS connection for reuse. Called in c.close(). |
|
* |
|
* @param clearFail true to clear the fail flag (default: true). |
|
*/ c4.reset = function(clearFail) { |
|
c4.version = { |
|
major: $e55982d45da68b81$var$tls.Version.major, |
|
minor: $e55982d45da68b81$var$tls.Version.minor |
|
}; |
|
c4.record = null; |
|
c4.session = null; |
|
c4.peerCertificate = null; |
|
c4.state = { |
|
pending: null, |
|
current: null |
|
}; |
|
c4.expect = c4.entity === $e55982d45da68b81$var$tls.ConnectionEnd.client ? $e55982d45da68b81$var$SHE : $e55982d45da68b81$var$CHE; |
|
c4.fragmented = null; |
|
c4.records = []; |
|
c4.open = false; |
|
c4.handshakes = 0; |
|
c4.handshaking = false; |
|
c4.isConnected = false; |
|
c4.fail = !(clearFail || typeof clearFail === 'undefined'); |
|
c4.input.clear(); |
|
c4.tlsData.clear(); |
|
c4.data.clear(); |
|
c4.state.current = $e55982d45da68b81$var$tls.createConnectionState(c4); |
|
}; |
|
// do initial reset of connection |
|
c4.reset(); |
|
/** |
|
* Updates the current TLS engine state based on the given record. |
|
* |
|
* @param c the TLS connection. |
|
* @param record the TLS record to act on. |
|
*/ var _update = function(c, record) { |
|
// get record handler (align type in table by subtracting lowest) |
|
var aligned = record.type - $e55982d45da68b81$var$tls.ContentType.change_cipher_spec; |
|
var handlers = $e55982d45da68b81$var$ctTable[c.entity][c.expect]; |
|
if (aligned in handlers) handlers[aligned](c, record); |
|
else // unexpected record |
|
$e55982d45da68b81$var$tls.handleUnexpected(c, record); |
|
}; |
|
/** |
|
* Reads the record header and initializes the next record on the given |
|
* connection. |
|
* |
|
* @param c the TLS connection with the next record. |
|
* |
|
* @return 0 if the input data could be processed, otherwise the |
|
* number of bytes required for data to be processed. |
|
*/ var _readRecordHeader = function(c) { |
|
var rval = 0; |
|
// get input buffer and its length |
|
var b = c.input; |
|
var len = b.length(); |
|
// need at least 5 bytes to initialize a record |
|
if (len < 5) rval = 5 - len; |
|
else { |
|
// enough bytes for header |
|
// initialize record |
|
c.record = { |
|
type: b.getByte(), |
|
version: { |
|
major: b.getByte(), |
|
minor: b.getByte() |
|
}, |
|
length: b.getInt16(), |
|
fragment: $iGlOy.util.createBuffer(), |
|
ready: false |
|
}; |
|
// check record version |
|
var compatibleVersion = c.record.version.major === c.version.major; |
|
if (compatibleVersion && c.session && c.session.version) // session version already set, require same minor version |
|
compatibleVersion = c.record.version.minor === c.version.minor; |
|
if (!compatibleVersion) c.error(c, { |
|
message: 'Incompatible TLS version.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.protocol_version |
|
} |
|
}); |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Reads the next record's contents and appends its message to any |
|
* previously fragmented message. |
|
* |
|
* @param c the TLS connection with the next record. |
|
* |
|
* @return 0 if the input data could be processed, otherwise the |
|
* number of bytes required for data to be processed. |
|
*/ var _readRecord = function(c) { |
|
var rval = 0; |
|
// ensure there is enough input data to get the entire record |
|
var b = c.input; |
|
var len = b.length(); |
|
if (len < c.record.length) // not enough data yet, return how much is required |
|
rval = c.record.length - len; |
|
else { |
|
// there is enough data to parse the pending record |
|
// fill record fragment and compact input buffer |
|
c.record.fragment.putBytes(b.getBytes(c.record.length)); |
|
b.compact(); |
|
// update record using current read state |
|
var s = c.state.current.read; |
|
if (s.update(c, c.record)) { |
|
// see if there is a previously fragmented message that the |
|
// new record's message fragment should be appended to |
|
if (c.fragmented !== null) { |
|
// if the record type matches a previously fragmented |
|
// record, append the record fragment to it |
|
if (c.fragmented.type === c.record.type) { |
|
// concatenate record fragments |
|
c.fragmented.fragment.putBuffer(c.record.fragment); |
|
c.record = c.fragmented; |
|
} else // error, invalid fragmented record |
|
c.error(c, { |
|
message: 'Invalid fragmented record.', |
|
send: true, |
|
alert: { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.fatal, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.unexpected_message |
|
} |
|
}); |
|
} |
|
// record is now ready |
|
c.record.ready = true; |
|
} |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Performs a handshake using the TLS Handshake Protocol, as a client. |
|
* |
|
* This method should only be called if the connection is in client mode. |
|
* |
|
* @param sessionId the session ID to use, null to start a new one. |
|
*/ c4.handshake = function(sessionId) { |
|
// error to call this in non-client mode |
|
if (c4.entity !== $e55982d45da68b81$var$tls.ConnectionEnd.client) // not fatal error |
|
c4.error(c4, { |
|
message: 'Cannot initiate handshake as a server.', |
|
fatal: false |
|
}); |
|
else if (c4.handshaking) // handshake is already in progress, fail but not fatal error |
|
c4.error(c4, { |
|
message: 'Handshake already in progress.', |
|
fatal: false |
|
}); |
|
else { |
|
// clear fail flag on reuse |
|
if (c4.fail && !c4.open && c4.handshakes === 0) c4.fail = false; |
|
// now handshaking |
|
c4.handshaking = true; |
|
// default to blank (new session) |
|
sessionId = sessionId || ''; |
|
// if a session ID was specified, try to find it in the cache |
|
var session = null; |
|
if (sessionId.length > 0) { |
|
if (c4.sessionCache) session = c4.sessionCache.getSession(sessionId); |
|
// matching session not found in cache, clear session ID |
|
if (session === null) sessionId = ''; |
|
} |
|
// no session given, grab a session from the cache, if available |
|
if (sessionId.length === 0 && c4.sessionCache) { |
|
session = c4.sessionCache.getSession(); |
|
if (session !== null) sessionId = session.id; |
|
} |
|
// set up session |
|
c4.session = { |
|
id: sessionId, |
|
version: null, |
|
cipherSuite: null, |
|
compressionMethod: null, |
|
serverCertificate: null, |
|
certificateRequest: null, |
|
clientCertificate: null, |
|
sp: { |
|
}, |
|
md5: $iGlOy.md.md5.create(), |
|
sha1: $iGlOy.md.sha1.create() |
|
}; |
|
// use existing session information |
|
if (session) { |
|
// only update version on connection, session version not yet set |
|
c4.version = session.version; |
|
c4.session.sp = session.sp; |
|
} |
|
// generate new client random |
|
c4.session.sp.client_random = $e55982d45da68b81$var$tls.createRandom().getBytes(); |
|
// connection now open |
|
c4.open = true; |
|
// send hello |
|
$e55982d45da68b81$var$tls.queue(c4, $e55982d45da68b81$var$tls.createRecord(c4, { |
|
type: $e55982d45da68b81$var$tls.ContentType.handshake, |
|
data: $e55982d45da68b81$var$tls.createClientHello(c4) |
|
})); |
|
$e55982d45da68b81$var$tls.flush(c4); |
|
} |
|
}; |
|
/** |
|
* Called when TLS protocol data has been received from somewhere and should |
|
* be processed by the TLS engine. |
|
* |
|
* @param data the TLS protocol data, as a string, to process. |
|
* |
|
* @return 0 if the data could be processed, otherwise the number of bytes |
|
* required for data to be processed. |
|
*/ c4.process = function(data) { |
|
var rval = 0; |
|
// buffer input data |
|
if (data) c4.input.putBytes(data); |
|
// process next record if no failure, process will be called after |
|
// each record is handled (since handling can be asynchronous) |
|
if (!c4.fail) { |
|
// reset record if ready and now empty |
|
if (c4.record !== null && c4.record.ready && c4.record.fragment.isEmpty()) c4.record = null; |
|
// if there is no pending record, try to read record header |
|
if (c4.record === null) rval = _readRecordHeader(c4); |
|
// read the next record (if record not yet ready) |
|
if (!c4.fail && c4.record !== null && !c4.record.ready) rval = _readRecord(c4); |
|
// record ready to be handled, update engine state |
|
if (!c4.fail && c4.record !== null && c4.record.ready) _update(c4, c4.record); |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Requests that application data be packaged into a TLS record. The |
|
* tlsDataReady handler will be called when the TLS record(s) have been |
|
* prepared. |
|
* |
|
* @param data the application data, as a raw 'binary' encoded string, to |
|
* be sent; to send utf-16/utf-8 string data, use the return value |
|
* of util.encodeUtf8(str). |
|
* |
|
* @return true on success, false on failure. |
|
*/ c4.prepare = function(data) { |
|
$e55982d45da68b81$var$tls.queue(c4, $e55982d45da68b81$var$tls.createRecord(c4, { |
|
type: $e55982d45da68b81$var$tls.ContentType.application_data, |
|
data: $iGlOy.util.createBuffer(data) |
|
})); |
|
return $e55982d45da68b81$var$tls.flush(c4); |
|
}; |
|
/** |
|
* Requests that a heartbeat request be packaged into a TLS record for |
|
* transmission. The tlsDataReady handler will be called when TLS record(s) |
|
* have been prepared. |
|
* |
|
* When a heartbeat response has been received, the heartbeatReceived |
|
* handler will be called with the matching payload. This handler can |
|
* be used to clear a retransmission timer, etc. |
|
* |
|
* @param payload the heartbeat data to send as the payload in the message. |
|
* @param [payloadLength] the payload length to use, defaults to the |
|
* actual payload length. |
|
* |
|
* @return true on success, false on failure. |
|
*/ c4.prepareHeartbeatRequest = function(payload, payloadLength) { |
|
if (payload instanceof $iGlOy.util.ByteBuffer) payload = payload.bytes(); |
|
if (typeof payloadLength === 'undefined') payloadLength = payload.length; |
|
c4.expectedHeartbeatPayload = payload; |
|
$e55982d45da68b81$var$tls.queue(c4, $e55982d45da68b81$var$tls.createRecord(c4, { |
|
type: $e55982d45da68b81$var$tls.ContentType.heartbeat, |
|
data: $e55982d45da68b81$var$tls.createHeartbeat($e55982d45da68b81$var$tls.HeartbeatMessageType.heartbeat_request, payload, payloadLength) |
|
})); |
|
return $e55982d45da68b81$var$tls.flush(c4); |
|
}; |
|
/** |
|
* Closes the connection (sends a close_notify alert). |
|
* |
|
* @param clearFail true to clear the fail flag (default: true). |
|
*/ c4.close = function(clearFail) { |
|
// save session if connection didn't fail |
|
if (!c4.fail && c4.sessionCache && c4.session) { |
|
// only need to preserve session ID, version, and security params |
|
var session = { |
|
id: c4.session.id, |
|
version: c4.session.version, |
|
sp: c4.session.sp |
|
}; |
|
session.sp.keys = null; |
|
c4.sessionCache.setSession(session.id, session); |
|
} |
|
if (c4.open) { |
|
// connection no longer open, clear input |
|
c4.open = false; |
|
c4.input.clear(); |
|
// if connected or handshaking, send an alert |
|
if (c4.isConnected || c4.handshaking) { |
|
c4.isConnected = c4.handshaking = false; |
|
// send close_notify alert |
|
$e55982d45da68b81$var$tls.queue(c4, $e55982d45da68b81$var$tls.createAlert(c4, { |
|
level: $e55982d45da68b81$var$tls.Alert.Level.warning, |
|
description: $e55982d45da68b81$var$tls.Alert.Description.close_notify |
|
})); |
|
$e55982d45da68b81$var$tls.flush(c4); |
|
} |
|
// call handler |
|
c4.closed(c4); |
|
} |
|
// reset TLS connection, do not clear fail flag |
|
c4.reset(clearFail); |
|
}; |
|
return c4; |
|
}; |
|
/* TLS API */ $e55982d45da68b81$exports = $iGlOy.tls = $iGlOy.tls || { |
|
}; |
|
// expose non-functions |
|
for(var $e55982d45da68b81$var$key in $e55982d45da68b81$var$tls)if (typeof $e55982d45da68b81$var$tls[$e55982d45da68b81$var$key] !== 'function') $iGlOy.tls[$e55982d45da68b81$var$key] = $e55982d45da68b81$var$tls[$e55982d45da68b81$var$key]; |
|
// expose prf_tls1 for testing |
|
$iGlOy.tls.prf_tls1 = $e55982d45da68b81$var$prf_TLS1; |
|
// expose sha1 hmac method |
|
$iGlOy.tls.hmac_sha1 = $e55982d45da68b81$var$hmac_sha1; |
|
// expose session cache creation |
|
$iGlOy.tls.createSessionCache = $e55982d45da68b81$var$tls.createSessionCache; |
|
/** |
|
* Creates a new TLS connection. This does not make any assumptions about the |
|
* transport layer that TLS is working on top of, ie: it does not assume there |
|
* is a TCP/IP connection or establish one. A TLS connection is totally |
|
* abstracted away from the layer is runs on top of, it merely establishes a |
|
* secure channel between a client" and a "server". |
|
* |
|
* A TLS connection contains 4 connection states: pending read and write, and |
|
* current read and write. |
|
* |
|
* At initialization, the current read and write states will be null. Only once |
|
* the security parameters have been set and the keys have been generated can |
|
* the pending states be converted into current states. Current states will be |
|
* updated for each record processed. |
|
* |
|
* A custom certificate verify callback may be provided to check information |
|
* like the common name on the server's certificate. It will be called for |
|
* every certificate in the chain. It has the following signature: |
|
* |
|
* variable func(c, certs, index, preVerify) |
|
* Where: |
|
* c The TLS connection |
|
* verified Set to true if certificate was verified, otherwise the alert |
|
* tls.Alert.Description for why the certificate failed. |
|
* depth The current index in the chain, where 0 is the server's cert. |
|
* certs The certificate chain, *NOTE* if the server was anonymous then |
|
* the chain will be empty. |
|
* |
|
* The function returns true on success and on failure either the appropriate |
|
* tls.Alert.Description or an object with 'alert' set to the appropriate |
|
* tls.Alert.Description and 'message' set to a custom error message. If true |
|
* is not returned then the connection will abort using, in order of |
|
* availability, first the returned alert description, second the preVerify |
|
* alert description, and lastly the default 'bad_certificate'. |
|
* |
|
* There are three callbacks that can be used to make use of client-side |
|
* certificates where each takes the TLS connection as the first parameter: |
|
* |
|
* getCertificate(conn, hint) |
|
* The second parameter is a hint as to which certificate should be |
|
* returned. If the connection entity is a client, then the hint will be |
|
* the CertificateRequest message from the server that is part of the |
|
* TLS protocol. If the connection entity is a server, then it will be |
|
* the servername list provided via an SNI extension the ClientHello, if |
|
* one was provided (empty array if not). The hint can be examined to |
|
* determine which certificate to use (advanced). Most implementations |
|
* will just return a certificate. The return value must be a |
|
* PEM-formatted certificate or an array of PEM-formatted certificates |
|
* that constitute a certificate chain, with the first in the array/chain |
|
* being the client's certificate. |
|
* getPrivateKey(conn, certificate) |
|
* The second parameter is an forge.pki X.509 certificate object that |
|
* is associated with the requested private key. The return value must |
|
* be a PEM-formatted private key. |
|
* getSignature(conn, bytes, callback) |
|
* This callback can be used instead of getPrivateKey if the private key |
|
* is not directly accessible in javascript or should not be. For |
|
* instance, a secure external web service could provide the signature |
|
* in exchange for appropriate credentials. The second parameter is a |
|
* string of bytes to be signed that are part of the TLS protocol. These |
|
* bytes are used to verify that the private key for the previously |
|
* provided client-side certificate is accessible to the client. The |
|
* callback is a function that takes 2 parameters, the TLS connection |
|
* and the RSA encrypted (signed) bytes as a string. This callback must |
|
* be called once the signature is ready. |
|
* |
|
* @param options the options for this connection: |
|
* server: true if the connection is server-side, false for client. |
|
* sessionId: a session ID to reuse, null for a new connection. |
|
* caStore: an array of certificates to trust. |
|
* sessionCache: a session cache to use. |
|
* cipherSuites: an optional array of cipher suites to use, |
|
* see tls.CipherSuites. |
|
* connected: function(conn) called when the first handshake completes. |
|
* virtualHost: the virtual server name to use in a TLS SNI extension. |
|
* verifyClient: true to require a client certificate in server mode, |
|
* 'optional' to request one, false not to (default: false). |
|
* verify: a handler used to custom verify certificates in the chain. |
|
* verifyOptions: an object with options for the certificate chain validation. |
|
* See documentation of pki.verifyCertificateChain for possible options. |
|
* verifyOptions.verify is ignored. If you wish to specify a verify handler |
|
* use the verify key. |
|
* getCertificate: an optional callback used to get a certificate or |
|
* a chain of certificates (as an array). |
|
* getPrivateKey: an optional callback used to get a private key. |
|
* getSignature: an optional callback used to get a signature. |
|
* tlsDataReady: function(conn) called when TLS protocol data has been |
|
* prepared and is ready to be used (typically sent over a socket |
|
* connection to its destination), read from conn.tlsData buffer. |
|
* dataReady: function(conn) called when application data has |
|
* been parsed from a TLS record and should be consumed by the |
|
* application, read from conn.data buffer. |
|
* closed: function(conn) called when the connection has been closed. |
|
* error: function(conn, error) called when there was an error. |
|
* deflate: function(inBytes) if provided, will deflate TLS records using |
|
* the deflate algorithm if the server supports it. |
|
* inflate: function(inBytes) if provided, will inflate TLS records using |
|
* the deflate algorithm if the server supports it. |
|
* |
|
* @return the new TLS connection. |
|
*/ $iGlOy.tls.createConnection = $e55982d45da68b81$var$tls.createConnection; |
|
|
|
|
|
var $48103dfbc323e2e4$var$tls = $48103dfbc323e2e4$exports = $iGlOy.tls; |
|
/** |
|
* Supported cipher suites. |
|
*/ $48103dfbc323e2e4$var$tls.CipherSuites['TLS_RSA_WITH_AES_128_CBC_SHA'] = { |
|
id: [ |
|
0, |
|
47 |
|
], |
|
name: 'TLS_RSA_WITH_AES_128_CBC_SHA', |
|
initSecurityParameters: function(sp) { |
|
sp.bulk_cipher_algorithm = $48103dfbc323e2e4$var$tls.BulkCipherAlgorithm.aes; |
|
sp.cipher_type = $48103dfbc323e2e4$var$tls.CipherType.block; |
|
sp.enc_key_length = 16; |
|
sp.block_length = 16; |
|
sp.fixed_iv_length = 16; |
|
sp.record_iv_length = 16; |
|
sp.mac_algorithm = $48103dfbc323e2e4$var$tls.MACAlgorithm.hmac_sha1; |
|
sp.mac_length = 20; |
|
sp.mac_key_length = 20; |
|
}, |
|
initConnectionState: $48103dfbc323e2e4$var$initConnectionState |
|
}; |
|
$48103dfbc323e2e4$var$tls.CipherSuites['TLS_RSA_WITH_AES_256_CBC_SHA'] = { |
|
id: [ |
|
0, |
|
53 |
|
], |
|
name: 'TLS_RSA_WITH_AES_256_CBC_SHA', |
|
initSecurityParameters: function(sp) { |
|
sp.bulk_cipher_algorithm = $48103dfbc323e2e4$var$tls.BulkCipherAlgorithm.aes; |
|
sp.cipher_type = $48103dfbc323e2e4$var$tls.CipherType.block; |
|
sp.enc_key_length = 32; |
|
sp.block_length = 16; |
|
sp.fixed_iv_length = 16; |
|
sp.record_iv_length = 16; |
|
sp.mac_algorithm = $48103dfbc323e2e4$var$tls.MACAlgorithm.hmac_sha1; |
|
sp.mac_length = 20; |
|
sp.mac_key_length = 20; |
|
}, |
|
initConnectionState: $48103dfbc323e2e4$var$initConnectionState |
|
}; |
|
function $48103dfbc323e2e4$var$initConnectionState(state, c, sp) { |
|
var client = c.entity === $iGlOy.tls.ConnectionEnd.client; |
|
// cipher setup |
|
state.read.cipherState = { |
|
init: false, |
|
cipher: $iGlOy.cipher.createDecipher('AES-CBC', client ? sp.keys.server_write_key : sp.keys.client_write_key), |
|
iv: client ? sp.keys.server_write_IV : sp.keys.client_write_IV |
|
}; |
|
state.write.cipherState = { |
|
init: false, |
|
cipher: $iGlOy.cipher.createCipher('AES-CBC', client ? sp.keys.client_write_key : sp.keys.server_write_key), |
|
iv: client ? sp.keys.client_write_IV : sp.keys.server_write_IV |
|
}; |
|
state.read.cipherFunction = $48103dfbc323e2e4$var$decrypt_aes_cbc_sha1; |
|
state.write.cipherFunction = $48103dfbc323e2e4$var$encrypt_aes_cbc_sha1; |
|
// MAC setup |
|
state.read.macLength = state.write.macLength = sp.mac_length; |
|
state.read.macFunction = state.write.macFunction = $48103dfbc323e2e4$var$tls.hmac_sha1; |
|
} |
|
/** |
|
* Encrypts the TLSCompressed record into a TLSCipherText record using AES |
|
* in CBC mode. |
|
* |
|
* @param record the TLSCompressed record to encrypt. |
|
* @param s the ConnectionState to use. |
|
* |
|
* @return true on success, false on failure. |
|
*/ function $48103dfbc323e2e4$var$encrypt_aes_cbc_sha1(record, s) { |
|
var rval = false; |
|
// append MAC to fragment, update sequence number |
|
var mac = s.macFunction(s.macKey, s.sequenceNumber, record); |
|
record.fragment.putBytes(mac); |
|
s.updateSequenceNumber(); |
|
// TLS 1.1+ use an explicit IV every time to protect against CBC attacks |
|
var iv; |
|
if (record.version.minor === $48103dfbc323e2e4$var$tls.Versions.TLS_1_0.minor) // use the pre-generated IV when initializing for TLS 1.0, otherwise use |
|
// the residue from the previous encryption |
|
iv = s.cipherState.init ? null : s.cipherState.iv; |
|
else iv = $iGlOy.random.getBytesSync(16); |
|
s.cipherState.init = true; |
|
// start cipher |
|
var cipher = s.cipherState.cipher; |
|
cipher.start({ |
|
iv: iv |
|
}); |
|
// TLS 1.1+ write IV into output |
|
if (record.version.minor >= $48103dfbc323e2e4$var$tls.Versions.TLS_1_1.minor) cipher.output.putBytes(iv); |
|
// do encryption (default padding is appropriate) |
|
cipher.update(record.fragment); |
|
if (cipher.finish($48103dfbc323e2e4$var$encrypt_aes_cbc_sha1_padding)) { |
|
// set record fragment to encrypted output |
|
record.fragment = cipher.output; |
|
record.length = record.fragment.length(); |
|
rval = true; |
|
} |
|
return rval; |
|
} |
|
/** |
|
* Handles padding for aes_cbc_sha1 in encrypt mode. |
|
* |
|
* @param blockSize the block size. |
|
* @param input the input buffer. |
|
* @param decrypt true in decrypt mode, false in encrypt mode. |
|
* |
|
* @return true on success, false on failure. |
|
*/ function $48103dfbc323e2e4$var$encrypt_aes_cbc_sha1_padding(blockSize, input, decrypt) { |
|
/* The encrypted data length (TLSCiphertext.length) is one more than the sum |
|
of SecurityParameters.block_length, TLSCompressed.length, |
|
SecurityParameters.mac_length, and padding_length. |
|
|
|
The padding may be any length up to 255 bytes long, as long as it results in |
|
the TLSCiphertext.length being an integral multiple of the block length. |
|
Lengths longer than necessary might be desirable to frustrate attacks on a |
|
protocol based on analysis of the lengths of exchanged messages. Each uint8 |
|
in the padding data vector must be filled with the padding length value. |
|
|
|
The padding length should be such that the total size of the |
|
GenericBlockCipher structure is a multiple of the cipher's block length. |
|
Legal values range from zero to 255, inclusive. This length specifies the |
|
length of the padding field exclusive of the padding_length field itself. |
|
|
|
This is slightly different from PKCS#7 because the padding value is 1 |
|
less than the actual number of padding bytes if you include the |
|
padding_length uint8 itself as a padding byte. */ if (!decrypt) { |
|
// get the number of padding bytes required to reach the blockSize and |
|
// subtract 1 for the padding value (to make room for the padding_length |
|
// uint8) |
|
var padding = blockSize - input.length() % blockSize; |
|
input.fillWithByte(padding - 1, padding); |
|
} |
|
return true; |
|
} |
|
/** |
|
* Handles padding for aes_cbc_sha1 in decrypt mode. |
|
* |
|
* @param blockSize the block size. |
|
* @param output the output buffer. |
|
* @param decrypt true in decrypt mode, false in encrypt mode. |
|
* |
|
* @return true on success, false on failure. |
|
*/ function $48103dfbc323e2e4$var$decrypt_aes_cbc_sha1_padding(blockSize, output, decrypt) { |
|
var rval = true; |
|
if (decrypt) { |
|
/* The last byte in the output specifies the number of padding bytes not |
|
including itself. Each of the padding bytes has the same value as that |
|
last byte (known as the padding_length). Here we check all padding |
|
bytes to ensure they have the value of padding_length even if one of |
|
them is bad in order to ward-off timing attacks. */ var len = output.length(); |
|
var paddingLength = output.last(); |
|
for(var i = len - 1 - paddingLength; i < len - 1; ++i)rval = rval && output.at(i) == paddingLength; |
|
if (rval) // trim off padding bytes and last padding length byte |
|
output.truncate(paddingLength + 1); |
|
} |
|
return rval; |
|
} |
|
/** |
|
* Decrypts a TLSCipherText record into a TLSCompressed record using |
|
* AES in CBC mode. |
|
* |
|
* @param record the TLSCipherText record to decrypt. |
|
* @param s the ConnectionState to use. |
|
* |
|
* @return true on success, false on failure. |
|
*/ function $48103dfbc323e2e4$var$decrypt_aes_cbc_sha1(record, s) { |
|
var rval = false; |
|
var iv; |
|
if (record.version.minor === $48103dfbc323e2e4$var$tls.Versions.TLS_1_0.minor) // use pre-generated IV when initializing for TLS 1.0, otherwise use the |
|
// residue from the previous decryption |
|
iv = s.cipherState.init ? null : s.cipherState.iv; |
|
else // TLS 1.1+ use an explicit IV every time to protect against CBC attacks |
|
// that is appended to the record fragment |
|
iv = record.fragment.getBytes(16); |
|
s.cipherState.init = true; |
|
// start cipher |
|
var cipher = s.cipherState.cipher; |
|
cipher.start({ |
|
iv: iv |
|
}); |
|
// do decryption |
|
cipher.update(record.fragment); |
|
rval = cipher.finish($48103dfbc323e2e4$var$decrypt_aes_cbc_sha1_padding); |
|
// even if decryption fails, keep going to minimize timing attacks |
|
// decrypted data: |
|
// first (len - 20) bytes = application data |
|
// last 20 bytes = MAC |
|
var macLen = s.macLength; |
|
// create a random MAC to check against should the mac length check fail |
|
// Note: do this regardless of the failure to keep timing consistent |
|
var mac = $iGlOy.random.getBytesSync(macLen); |
|
// get fragment and mac |
|
var len = cipher.output.length(); |
|
if (len >= macLen) { |
|
record.fragment = cipher.output.getBytes(len - macLen); |
|
mac = cipher.output.getBytes(macLen); |
|
} else // bad data, but get bytes anyway to try to keep timing consistent |
|
record.fragment = cipher.output.getBytes(); |
|
record.fragment = $iGlOy.util.createBuffer(record.fragment); |
|
record.length = record.fragment.length(); |
|
// see if data integrity checks out, update sequence number |
|
var mac2 = s.macFunction(s.macKey, s.sequenceNumber, record); |
|
s.updateSequenceNumber(); |
|
rval = $48103dfbc323e2e4$var$compareMacs(s.macKey, mac, mac2) && rval; |
|
return rval; |
|
} |
|
/** |
|
* Safely compare two MACs. This function will compare two MACs in a way |
|
* that protects against timing attacks. |
|
* |
|
* TODO: Expose elsewhere as a utility API. |
|
* |
|
* See: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ |
|
* |
|
* @param key the MAC key to use. |
|
* @param mac1 as a binary-encoded string of bytes. |
|
* @param mac2 as a binary-encoded string of bytes. |
|
* |
|
* @return true if the MACs are the same, false if not. |
|
*/ function $48103dfbc323e2e4$var$compareMacs(key, mac1, mac2) { |
|
var hmac = $iGlOy.hmac.create(); |
|
hmac.start('SHA1', key); |
|
hmac.update(mac1); |
|
mac1 = hmac.digest().getBytes(); |
|
hmac.start(null, null); |
|
hmac.update(mac2); |
|
mac2 = hmac.digest().getBytes(); |
|
return mac1 === mac2; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
var $96695cc1b97188e1$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
var $33c8fc1a702f0359$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
parcelRequire("ai0Z9"); |
|
|
|
var $33c8fc1a702f0359$var$sha512 = $33c8fc1a702f0359$exports = $iGlOy.sha512 = $iGlOy.sha512 || { |
|
}; |
|
// SHA-512 |
|
$iGlOy.md.sha512 = $iGlOy.md.algorithms.sha512 = $33c8fc1a702f0359$var$sha512; |
|
// SHA-384 |
|
var $33c8fc1a702f0359$var$sha384 = $iGlOy.sha384 = $iGlOy.sha512.sha384 = $iGlOy.sha512.sha384 || { |
|
}; |
|
$33c8fc1a702f0359$var$sha384.create = function() { |
|
return $33c8fc1a702f0359$var$sha512.create('SHA-384'); |
|
}; |
|
$iGlOy.md.sha384 = $iGlOy.md.algorithms.sha384 = $33c8fc1a702f0359$var$sha384; |
|
// SHA-512/256 |
|
$iGlOy.sha512.sha256 = $iGlOy.sha512.sha256 || { |
|
create: function() { |
|
return $33c8fc1a702f0359$var$sha512.create('SHA-512/256'); |
|
} |
|
}; |
|
$iGlOy.md['sha512/256'] = $iGlOy.md.algorithms['sha512/256'] = $iGlOy.sha512.sha256; |
|
// SHA-512/224 |
|
$iGlOy.sha512.sha224 = $iGlOy.sha512.sha224 || { |
|
create: function() { |
|
return $33c8fc1a702f0359$var$sha512.create('SHA-512/224'); |
|
} |
|
}; |
|
$iGlOy.md['sha512/224'] = $iGlOy.md.algorithms['sha512/224'] = $iGlOy.sha512.sha224; |
|
/** |
|
* Creates a SHA-2 message digest object. |
|
* |
|
* @param algorithm the algorithm to use (SHA-512, SHA-384, SHA-512/224, |
|
* SHA-512/256). |
|
* |
|
* @return a message digest object. |
|
*/ $33c8fc1a702f0359$var$sha512.create = function(algorithm) { |
|
// do initialization as necessary |
|
if (!$33c8fc1a702f0359$var$_initialized) $33c8fc1a702f0359$var$_init(); |
|
if (typeof algorithm === 'undefined') algorithm = 'SHA-512'; |
|
if (!(algorithm in $33c8fc1a702f0359$var$_states)) throw new Error('Invalid SHA-512 algorithm: ' + algorithm); |
|
// SHA-512 state contains eight 64-bit integers (each as two 32-bit ints) |
|
var _state = $33c8fc1a702f0359$var$_states[algorithm]; |
|
var _h = null; |
|
// input buffer |
|
var _input = $iGlOy.util.createBuffer(); |
|
// used for 64-bit word storage |
|
var _w = new Array(80); |
|
for(var wi = 0; wi < 80; ++wi)_w[wi] = new Array(2); |
|
// determine digest length by algorithm name (default) |
|
var digestLength = 64; |
|
switch(algorithm){ |
|
case 'SHA-384': |
|
digestLength = 48; |
|
break; |
|
case 'SHA-512/256': |
|
digestLength = 32; |
|
break; |
|
case 'SHA-512/224': |
|
digestLength = 28; |
|
break; |
|
} |
|
// message digest object |
|
var md = { |
|
// SHA-512 => sha512 |
|
algorithm: algorithm.replace('-', '').toLowerCase(), |
|
blockLength: 128, |
|
digestLength: digestLength, |
|
// 56-bit length of message so far (does not including padding) |
|
messageLength: 0, |
|
// true message length |
|
fullMessageLength: null, |
|
// size of message length in bytes |
|
messageLengthSize: 16 |
|
}; |
|
/** |
|
* Starts the digest. |
|
* |
|
* @return this digest object. |
|
*/ md.start = function() { |
|
// up to 56-bit message length for convenience |
|
md.messageLength = 0; |
|
// full message length (set md.messageLength128 for backwards-compatibility) |
|
md.fullMessageLength = md.messageLength128 = []; |
|
var int32s = md.messageLengthSize / 4; |
|
for(var i = 0; i < int32s; ++i)md.fullMessageLength.push(0); |
|
_input = $iGlOy.util.createBuffer(); |
|
_h = new Array(_state.length); |
|
for(var i = 0; i < _state.length; ++i)_h[i] = _state[i].slice(0); |
|
return md; |
|
}; |
|
// start digest automatically for first time |
|
md.start(); |
|
/** |
|
* Updates the digest with the given message input. The given input can |
|
* treated as raw input (no encoding will be applied) or an encoding of |
|
* 'utf8' maybe given to encode the input using UTF-8. |
|
* |
|
* @param msg the message input to update with. |
|
* @param encoding the encoding to use (default: 'raw', other: 'utf8'). |
|
* |
|
* @return this digest object. |
|
*/ md.update = function(msg, encoding) { |
|
if (encoding === 'utf8') msg = $iGlOy.util.encodeUtf8(msg); |
|
// update message length |
|
var len = msg.length; |
|
md.messageLength += len; |
|
len = [ |
|
len / 4294967296 >>> 0, |
|
len >>> 0 |
|
]; |
|
for(var i = md.fullMessageLength.length - 1; i >= 0; --i){ |
|
md.fullMessageLength[i] += len[1]; |
|
len[1] = len[0] + (md.fullMessageLength[i] / 4294967296 >>> 0); |
|
md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; |
|
len[0] = len[1] / 4294967296 >>> 0; |
|
} |
|
// add bytes to input buffer |
|
_input.putBytes(msg); |
|
// process bytes |
|
$33c8fc1a702f0359$var$_update(_h, _w, _input); |
|
// compact input buffer every 2K or if empty |
|
if (_input.read > 2048 || _input.length() === 0) _input.compact(); |
|
return md; |
|
}; |
|
/** |
|
* Produces the digest. |
|
* |
|
* @return a byte buffer containing the digest value. |
|
*/ md.digest = function() { |
|
/* Note: Here we copy the remaining bytes in the input buffer and |
|
add the appropriate SHA-512 padding. Then we do the final update |
|
on a copy of the state so that if the user wants to get |
|
intermediate digests they can do so. */ /* Determine the number of bytes that must be added to the message |
|
to ensure its length is congruent to 896 mod 1024. In other words, |
|
the data to be digested must be a multiple of 1024 bits (or 128 bytes). |
|
This data includes the message, some padding, and the length of the |
|
message. Since the length of the message will be encoded as 16 bytes (128 |
|
bits), that means that the last segment of the data must have 112 bytes |
|
(896 bits) of message and padding. Therefore, the length of the message |
|
plus the padding must be congruent to 896 mod 1024 because |
|
1024 - 128 = 896. |
|
|
|
In order to fill up the message length it must be filled with |
|
padding that begins with 1 bit followed by all 0 bits. Padding |
|
must *always* be present, so if the message length is already |
|
congruent to 896 mod 1024, then 1024 padding bits must be added. */ var finalBlock = $iGlOy.util.createBuffer(); |
|
finalBlock.putBytes(_input.bytes()); |
|
// compute remaining size to be digested (include message length size) |
|
var remaining = md.fullMessageLength[md.fullMessageLength.length - 1] + md.messageLengthSize; |
|
// add padding for overflow blockSize - overflow |
|
// _padding starts with 1 byte with first bit is set (byte value 128), then |
|
// there may be up to (blockSize - 1) other pad bytes |
|
var overflow = remaining & md.blockLength - 1; |
|
finalBlock.putBytes($33c8fc1a702f0359$var$_padding.substr(0, md.blockLength - overflow)); |
|
// serialize message length in bits in big-endian order; since length |
|
// is stored in bytes we multiply by 8 and add carry from next int |
|
var next, carry; |
|
var bits = md.fullMessageLength[0] * 8; |
|
for(var i = 0; i < md.fullMessageLength.length - 1; ++i){ |
|
next = md.fullMessageLength[i + 1] * 8; |
|
carry = next / 4294967296 >>> 0; |
|
bits += carry; |
|
finalBlock.putInt32(bits >>> 0); |
|
bits = next >>> 0; |
|
} |
|
finalBlock.putInt32(bits); |
|
var h = new Array(_h.length); |
|
for(var i = 0; i < _h.length; ++i)h[i] = _h[i].slice(0); |
|
$33c8fc1a702f0359$var$_update(h, _w, finalBlock); |
|
var rval = $iGlOy.util.createBuffer(); |
|
var hlen; |
|
if (algorithm === 'SHA-512') hlen = h.length; |
|
else if (algorithm === 'SHA-384') hlen = h.length - 2; |
|
else hlen = h.length - 4; |
|
for(var i = 0; i < hlen; ++i){ |
|
rval.putInt32(h[i][0]); |
|
if (i !== hlen - 1 || algorithm !== 'SHA-512/224') rval.putInt32(h[i][1]); |
|
} |
|
return rval; |
|
}; |
|
return md; |
|
}; |
|
// sha-512 padding bytes not initialized yet |
|
var $33c8fc1a702f0359$var$_padding = null; |
|
var $33c8fc1a702f0359$var$_initialized = false; |
|
// table of constants |
|
var $33c8fc1a702f0359$var$_k = null; |
|
// initial hash states |
|
var $33c8fc1a702f0359$var$_states = null; |
|
/** |
|
* Initializes the constant tables. |
|
*/ function $33c8fc1a702f0359$var$_init() { |
|
// create padding |
|
$33c8fc1a702f0359$var$_padding = String.fromCharCode(128); |
|
$33c8fc1a702f0359$var$_padding += $iGlOy.util.fillString(String.fromCharCode(0), 128); |
|
// create K table for SHA-512 |
|
$33c8fc1a702f0359$var$_k = [ |
|
[ |
|
1116352408, |
|
3609767458 |
|
], |
|
[ |
|
1899447441, |
|
602891725 |
|
], |
|
[ |
|
3049323471, |
|
3964484399 |
|
], |
|
[ |
|
3921009573, |
|
2173295548 |
|
], |
|
[ |
|
961987163, |
|
4081628472 |
|
], |
|
[ |
|
1508970993, |
|
3053834265 |
|
], |
|
[ |
|
2453635748, |
|
2937671579 |
|
], |
|
[ |
|
2870763221, |
|
3664609560 |
|
], |
|
[ |
|
3624381080, |
|
2734883394 |
|
], |
|
[ |
|
310598401, |
|
1164996542 |
|
], |
|
[ |
|
607225278, |
|
1323610764 |
|
], |
|
[ |
|
1426881987, |
|
3590304994 |
|
], |
|
[ |
|
1925078388, |
|
4068182383 |
|
], |
|
[ |
|
2162078206, |
|
991336113 |
|
], |
|
[ |
|
2614888103, |
|
633803317 |
|
], |
|
[ |
|
3248222580, |
|
3479774868 |
|
], |
|
[ |
|
3835390401, |
|
2666613458 |
|
], |
|
[ |
|
4022224774, |
|
944711139 |
|
], |
|
[ |
|
264347078, |
|
2341262773 |
|
], |
|
[ |
|
604807628, |
|
2007800933 |
|
], |
|
[ |
|
770255983, |
|
1495990901 |
|
], |
|
[ |
|
1249150122, |
|
1856431235 |
|
], |
|
[ |
|
1555081692, |
|
3175218132 |
|
], |
|
[ |
|
1996064986, |
|
2198950837 |
|
], |
|
[ |
|
2554220882, |
|
3999719339 |
|
], |
|
[ |
|
2821834349, |
|
766784016 |
|
], |
|
[ |
|
2952996808, |
|
2566594879 |
|
], |
|
[ |
|
3210313671, |
|
3203337956 |
|
], |
|
[ |
|
3336571891, |
|
1034457026 |
|
], |
|
[ |
|
3584528711, |
|
2466948901 |
|
], |
|
[ |
|
113926993, |
|
3758326383 |
|
], |
|
[ |
|
338241895, |
|
168717936 |
|
], |
|
[ |
|
666307205, |
|
1188179964 |
|
], |
|
[ |
|
773529912, |
|
1546045734 |
|
], |
|
[ |
|
1294757372, |
|
1522805485 |
|
], |
|
[ |
|
1396182291, |
|
2643833823 |
|
], |
|
[ |
|
1695183700, |
|
2343527390 |
|
], |
|
[ |
|
1986661051, |
|
1014477480 |
|
], |
|
[ |
|
2177026350, |
|
1206759142 |
|
], |
|
[ |
|
2456956037, |
|
344077627 |
|
], |
|
[ |
|
2730485921, |
|
1290863460 |
|
], |
|
[ |
|
2820302411, |
|
3158454273 |
|
], |
|
[ |
|
3259730800, |
|
3505952657 |
|
], |
|
[ |
|
3345764771, |
|
106217008 |
|
], |
|
[ |
|
3516065817, |
|
3606008344 |
|
], |
|
[ |
|
3600352804, |
|
1432725776 |
|
], |
|
[ |
|
4094571909, |
|
1467031594 |
|
], |
|
[ |
|
275423344, |
|
851169720 |
|
], |
|
[ |
|
430227734, |
|
3100823752 |
|
], |
|
[ |
|
506948616, |
|
1363258195 |
|
], |
|
[ |
|
659060556, |
|
3750685593 |
|
], |
|
[ |
|
883997877, |
|
3785050280 |
|
], |
|
[ |
|
958139571, |
|
3318307427 |
|
], |
|
[ |
|
1322822218, |
|
3812723403 |
|
], |
|
[ |
|
1537002063, |
|
2003034995 |
|
], |
|
[ |
|
1747873779, |
|
3602036899 |
|
], |
|
[ |
|
1955562222, |
|
1575990012 |
|
], |
|
[ |
|
2024104815, |
|
1125592928 |
|
], |
|
[ |
|
2227730452, |
|
2716904306 |
|
], |
|
[ |
|
2361852424, |
|
442776044 |
|
], |
|
[ |
|
2428436474, |
|
593698344 |
|
], |
|
[ |
|
2756734187, |
|
3733110249 |
|
], |
|
[ |
|
3204031479, |
|
2999351573 |
|
], |
|
[ |
|
3329325298, |
|
3815920427 |
|
], |
|
[ |
|
3391569614, |
|
3928383900 |
|
], |
|
[ |
|
3515267271, |
|
566280711 |
|
], |
|
[ |
|
3940187606, |
|
3454069534 |
|
], |
|
[ |
|
4118630271, |
|
4000239992 |
|
], |
|
[ |
|
116418474, |
|
1914138554 |
|
], |
|
[ |
|
174292421, |
|
2731055270 |
|
], |
|
[ |
|
289380356, |
|
3203993006 |
|
], |
|
[ |
|
460393269, |
|
320620315 |
|
], |
|
[ |
|
685471733, |
|
587496836 |
|
], |
|
[ |
|
852142971, |
|
1086792851 |
|
], |
|
[ |
|
1017036298, |
|
365543100 |
|
], |
|
[ |
|
1126000580, |
|
2618297676 |
|
], |
|
[ |
|
1288033470, |
|
3409855158 |
|
], |
|
[ |
|
1501505948, |
|
4234509866 |
|
], |
|
[ |
|
1607167915, |
|
987167468 |
|
], |
|
[ |
|
1816402316, |
|
1246189591 |
|
] |
|
]; |
|
// initial hash states |
|
$33c8fc1a702f0359$var$_states = { |
|
}; |
|
$33c8fc1a702f0359$var$_states['SHA-512'] = [ |
|
[ |
|
1779033703, |
|
4089235720 |
|
], |
|
[ |
|
3144134277, |
|
2227873595 |
|
], |
|
[ |
|
1013904242, |
|
4271175723 |
|
], |
|
[ |
|
2773480762, |
|
1595750129 |
|
], |
|
[ |
|
1359893119, |
|
2917565137 |
|
], |
|
[ |
|
2600822924, |
|
725511199 |
|
], |
|
[ |
|
528734635, |
|
4215389547 |
|
], |
|
[ |
|
1541459225, |
|
327033209 |
|
] |
|
]; |
|
$33c8fc1a702f0359$var$_states['SHA-384'] = [ |
|
[ |
|
3418070365, |
|
3238371032 |
|
], |
|
[ |
|
1654270250, |
|
914150663 |
|
], |
|
[ |
|
2438529370, |
|
812702999 |
|
], |
|
[ |
|
355462360, |
|
4144912697 |
|
], |
|
[ |
|
1731405415, |
|
4290775857 |
|
], |
|
[ |
|
2394180231, |
|
1750603025 |
|
], |
|
[ |
|
3675008525, |
|
1694076839 |
|
], |
|
[ |
|
1203062813, |
|
3204075428 |
|
] |
|
]; |
|
$33c8fc1a702f0359$var$_states['SHA-512/256'] = [ |
|
[ |
|
573645204, |
|
4230739756 |
|
], |
|
[ |
|
2673172387, |
|
3360449730 |
|
], |
|
[ |
|
596883563, |
|
1867755857 |
|
], |
|
[ |
|
2520282905, |
|
1497426621 |
|
], |
|
[ |
|
2519219938, |
|
2827943907 |
|
], |
|
[ |
|
3193839141, |
|
1401305490 |
|
], |
|
[ |
|
721525244, |
|
746961066 |
|
], |
|
[ |
|
246885852, |
|
2177182882 |
|
] |
|
]; |
|
$33c8fc1a702f0359$var$_states['SHA-512/224'] = [ |
|
[ |
|
2352822216, |
|
424955298 |
|
], |
|
[ |
|
1944164710, |
|
2312950998 |
|
], |
|
[ |
|
502970286, |
|
855612546 |
|
], |
|
[ |
|
1738396948, |
|
1479516111 |
|
], |
|
[ |
|
258812777, |
|
2077511080 |
|
], |
|
[ |
|
2011393907, |
|
79989058 |
|
], |
|
[ |
|
1067287976, |
|
1780299464 |
|
], |
|
[ |
|
286451373, |
|
2446758561 |
|
] |
|
]; |
|
// now initialized |
|
$33c8fc1a702f0359$var$_initialized = true; |
|
} |
|
/** |
|
* Updates a SHA-512 state with the given byte buffer. |
|
* |
|
* @param s the SHA-512 state to update. |
|
* @param w the array to use to store words. |
|
* @param bytes the byte buffer to update with. |
|
*/ function $33c8fc1a702f0359$var$_update(s, w, bytes) { |
|
// consume 512 bit (128 byte) chunks |
|
var t1_hi, t1_lo; |
|
var t2_hi, t2_lo; |
|
var s0_hi, s0_lo; |
|
var s1_hi, s1_lo; |
|
var ch_hi, ch_lo; |
|
var maj_hi, maj_lo; |
|
var a_hi, a_lo; |
|
var b_hi, b_lo; |
|
var c_hi, c_lo; |
|
var d_hi, d_lo; |
|
var e_hi, e_lo; |
|
var f_hi, f_lo; |
|
var g_hi, g_lo; |
|
var h_hi, h_lo; |
|
var i, hi, lo, w2, w7, w15, w16; |
|
var len = bytes.length(); |
|
while(len >= 128){ |
|
// the w array will be populated with sixteen 64-bit big-endian words |
|
// and then extended into 64 64-bit words according to SHA-512 |
|
for(i = 0; i < 16; ++i){ |
|
w[i][0] = bytes.getInt32() >>> 0; |
|
w[i][1] = bytes.getInt32() >>> 0; |
|
} |
|
for(; i < 80; ++i){ |
|
// for word 2 words ago: ROTR 19(x) ^ ROTR 61(x) ^ SHR 6(x) |
|
w2 = w[i - 2]; |
|
hi = w2[0]; |
|
lo = w2[1]; |
|
// high bits |
|
t1_hi = ((hi >>> 19 | lo << 13) ^ (lo >>> 29 | hi << 3) ^ hi >>> 6) >>> 0; // SHR 6 |
|
// low bits |
|
t1_lo = ((hi << 13 | lo >>> 19) ^ (lo << 3 | hi >>> 29) ^ (hi << 26 | lo >>> 6)) >>> 0; // SHR 6 |
|
// for word 15 words ago: ROTR 1(x) ^ ROTR 8(x) ^ SHR 7(x) |
|
w15 = w[i - 15]; |
|
hi = w15[0]; |
|
lo = w15[1]; |
|
// high bits |
|
t2_hi = ((hi >>> 1 | lo << 31) ^ (hi >>> 8 | lo << 24) ^ hi >>> 7) >>> 0; // SHR 7 |
|
// low bits |
|
t2_lo = ((hi << 31 | lo >>> 1) ^ (hi << 24 | lo >>> 8) ^ (hi << 25 | lo >>> 7)) >>> 0; // SHR 7 |
|
// sum(t1, word 7 ago, t2, word 16 ago) modulo 2^64 (carry lo overflow) |
|
w7 = w[i - 7]; |
|
w16 = w[i - 16]; |
|
lo = t1_lo + w7[1] + t2_lo + w16[1]; |
|
w[i][0] = t1_hi + w7[0] + t2_hi + w16[0] + (lo / 4294967296 >>> 0) >>> 0; |
|
w[i][1] = lo >>> 0; |
|
} |
|
// initialize hash value for this chunk |
|
a_hi = s[0][0]; |
|
a_lo = s[0][1]; |
|
b_hi = s[1][0]; |
|
b_lo = s[1][1]; |
|
c_hi = s[2][0]; |
|
c_lo = s[2][1]; |
|
d_hi = s[3][0]; |
|
d_lo = s[3][1]; |
|
e_hi = s[4][0]; |
|
e_lo = s[4][1]; |
|
f_hi = s[5][0]; |
|
f_lo = s[5][1]; |
|
g_hi = s[6][0]; |
|
g_lo = s[6][1]; |
|
h_hi = s[7][0]; |
|
h_lo = s[7][1]; |
|
// round function |
|
for(i = 0; i < 80; ++i){ |
|
// Sum1(e) = ROTR 14(e) ^ ROTR 18(e) ^ ROTR 41(e) |
|
s1_hi = ((e_hi >>> 14 | e_lo << 18) ^ (e_hi >>> 18 | e_lo << 14) ^ (e_lo >>> 9 | e_hi << 23)) >>> 0; // ROTR 41/(swap + ROTR 9) |
|
s1_lo = ((e_hi << 18 | e_lo >>> 14) ^ (e_hi << 14 | e_lo >>> 18) ^ (e_lo << 23 | e_hi >>> 9)) >>> 0; // ROTR 41/(swap + ROTR 9) |
|
// Ch(e, f, g) (optimized the same way as SHA-1) |
|
ch_hi = (g_hi ^ e_hi & (f_hi ^ g_hi)) >>> 0; |
|
ch_lo = (g_lo ^ e_lo & (f_lo ^ g_lo)) >>> 0; |
|
// Sum0(a) = ROTR 28(a) ^ ROTR 34(a) ^ ROTR 39(a) |
|
s0_hi = ((a_hi >>> 28 | a_lo << 4) ^ (a_lo >>> 2 | a_hi << 30) ^ (a_lo >>> 7 | a_hi << 25)) >>> 0; // ROTR 39/(swap + ROTR 7) |
|
s0_lo = ((a_hi << 4 | a_lo >>> 28) ^ (a_lo << 30 | a_hi >>> 2) ^ (a_lo << 25 | a_hi >>> 7)) >>> 0; // ROTR 39/(swap + ROTR 7) |
|
// Maj(a, b, c) (optimized the same way as SHA-1) |
|
maj_hi = (a_hi & b_hi | c_hi & (a_hi ^ b_hi)) >>> 0; |
|
maj_lo = (a_lo & b_lo | c_lo & (a_lo ^ b_lo)) >>> 0; |
|
// main algorithm |
|
// t1 = (h + s1 + ch + _k[i] + _w[i]) modulo 2^64 (carry lo overflow) |
|
lo = h_lo + s1_lo + ch_lo + $33c8fc1a702f0359$var$_k[i][1] + w[i][1]; |
|
t1_hi = h_hi + s1_hi + ch_hi + $33c8fc1a702f0359$var$_k[i][0] + w[i][0] + (lo / 4294967296 >>> 0) >>> 0; |
|
t1_lo = lo >>> 0; |
|
// t2 = s0 + maj modulo 2^64 (carry lo overflow) |
|
lo = s0_lo + maj_lo; |
|
t2_hi = s0_hi + maj_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
t2_lo = lo >>> 0; |
|
h_hi = g_hi; |
|
h_lo = g_lo; |
|
g_hi = f_hi; |
|
g_lo = f_lo; |
|
f_hi = e_hi; |
|
f_lo = e_lo; |
|
// e = (d + t1) modulo 2^64 (carry lo overflow) |
|
lo = d_lo + t1_lo; |
|
e_hi = d_hi + t1_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
e_lo = lo >>> 0; |
|
d_hi = c_hi; |
|
d_lo = c_lo; |
|
c_hi = b_hi; |
|
c_lo = b_lo; |
|
b_hi = a_hi; |
|
b_lo = a_lo; |
|
// a = (t1 + t2) modulo 2^64 (carry lo overflow) |
|
lo = t1_lo + t2_lo; |
|
a_hi = t1_hi + t2_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
a_lo = lo >>> 0; |
|
} |
|
// update hash state (additional modulo 2^64) |
|
lo = s[0][1] + a_lo; |
|
s[0][0] = s[0][0] + a_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
s[0][1] = lo >>> 0; |
|
lo = s[1][1] + b_lo; |
|
s[1][0] = s[1][0] + b_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
s[1][1] = lo >>> 0; |
|
lo = s[2][1] + c_lo; |
|
s[2][0] = s[2][0] + c_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
s[2][1] = lo >>> 0; |
|
lo = s[3][1] + d_lo; |
|
s[3][0] = s[3][0] + d_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
s[3][1] = lo >>> 0; |
|
lo = s[4][1] + e_lo; |
|
s[4][0] = s[4][0] + e_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
s[4][1] = lo >>> 0; |
|
lo = s[5][1] + f_lo; |
|
s[5][0] = s[5][0] + f_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
s[5][1] = lo >>> 0; |
|
lo = s[6][1] + g_lo; |
|
s[6][0] = s[6][0] + g_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
s[6][1] = lo >>> 0; |
|
lo = s[7][1] + h_lo; |
|
s[7][0] = s[7][0] + h_hi + (lo / 4294967296 >>> 0) >>> 0; |
|
s[7][1] = lo >>> 0; |
|
len -= 128; |
|
} |
|
} |
|
|
|
|
|
|
|
var $4540a91b15e72417$export$fed72f95cdc10258; |
|
var $4540a91b15e72417$export$16f1063872153885; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
var $4540a91b15e72417$var$asn1 = $iGlOy.asn1; |
|
$4540a91b15e72417$export$fed72f95cdc10258 = { |
|
// PrivateKeyInfo |
|
name: 'PrivateKeyInfo', |
|
tagClass: $4540a91b15e72417$var$asn1.Class.UNIVERSAL, |
|
type: $4540a91b15e72417$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
// Version (INTEGER) |
|
name: 'PrivateKeyInfo.version', |
|
tagClass: $4540a91b15e72417$var$asn1.Class.UNIVERSAL, |
|
type: $4540a91b15e72417$var$asn1.Type.INTEGER, |
|
constructed: false, |
|
capture: 'privateKeyVersion' |
|
}, |
|
{ |
|
// privateKeyAlgorithm |
|
name: 'PrivateKeyInfo.privateKeyAlgorithm', |
|
tagClass: $4540a91b15e72417$var$asn1.Class.UNIVERSAL, |
|
type: $4540a91b15e72417$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'AlgorithmIdentifier.algorithm', |
|
tagClass: $4540a91b15e72417$var$asn1.Class.UNIVERSAL, |
|
type: $4540a91b15e72417$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'privateKeyOid' |
|
} |
|
] |
|
}, |
|
{ |
|
// PrivateKey |
|
name: 'PrivateKeyInfo', |
|
tagClass: $4540a91b15e72417$var$asn1.Class.UNIVERSAL, |
|
type: $4540a91b15e72417$var$asn1.Type.OCTETSTRING, |
|
constructed: false, |
|
capture: 'privateKey' |
|
} |
|
] |
|
}; |
|
$4540a91b15e72417$export$16f1063872153885 = { |
|
name: 'SubjectPublicKeyInfo', |
|
tagClass: $4540a91b15e72417$var$asn1.Class.UNIVERSAL, |
|
type: $4540a91b15e72417$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
captureAsn1: 'subjectPublicKeyInfo', |
|
value: [ |
|
{ |
|
name: 'SubjectPublicKeyInfo.AlgorithmIdentifier', |
|
tagClass: $4540a91b15e72417$var$asn1.Class.UNIVERSAL, |
|
type: $4540a91b15e72417$var$asn1.Type.SEQUENCE, |
|
constructed: true, |
|
value: [ |
|
{ |
|
name: 'AlgorithmIdentifier.algorithm', |
|
tagClass: $4540a91b15e72417$var$asn1.Class.UNIVERSAL, |
|
type: $4540a91b15e72417$var$asn1.Type.OID, |
|
constructed: false, |
|
capture: 'publicKeyOid' |
|
} |
|
] |
|
}, |
|
// capture group for ed25519PublicKey |
|
{ |
|
tagClass: $4540a91b15e72417$var$asn1.Class.UNIVERSAL, |
|
type: $4540a91b15e72417$var$asn1.Type.BITSTRING, |
|
constructed: false, |
|
composed: true, |
|
captureBitStringValue: 'ed25519PublicKey' |
|
} |
|
] |
|
}; |
|
|
|
|
|
var $96695cc1b97188e1$var$publicKeyValidator = $4540a91b15e72417$export$16f1063872153885; |
|
var $96695cc1b97188e1$var$privateKeyValidator = $4540a91b15e72417$export$fed72f95cdc10258; |
|
if (typeof $96695cc1b97188e1$var$BigInteger === 'undefined') var $96695cc1b97188e1$var$BigInteger = $iGlOy.jsbn.BigInteger; |
|
var $96695cc1b97188e1$var$ByteBuffer = $iGlOy.util.ByteBuffer; |
|
var $96695cc1b97188e1$var$NativeBuffer = typeof Buffer === 'undefined' ? Uint8Array : Buffer; |
|
/* |
|
* Ed25519 algorithms, see RFC 8032: |
|
* https://tools.ietf.org/html/rfc8032 |
|
*/ $iGlOy.pki = $iGlOy.pki || { |
|
}; |
|
$96695cc1b97188e1$exports = $iGlOy.pki.ed25519 = $iGlOy.ed25519 = $iGlOy.ed25519 || { |
|
}; |
|
var $96695cc1b97188e1$var$ed25519 = $iGlOy.ed25519; |
|
$96695cc1b97188e1$var$ed25519.constants = { |
|
}; |
|
$96695cc1b97188e1$var$ed25519.constants.PUBLIC_KEY_BYTE_LENGTH = 32; |
|
$96695cc1b97188e1$var$ed25519.constants.PRIVATE_KEY_BYTE_LENGTH = 64; |
|
$96695cc1b97188e1$var$ed25519.constants.SEED_BYTE_LENGTH = 32; |
|
$96695cc1b97188e1$var$ed25519.constants.SIGN_BYTE_LENGTH = 64; |
|
$96695cc1b97188e1$var$ed25519.constants.HASH_BYTE_LENGTH = 64; |
|
$96695cc1b97188e1$var$ed25519.generateKeyPair = function(options) { |
|
options = options || { |
|
}; |
|
var seed = options.seed; |
|
if (seed === undefined) // generate seed |
|
seed = $iGlOy.random.getBytesSync($96695cc1b97188e1$var$ed25519.constants.SEED_BYTE_LENGTH); |
|
else if (typeof seed === 'string') { |
|
if (seed.length !== $96695cc1b97188e1$var$ed25519.constants.SEED_BYTE_LENGTH) throw new TypeError('"seed" must be ' + $96695cc1b97188e1$var$ed25519.constants.SEED_BYTE_LENGTH + ' bytes in length.'); |
|
} else if (!(seed instanceof Uint8Array)) throw new TypeError('"seed" must be a node.js Buffer, Uint8Array, or a binary string.'); |
|
seed = $96695cc1b97188e1$var$messageToNativeBuffer({ |
|
message: seed, |
|
encoding: 'binary' |
|
}); |
|
var pk = new $96695cc1b97188e1$var$NativeBuffer($96695cc1b97188e1$var$ed25519.constants.PUBLIC_KEY_BYTE_LENGTH); |
|
var sk = new $96695cc1b97188e1$var$NativeBuffer($96695cc1b97188e1$var$ed25519.constants.PRIVATE_KEY_BYTE_LENGTH); |
|
for(var i = 0; i < 32; ++i)sk[i] = seed[i]; |
|
$96695cc1b97188e1$var$crypto_sign_keypair(pk, sk); |
|
return { |
|
publicKey: pk, |
|
privateKey: sk |
|
}; |
|
}; |
|
/** |
|
* Converts a private key from a RFC8410 ASN.1 encoding. |
|
* |
|
* @param obj - The asn1 representation of a private key. |
|
* |
|
* @returns {Object} keyInfo - The key information. |
|
* @returns {Buffer|Uint8Array} keyInfo.privateKeyBytes - 32 private key bytes. |
|
*/ $96695cc1b97188e1$var$ed25519.privateKeyFromAsn1 = function(obj) { |
|
var capture = { |
|
}; |
|
var errors = []; |
|
var valid = $iGlOy.asn1.validate(obj, $96695cc1b97188e1$var$privateKeyValidator, capture, errors); |
|
if (!valid) { |
|
var error = new Error('Invalid Key.'); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
var oid = $iGlOy.asn1.derToOid(capture.privateKeyOid); |
|
var ed25519Oid = $iGlOy.oids.EdDSA25519; |
|
if (oid !== ed25519Oid) throw new Error('Invalid OID "' + oid + '"; OID must be "' + ed25519Oid + '".'); |
|
var privateKey = capture.privateKey; |
|
// manually extract the private key bytes from nested octet string, see FIXME: |
|
// https://github.com/digitalbazaar/forge/blob/master/lib/asn1.js#L542 |
|
var privateKeyBytes = $96695cc1b97188e1$var$messageToNativeBuffer({ |
|
message: $iGlOy.asn1.fromDer(privateKey).value, |
|
encoding: 'binary' |
|
}); |
|
// TODO: RFC8410 specifies a format for encoding the public key bytes along |
|
// with the private key bytes. `publicKeyBytes` can be returned in the |
|
// future. https://tools.ietf.org/html/rfc8410#section-10.3 |
|
return { |
|
privateKeyBytes: privateKeyBytes |
|
}; |
|
}; |
|
/** |
|
* Converts a public key from a RFC8410 ASN.1 encoding. |
|
* |
|
* @param obj - The asn1 representation of a public key. |
|
* |
|
* @return {Buffer|Uint8Array} - 32 public key bytes. |
|
*/ $96695cc1b97188e1$var$ed25519.publicKeyFromAsn1 = function(obj) { |
|
// get SubjectPublicKeyInfo |
|
var capture = { |
|
}; |
|
var errors = []; |
|
var valid = $iGlOy.asn1.validate(obj, $96695cc1b97188e1$var$publicKeyValidator, capture, errors); |
|
if (!valid) { |
|
var error = new Error('Invalid Key.'); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
var oid = $iGlOy.asn1.derToOid(capture.publicKeyOid); |
|
var ed25519Oid = $iGlOy.oids.EdDSA25519; |
|
if (oid !== ed25519Oid) throw new Error('Invalid OID "' + oid + '"; OID must be "' + ed25519Oid + '".'); |
|
var publicKeyBytes = capture.ed25519PublicKey; |
|
if (publicKeyBytes.length !== $96695cc1b97188e1$var$ed25519.constants.PUBLIC_KEY_BYTE_LENGTH) throw new Error('Key length is invalid.'); |
|
return $96695cc1b97188e1$var$messageToNativeBuffer({ |
|
message: publicKeyBytes, |
|
encoding: 'binary' |
|
}); |
|
}; |
|
$96695cc1b97188e1$var$ed25519.publicKeyFromPrivateKey = function(options) { |
|
options = options || { |
|
}; |
|
var privateKey = $96695cc1b97188e1$var$messageToNativeBuffer({ |
|
message: options.privateKey, |
|
encoding: 'binary' |
|
}); |
|
if (privateKey.length !== $96695cc1b97188e1$var$ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) throw new TypeError('"options.privateKey" must have a byte length of ' + $96695cc1b97188e1$var$ed25519.constants.PRIVATE_KEY_BYTE_LENGTH); |
|
var pk = new $96695cc1b97188e1$var$NativeBuffer($96695cc1b97188e1$var$ed25519.constants.PUBLIC_KEY_BYTE_LENGTH); |
|
for(var i = 0; i < pk.length; ++i)pk[i] = privateKey[32 + i]; |
|
return pk; |
|
}; |
|
$96695cc1b97188e1$var$ed25519.sign = function(options) { |
|
options = options || { |
|
}; |
|
var msg = $96695cc1b97188e1$var$messageToNativeBuffer(options); |
|
var privateKey = $96695cc1b97188e1$var$messageToNativeBuffer({ |
|
message: options.privateKey, |
|
encoding: 'binary' |
|
}); |
|
if (privateKey.length === $96695cc1b97188e1$var$ed25519.constants.SEED_BYTE_LENGTH) { |
|
var keyPair = $96695cc1b97188e1$var$ed25519.generateKeyPair({ |
|
seed: privateKey |
|
}); |
|
privateKey = keyPair.privateKey; |
|
} else if (privateKey.length !== $96695cc1b97188e1$var$ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) throw new TypeError('"options.privateKey" must have a byte length of ' + $96695cc1b97188e1$var$ed25519.constants.SEED_BYTE_LENGTH + ' or ' + $96695cc1b97188e1$var$ed25519.constants.PRIVATE_KEY_BYTE_LENGTH); |
|
var signedMsg = new $96695cc1b97188e1$var$NativeBuffer($96695cc1b97188e1$var$ed25519.constants.SIGN_BYTE_LENGTH + msg.length); |
|
$96695cc1b97188e1$var$crypto_sign(signedMsg, msg, msg.length, privateKey); |
|
var sig = new $96695cc1b97188e1$var$NativeBuffer($96695cc1b97188e1$var$ed25519.constants.SIGN_BYTE_LENGTH); |
|
for(var i = 0; i < sig.length; ++i)sig[i] = signedMsg[i]; |
|
return sig; |
|
}; |
|
$96695cc1b97188e1$var$ed25519.verify = function(options) { |
|
options = options || { |
|
}; |
|
var msg = $96695cc1b97188e1$var$messageToNativeBuffer(options); |
|
if (options.signature === undefined) throw new TypeError("\"options.signature\" must be a node.js Buffer, a Uint8Array, a forge ByteBuffer, or a binary string."); |
|
var sig = $96695cc1b97188e1$var$messageToNativeBuffer({ |
|
message: options.signature, |
|
encoding: 'binary' |
|
}); |
|
if (sig.length !== $96695cc1b97188e1$var$ed25519.constants.SIGN_BYTE_LENGTH) throw new TypeError('"options.signature" must have a byte length of ' + $96695cc1b97188e1$var$ed25519.constants.SIGN_BYTE_LENGTH); |
|
var publicKey = $96695cc1b97188e1$var$messageToNativeBuffer({ |
|
message: options.publicKey, |
|
encoding: 'binary' |
|
}); |
|
if (publicKey.length !== $96695cc1b97188e1$var$ed25519.constants.PUBLIC_KEY_BYTE_LENGTH) throw new TypeError('"options.publicKey" must have a byte length of ' + $96695cc1b97188e1$var$ed25519.constants.PUBLIC_KEY_BYTE_LENGTH); |
|
var sm = new $96695cc1b97188e1$var$NativeBuffer($96695cc1b97188e1$var$ed25519.constants.SIGN_BYTE_LENGTH + msg.length); |
|
var m = new $96695cc1b97188e1$var$NativeBuffer($96695cc1b97188e1$var$ed25519.constants.SIGN_BYTE_LENGTH + msg.length); |
|
var i; |
|
for(i = 0; i < $96695cc1b97188e1$var$ed25519.constants.SIGN_BYTE_LENGTH; ++i)sm[i] = sig[i]; |
|
for(i = 0; i < msg.length; ++i)sm[i + $96695cc1b97188e1$var$ed25519.constants.SIGN_BYTE_LENGTH] = msg[i]; |
|
return $96695cc1b97188e1$var$crypto_sign_open(m, sm, sm.length, publicKey) >= 0; |
|
}; |
|
function $96695cc1b97188e1$var$messageToNativeBuffer(options) { |
|
var message = options.message; |
|
if (message instanceof Uint8Array || message instanceof $96695cc1b97188e1$var$NativeBuffer) return message; |
|
var encoding = options.encoding; |
|
if (message === undefined) { |
|
if (options.md) { |
|
// TODO: more rigorous validation that `md` is a MessageDigest |
|
message = options.md.digest().getBytes(); |
|
encoding = 'binary'; |
|
} else throw new TypeError('"options.message" or "options.md" not specified.'); |
|
} |
|
if (typeof message === 'string' && !encoding) throw new TypeError('"options.encoding" must be "binary" or "utf8".'); |
|
if (typeof message === 'string') { |
|
if (typeof Buffer !== 'undefined') return Buffer.from(message, encoding); |
|
message = new $96695cc1b97188e1$var$ByteBuffer(message, encoding); |
|
} else if (!(message instanceof $96695cc1b97188e1$var$ByteBuffer)) throw new TypeError("\"options.message\" must be a node.js Buffer, a Uint8Array, a forge ByteBuffer, or a string with \"options.encoding\" specifying its encoding."); |
|
// convert to native buffer |
|
var buffer = new $96695cc1b97188e1$var$NativeBuffer(message.length()); |
|
for(var i = 0; i < buffer.length; ++i)buffer[i] = message.at(i); |
|
return buffer; |
|
} |
|
var $96695cc1b97188e1$var$gf0 = $96695cc1b97188e1$var$gf(); |
|
var $96695cc1b97188e1$var$gf1 = $96695cc1b97188e1$var$gf([ |
|
1 |
|
]); |
|
var $96695cc1b97188e1$var$D = $96695cc1b97188e1$var$gf([ |
|
30883, |
|
4953, |
|
19914, |
|
30187, |
|
55467, |
|
16705, |
|
2637, |
|
112, |
|
59544, |
|
30585, |
|
16505, |
|
36039, |
|
65139, |
|
11119, |
|
27886, |
|
20995 |
|
]); |
|
var $96695cc1b97188e1$var$D2 = $96695cc1b97188e1$var$gf([ |
|
61785, |
|
9906, |
|
39828, |
|
60374, |
|
45398, |
|
33411, |
|
5274, |
|
224, |
|
53552, |
|
61171, |
|
33010, |
|
6542, |
|
64743, |
|
22239, |
|
55772, |
|
9222 |
|
]); |
|
var $96695cc1b97188e1$var$X = $96695cc1b97188e1$var$gf([ |
|
54554, |
|
36645, |
|
11616, |
|
51542, |
|
42930, |
|
38181, |
|
51040, |
|
26924, |
|
56412, |
|
64982, |
|
57905, |
|
49316, |
|
21502, |
|
52590, |
|
14035, |
|
8553 |
|
]); |
|
var $96695cc1b97188e1$var$Y = $96695cc1b97188e1$var$gf([ |
|
26200, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214, |
|
26214 |
|
]); |
|
var $96695cc1b97188e1$var$L = new Float64Array([ |
|
237, |
|
211, |
|
245, |
|
92, |
|
26, |
|
99, |
|
18, |
|
88, |
|
214, |
|
156, |
|
247, |
|
162, |
|
222, |
|
249, |
|
222, |
|
20, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
0, |
|
16 |
|
]); |
|
var $96695cc1b97188e1$var$I = $96695cc1b97188e1$var$gf([ |
|
41136, |
|
18958, |
|
6951, |
|
50414, |
|
58488, |
|
44335, |
|
6150, |
|
12099, |
|
55207, |
|
15867, |
|
153, |
|
11085, |
|
57099, |
|
20417, |
|
9344, |
|
11139 |
|
]); |
|
// TODO: update forge buffer implementation to use `Buffer` or `Uint8Array`, |
|
// whichever is available, to improve performance |
|
function $96695cc1b97188e1$var$sha512(msg, msgLen) { |
|
// Note: `out` and `msg` are NativeBuffer |
|
var md = $iGlOy.md.sha512.create(); |
|
var buffer = new $96695cc1b97188e1$var$ByteBuffer(msg); |
|
md.update(buffer.getBytes(msgLen), 'binary'); |
|
var hash = md.digest().getBytes(); |
|
if (typeof Buffer !== 'undefined') return Buffer.from(hash, 'binary'); |
|
var out = new $96695cc1b97188e1$var$NativeBuffer($96695cc1b97188e1$var$ed25519.constants.HASH_BYTE_LENGTH); |
|
for(var i = 0; i < 64; ++i)out[i] = hash.charCodeAt(i); |
|
return out; |
|
} |
|
function $96695cc1b97188e1$var$crypto_sign_keypair(pk, sk) { |
|
var p = [ |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf() |
|
]; |
|
var i; |
|
var d = $96695cc1b97188e1$var$sha512(sk, 32); |
|
d[0] &= 248; |
|
d[31] &= 127; |
|
d[31] |= 64; |
|
$96695cc1b97188e1$var$scalarbase(p, d); |
|
$96695cc1b97188e1$var$pack(pk, p); |
|
for(i = 0; i < 32; ++i)sk[i + 32] = pk[i]; |
|
return 0; |
|
} |
|
// Note: difference from C - smlen returned, not passed as argument. |
|
function $96695cc1b97188e1$var$crypto_sign(sm, m, n, sk) { |
|
var i, j, x = new Float64Array(64); |
|
var p = [ |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf() |
|
]; |
|
var d = $96695cc1b97188e1$var$sha512(sk, 32); |
|
d[0] &= 248; |
|
d[31] &= 127; |
|
d[31] |= 64; |
|
var smlen = n + 64; |
|
for(i = 0; i < n; ++i)sm[64 + i] = m[i]; |
|
for(i = 0; i < 32; ++i)sm[32 + i] = d[32 + i]; |
|
var r = $96695cc1b97188e1$var$sha512(sm.subarray(32), n + 32); |
|
$96695cc1b97188e1$var$reduce(r); |
|
$96695cc1b97188e1$var$scalarbase(p, r); |
|
$96695cc1b97188e1$var$pack(sm, p); |
|
for(i = 32; i < 64; ++i)sm[i] = sk[i]; |
|
var h = $96695cc1b97188e1$var$sha512(sm, n + 64); |
|
$96695cc1b97188e1$var$reduce(h); |
|
for(i = 32; i < 64; ++i)x[i] = 0; |
|
for(i = 0; i < 32; ++i)x[i] = r[i]; |
|
for(i = 0; i < 32; ++i)for(j = 0; j < 32; j++)x[i + j] += h[i] * d[j]; |
|
$96695cc1b97188e1$var$modL(sm.subarray(32), x); |
|
return smlen; |
|
} |
|
function $96695cc1b97188e1$var$crypto_sign_open(m, sm, n, pk) { |
|
var i, mlen; |
|
var t = new $96695cc1b97188e1$var$NativeBuffer(32); |
|
var p = [ |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf() |
|
], q = [ |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf() |
|
]; |
|
mlen = -1; |
|
if (n < 64) return -1; |
|
if ($96695cc1b97188e1$var$unpackneg(q, pk)) return -1; |
|
for(i = 0; i < n; ++i)m[i] = sm[i]; |
|
for(i = 0; i < 32; ++i)m[i + 32] = pk[i]; |
|
var h = $96695cc1b97188e1$var$sha512(m, n); |
|
$96695cc1b97188e1$var$reduce(h); |
|
$96695cc1b97188e1$var$scalarmult(p, q, h); |
|
$96695cc1b97188e1$var$scalarbase(q, sm.subarray(32)); |
|
$96695cc1b97188e1$var$add(p, q); |
|
$96695cc1b97188e1$var$pack(t, p); |
|
n -= 64; |
|
if ($96695cc1b97188e1$var$crypto_verify_32(sm, 0, t, 0)) { |
|
for(i = 0; i < n; ++i)m[i] = 0; |
|
return -1; |
|
} |
|
for(i = 0; i < n; ++i)m[i] = sm[i + 64]; |
|
mlen = n; |
|
return mlen; |
|
} |
|
function $96695cc1b97188e1$var$modL(r, x) { |
|
var carry, i, j, k; |
|
for(i = 63; i >= 32; --i){ |
|
carry = 0; |
|
for(j = i - 32, k = i - 12; j < k; ++j){ |
|
x[j] += carry - 16 * x[i] * $96695cc1b97188e1$var$L[j - (i - 32)]; |
|
carry = x[j] + 128 >> 8; |
|
x[j] -= carry * 256; |
|
} |
|
x[j] += carry; |
|
x[i] = 0; |
|
} |
|
carry = 0; |
|
for(j = 0; j < 32; ++j){ |
|
x[j] += carry - (x[31] >> 4) * $96695cc1b97188e1$var$L[j]; |
|
carry = x[j] >> 8; |
|
x[j] &= 255; |
|
} |
|
for(j = 0; j < 32; ++j)x[j] -= carry * $96695cc1b97188e1$var$L[j]; |
|
for(i = 0; i < 32; ++i){ |
|
x[i + 1] += x[i] >> 8; |
|
r[i] = x[i] & 255; |
|
} |
|
} |
|
function $96695cc1b97188e1$var$reduce(r) { |
|
var x = new Float64Array(64); |
|
for(var i = 0; i < 64; ++i){ |
|
x[i] = r[i]; |
|
r[i] = 0; |
|
} |
|
$96695cc1b97188e1$var$modL(r, x); |
|
} |
|
function $96695cc1b97188e1$var$add(p, q) { |
|
var a = $96695cc1b97188e1$var$gf(), b = $96695cc1b97188e1$var$gf(), c = $96695cc1b97188e1$var$gf(), d = $96695cc1b97188e1$var$gf(), e = $96695cc1b97188e1$var$gf(), f = $96695cc1b97188e1$var$gf(), g = $96695cc1b97188e1$var$gf(), h = $96695cc1b97188e1$var$gf(), t = $96695cc1b97188e1$var$gf(); |
|
$96695cc1b97188e1$var$Z(a, p[1], p[0]); |
|
$96695cc1b97188e1$var$Z(t, q[1], q[0]); |
|
$96695cc1b97188e1$var$M(a, a, t); |
|
$96695cc1b97188e1$var$A(b, p[0], p[1]); |
|
$96695cc1b97188e1$var$A(t, q[0], q[1]); |
|
$96695cc1b97188e1$var$M(b, b, t); |
|
$96695cc1b97188e1$var$M(c, p[3], q[3]); |
|
$96695cc1b97188e1$var$M(c, c, $96695cc1b97188e1$var$D2); |
|
$96695cc1b97188e1$var$M(d, p[2], q[2]); |
|
$96695cc1b97188e1$var$A(d, d, d); |
|
$96695cc1b97188e1$var$Z(e, b, a); |
|
$96695cc1b97188e1$var$Z(f, d, c); |
|
$96695cc1b97188e1$var$A(g, d, c); |
|
$96695cc1b97188e1$var$A(h, b, a); |
|
$96695cc1b97188e1$var$M(p[0], e, f); |
|
$96695cc1b97188e1$var$M(p[1], h, g); |
|
$96695cc1b97188e1$var$M(p[2], g, f); |
|
$96695cc1b97188e1$var$M(p[3], e, h); |
|
} |
|
function $96695cc1b97188e1$var$cswap(p, q, b) { |
|
for(var i = 0; i < 4; ++i)$96695cc1b97188e1$var$sel25519(p[i], q[i], b); |
|
} |
|
function $96695cc1b97188e1$var$pack(r, p) { |
|
var tx = $96695cc1b97188e1$var$gf(), ty = $96695cc1b97188e1$var$gf(), zi = $96695cc1b97188e1$var$gf(); |
|
$96695cc1b97188e1$var$inv25519(zi, p[2]); |
|
$96695cc1b97188e1$var$M(tx, p[0], zi); |
|
$96695cc1b97188e1$var$M(ty, p[1], zi); |
|
$96695cc1b97188e1$var$pack25519(r, ty); |
|
r[31] ^= $96695cc1b97188e1$var$par25519(tx) << 7; |
|
} |
|
function $96695cc1b97188e1$var$pack25519(o, n) { |
|
var i, j, b; |
|
var m = $96695cc1b97188e1$var$gf(), t = $96695cc1b97188e1$var$gf(); |
|
for(i = 0; i < 16; ++i)t[i] = n[i]; |
|
$96695cc1b97188e1$var$car25519(t); |
|
$96695cc1b97188e1$var$car25519(t); |
|
$96695cc1b97188e1$var$car25519(t); |
|
for(j = 0; j < 2; ++j){ |
|
m[0] = t[0] - 65517; |
|
for(i = 1; i < 15; ++i){ |
|
m[i] = t[i] - 65535 - (m[i - 1] >> 16 & 1); |
|
m[i - 1] &= 65535; |
|
} |
|
m[15] = t[15] - 32767 - (m[14] >> 16 & 1); |
|
b = m[15] >> 16 & 1; |
|
m[14] &= 65535; |
|
$96695cc1b97188e1$var$sel25519(t, m, 1 - b); |
|
} |
|
for(i = 0; i < 16; i++){ |
|
o[2 * i] = t[i] & 255; |
|
o[2 * i + 1] = t[i] >> 8; |
|
} |
|
} |
|
function $96695cc1b97188e1$var$unpackneg(r, p) { |
|
var t = $96695cc1b97188e1$var$gf(), chk = $96695cc1b97188e1$var$gf(), num = $96695cc1b97188e1$var$gf(), den = $96695cc1b97188e1$var$gf(), den2 = $96695cc1b97188e1$var$gf(), den4 = $96695cc1b97188e1$var$gf(), den6 = $96695cc1b97188e1$var$gf(); |
|
$96695cc1b97188e1$var$set25519(r[2], $96695cc1b97188e1$var$gf1); |
|
$96695cc1b97188e1$var$unpack25519(r[1], p); |
|
$96695cc1b97188e1$var$S(num, r[1]); |
|
$96695cc1b97188e1$var$M(den, num, $96695cc1b97188e1$var$D); |
|
$96695cc1b97188e1$var$Z(num, num, r[2]); |
|
$96695cc1b97188e1$var$A(den, r[2], den); |
|
$96695cc1b97188e1$var$S(den2, den); |
|
$96695cc1b97188e1$var$S(den4, den2); |
|
$96695cc1b97188e1$var$M(den6, den4, den2); |
|
$96695cc1b97188e1$var$M(t, den6, num); |
|
$96695cc1b97188e1$var$M(t, t, den); |
|
$96695cc1b97188e1$var$pow2523(t, t); |
|
$96695cc1b97188e1$var$M(t, t, num); |
|
$96695cc1b97188e1$var$M(t, t, den); |
|
$96695cc1b97188e1$var$M(t, t, den); |
|
$96695cc1b97188e1$var$M(r[0], t, den); |
|
$96695cc1b97188e1$var$S(chk, r[0]); |
|
$96695cc1b97188e1$var$M(chk, chk, den); |
|
if ($96695cc1b97188e1$var$neq25519(chk, num)) $96695cc1b97188e1$var$M(r[0], r[0], $96695cc1b97188e1$var$I); |
|
$96695cc1b97188e1$var$S(chk, r[0]); |
|
$96695cc1b97188e1$var$M(chk, chk, den); |
|
if ($96695cc1b97188e1$var$neq25519(chk, num)) return -1; |
|
if ($96695cc1b97188e1$var$par25519(r[0]) === p[31] >> 7) $96695cc1b97188e1$var$Z(r[0], $96695cc1b97188e1$var$gf0, r[0]); |
|
$96695cc1b97188e1$var$M(r[3], r[0], r[1]); |
|
return 0; |
|
} |
|
function $96695cc1b97188e1$var$unpack25519(o, n) { |
|
var i; |
|
for(i = 0; i < 16; ++i)o[i] = n[2 * i] + (n[2 * i + 1] << 8); |
|
o[15] &= 32767; |
|
} |
|
function $96695cc1b97188e1$var$pow2523(o, i) { |
|
var c = $96695cc1b97188e1$var$gf(); |
|
var a; |
|
for(a = 0; a < 16; ++a)c[a] = i[a]; |
|
for(a = 250; a >= 0; --a){ |
|
$96695cc1b97188e1$var$S(c, c); |
|
if (a !== 1) $96695cc1b97188e1$var$M(c, c, i); |
|
} |
|
for(a = 0; a < 16; ++a)o[a] = c[a]; |
|
} |
|
function $96695cc1b97188e1$var$neq25519(a, b) { |
|
var c = new $96695cc1b97188e1$var$NativeBuffer(32); |
|
var d = new $96695cc1b97188e1$var$NativeBuffer(32); |
|
$96695cc1b97188e1$var$pack25519(c, a); |
|
$96695cc1b97188e1$var$pack25519(d, b); |
|
return $96695cc1b97188e1$var$crypto_verify_32(c, 0, d, 0); |
|
} |
|
function $96695cc1b97188e1$var$crypto_verify_32(x, xi, y, yi) { |
|
return $96695cc1b97188e1$var$vn(x, xi, y, yi, 32); |
|
} |
|
function $96695cc1b97188e1$var$vn(x, xi, y, yi, n) { |
|
var i, d = 0; |
|
for(i = 0; i < n; ++i)d |= x[xi + i] ^ y[yi + i]; |
|
return (1 & d - 1 >>> 8) - 1; |
|
} |
|
function $96695cc1b97188e1$var$par25519(a) { |
|
var d = new $96695cc1b97188e1$var$NativeBuffer(32); |
|
$96695cc1b97188e1$var$pack25519(d, a); |
|
return d[0] & 1; |
|
} |
|
function $96695cc1b97188e1$var$scalarmult(p, q, s) { |
|
var b, i; |
|
$96695cc1b97188e1$var$set25519(p[0], $96695cc1b97188e1$var$gf0); |
|
$96695cc1b97188e1$var$set25519(p[1], $96695cc1b97188e1$var$gf1); |
|
$96695cc1b97188e1$var$set25519(p[2], $96695cc1b97188e1$var$gf1); |
|
$96695cc1b97188e1$var$set25519(p[3], $96695cc1b97188e1$var$gf0); |
|
for(i = 255; i >= 0; --i){ |
|
b = s[i / 8 | 0] >> (i & 7) & 1; |
|
$96695cc1b97188e1$var$cswap(p, q, b); |
|
$96695cc1b97188e1$var$add(q, p); |
|
$96695cc1b97188e1$var$add(p, p); |
|
$96695cc1b97188e1$var$cswap(p, q, b); |
|
} |
|
} |
|
function $96695cc1b97188e1$var$scalarbase(p, s) { |
|
var q = [ |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf(), |
|
$96695cc1b97188e1$var$gf() |
|
]; |
|
$96695cc1b97188e1$var$set25519(q[0], $96695cc1b97188e1$var$X); |
|
$96695cc1b97188e1$var$set25519(q[1], $96695cc1b97188e1$var$Y); |
|
$96695cc1b97188e1$var$set25519(q[2], $96695cc1b97188e1$var$gf1); |
|
$96695cc1b97188e1$var$M(q[3], $96695cc1b97188e1$var$X, $96695cc1b97188e1$var$Y); |
|
$96695cc1b97188e1$var$scalarmult(p, q, s); |
|
} |
|
function $96695cc1b97188e1$var$set25519(r, a) { |
|
var i; |
|
for(i = 0; i < 16; i++)r[i] = a[i] | 0; |
|
} |
|
function $96695cc1b97188e1$var$inv25519(o, i) { |
|
var c = $96695cc1b97188e1$var$gf(); |
|
var a; |
|
for(a = 0; a < 16; ++a)c[a] = i[a]; |
|
for(a = 253; a >= 0; --a){ |
|
$96695cc1b97188e1$var$S(c, c); |
|
if (a !== 2 && a !== 4) $96695cc1b97188e1$var$M(c, c, i); |
|
} |
|
for(a = 0; a < 16; ++a)o[a] = c[a]; |
|
} |
|
function $96695cc1b97188e1$var$car25519(o) { |
|
var i, v, c = 1; |
|
for(i = 0; i < 16; ++i){ |
|
v = o[i] + c + 65535; |
|
c = Math.floor(v / 65536); |
|
o[i] = v - c * 65536; |
|
} |
|
o[0] += c - 1 + 37 * (c - 1); |
|
} |
|
function $96695cc1b97188e1$var$sel25519(p, q, b) { |
|
var t, c = ~(b - 1); |
|
for(var i = 0; i < 16; ++i){ |
|
t = c & (p[i] ^ q[i]); |
|
p[i] ^= t; |
|
q[i] ^= t; |
|
} |
|
} |
|
function $96695cc1b97188e1$var$gf(init) { |
|
var i, r = new Float64Array(16); |
|
if (init) for(i = 0; i < init.length; ++i)r[i] = init[i]; |
|
return r; |
|
} |
|
function $96695cc1b97188e1$var$A(o, a, b) { |
|
for(var i = 0; i < 16; ++i)o[i] = a[i] + b[i]; |
|
} |
|
function $96695cc1b97188e1$var$Z(o, a, b) { |
|
for(var i = 0; i < 16; ++i)o[i] = a[i] - b[i]; |
|
} |
|
function $96695cc1b97188e1$var$S(o, a) { |
|
$96695cc1b97188e1$var$M(o, a, a); |
|
} |
|
function $96695cc1b97188e1$var$M(o, a, b) { |
|
var v, c, t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5], b6 = b[6], b7 = b[7], b8 = b[8], b9 = b[9], b10 = b[10], b11 = b[11], b12 = b[12], b13 = b[13], b14 = b[14], b15 = b[15]; |
|
v = a[0]; |
|
t0 += v * b0; |
|
t1 += v * b1; |
|
t2 += v * b2; |
|
t3 += v * b3; |
|
t4 += v * b4; |
|
t5 += v * b5; |
|
t6 += v * b6; |
|
t7 += v * b7; |
|
t8 += v * b8; |
|
t9 += v * b9; |
|
t10 += v * b10; |
|
t11 += v * b11; |
|
t12 += v * b12; |
|
t13 += v * b13; |
|
t14 += v * b14; |
|
t15 += v * b15; |
|
v = a[1]; |
|
t1 += v * b0; |
|
t2 += v * b1; |
|
t3 += v * b2; |
|
t4 += v * b3; |
|
t5 += v * b4; |
|
t6 += v * b5; |
|
t7 += v * b6; |
|
t8 += v * b7; |
|
t9 += v * b8; |
|
t10 += v * b9; |
|
t11 += v * b10; |
|
t12 += v * b11; |
|
t13 += v * b12; |
|
t14 += v * b13; |
|
t15 += v * b14; |
|
t16 += v * b15; |
|
v = a[2]; |
|
t2 += v * b0; |
|
t3 += v * b1; |
|
t4 += v * b2; |
|
t5 += v * b3; |
|
t6 += v * b4; |
|
t7 += v * b5; |
|
t8 += v * b6; |
|
t9 += v * b7; |
|
t10 += v * b8; |
|
t11 += v * b9; |
|
t12 += v * b10; |
|
t13 += v * b11; |
|
t14 += v * b12; |
|
t15 += v * b13; |
|
t16 += v * b14; |
|
t17 += v * b15; |
|
v = a[3]; |
|
t3 += v * b0; |
|
t4 += v * b1; |
|
t5 += v * b2; |
|
t6 += v * b3; |
|
t7 += v * b4; |
|
t8 += v * b5; |
|
t9 += v * b6; |
|
t10 += v * b7; |
|
t11 += v * b8; |
|
t12 += v * b9; |
|
t13 += v * b10; |
|
t14 += v * b11; |
|
t15 += v * b12; |
|
t16 += v * b13; |
|
t17 += v * b14; |
|
t18 += v * b15; |
|
v = a[4]; |
|
t4 += v * b0; |
|
t5 += v * b1; |
|
t6 += v * b2; |
|
t7 += v * b3; |
|
t8 += v * b4; |
|
t9 += v * b5; |
|
t10 += v * b6; |
|
t11 += v * b7; |
|
t12 += v * b8; |
|
t13 += v * b9; |
|
t14 += v * b10; |
|
t15 += v * b11; |
|
t16 += v * b12; |
|
t17 += v * b13; |
|
t18 += v * b14; |
|
t19 += v * b15; |
|
v = a[5]; |
|
t5 += v * b0; |
|
t6 += v * b1; |
|
t7 += v * b2; |
|
t8 += v * b3; |
|
t9 += v * b4; |
|
t10 += v * b5; |
|
t11 += v * b6; |
|
t12 += v * b7; |
|
t13 += v * b8; |
|
t14 += v * b9; |
|
t15 += v * b10; |
|
t16 += v * b11; |
|
t17 += v * b12; |
|
t18 += v * b13; |
|
t19 += v * b14; |
|
t20 += v * b15; |
|
v = a[6]; |
|
t6 += v * b0; |
|
t7 += v * b1; |
|
t8 += v * b2; |
|
t9 += v * b3; |
|
t10 += v * b4; |
|
t11 += v * b5; |
|
t12 += v * b6; |
|
t13 += v * b7; |
|
t14 += v * b8; |
|
t15 += v * b9; |
|
t16 += v * b10; |
|
t17 += v * b11; |
|
t18 += v * b12; |
|
t19 += v * b13; |
|
t20 += v * b14; |
|
t21 += v * b15; |
|
v = a[7]; |
|
t7 += v * b0; |
|
t8 += v * b1; |
|
t9 += v * b2; |
|
t10 += v * b3; |
|
t11 += v * b4; |
|
t12 += v * b5; |
|
t13 += v * b6; |
|
t14 += v * b7; |
|
t15 += v * b8; |
|
t16 += v * b9; |
|
t17 += v * b10; |
|
t18 += v * b11; |
|
t19 += v * b12; |
|
t20 += v * b13; |
|
t21 += v * b14; |
|
t22 += v * b15; |
|
v = a[8]; |
|
t8 += v * b0; |
|
t9 += v * b1; |
|
t10 += v * b2; |
|
t11 += v * b3; |
|
t12 += v * b4; |
|
t13 += v * b5; |
|
t14 += v * b6; |
|
t15 += v * b7; |
|
t16 += v * b8; |
|
t17 += v * b9; |
|
t18 += v * b10; |
|
t19 += v * b11; |
|
t20 += v * b12; |
|
t21 += v * b13; |
|
t22 += v * b14; |
|
t23 += v * b15; |
|
v = a[9]; |
|
t9 += v * b0; |
|
t10 += v * b1; |
|
t11 += v * b2; |
|
t12 += v * b3; |
|
t13 += v * b4; |
|
t14 += v * b5; |
|
t15 += v * b6; |
|
t16 += v * b7; |
|
t17 += v * b8; |
|
t18 += v * b9; |
|
t19 += v * b10; |
|
t20 += v * b11; |
|
t21 += v * b12; |
|
t22 += v * b13; |
|
t23 += v * b14; |
|
t24 += v * b15; |
|
v = a[10]; |
|
t10 += v * b0; |
|
t11 += v * b1; |
|
t12 += v * b2; |
|
t13 += v * b3; |
|
t14 += v * b4; |
|
t15 += v * b5; |
|
t16 += v * b6; |
|
t17 += v * b7; |
|
t18 += v * b8; |
|
t19 += v * b9; |
|
t20 += v * b10; |
|
t21 += v * b11; |
|
t22 += v * b12; |
|
t23 += v * b13; |
|
t24 += v * b14; |
|
t25 += v * b15; |
|
v = a[11]; |
|
t11 += v * b0; |
|
t12 += v * b1; |
|
t13 += v * b2; |
|
t14 += v * b3; |
|
t15 += v * b4; |
|
t16 += v * b5; |
|
t17 += v * b6; |
|
t18 += v * b7; |
|
t19 += v * b8; |
|
t20 += v * b9; |
|
t21 += v * b10; |
|
t22 += v * b11; |
|
t23 += v * b12; |
|
t24 += v * b13; |
|
t25 += v * b14; |
|
t26 += v * b15; |
|
v = a[12]; |
|
t12 += v * b0; |
|
t13 += v * b1; |
|
t14 += v * b2; |
|
t15 += v * b3; |
|
t16 += v * b4; |
|
t17 += v * b5; |
|
t18 += v * b6; |
|
t19 += v * b7; |
|
t20 += v * b8; |
|
t21 += v * b9; |
|
t22 += v * b10; |
|
t23 += v * b11; |
|
t24 += v * b12; |
|
t25 += v * b13; |
|
t26 += v * b14; |
|
t27 += v * b15; |
|
v = a[13]; |
|
t13 += v * b0; |
|
t14 += v * b1; |
|
t15 += v * b2; |
|
t16 += v * b3; |
|
t17 += v * b4; |
|
t18 += v * b5; |
|
t19 += v * b6; |
|
t20 += v * b7; |
|
t21 += v * b8; |
|
t22 += v * b9; |
|
t23 += v * b10; |
|
t24 += v * b11; |
|
t25 += v * b12; |
|
t26 += v * b13; |
|
t27 += v * b14; |
|
t28 += v * b15; |
|
v = a[14]; |
|
t14 += v * b0; |
|
t15 += v * b1; |
|
t16 += v * b2; |
|
t17 += v * b3; |
|
t18 += v * b4; |
|
t19 += v * b5; |
|
t20 += v * b6; |
|
t21 += v * b7; |
|
t22 += v * b8; |
|
t23 += v * b9; |
|
t24 += v * b10; |
|
t25 += v * b11; |
|
t26 += v * b12; |
|
t27 += v * b13; |
|
t28 += v * b14; |
|
t29 += v * b15; |
|
v = a[15]; |
|
t15 += v * b0; |
|
t16 += v * b1; |
|
t17 += v * b2; |
|
t18 += v * b3; |
|
t19 += v * b4; |
|
t20 += v * b5; |
|
t21 += v * b6; |
|
t22 += v * b7; |
|
t23 += v * b8; |
|
t24 += v * b9; |
|
t25 += v * b10; |
|
t26 += v * b11; |
|
t27 += v * b12; |
|
t28 += v * b13; |
|
t29 += v * b14; |
|
t30 += v * b15; |
|
t0 += 38 * t16; |
|
t1 += 38 * t17; |
|
t2 += 38 * t18; |
|
t3 += 38 * t19; |
|
t4 += 38 * t20; |
|
t5 += 38 * t21; |
|
t6 += 38 * t22; |
|
t7 += 38 * t23; |
|
t8 += 38 * t24; |
|
t9 += 38 * t25; |
|
t10 += 38 * t26; |
|
t11 += 38 * t27; |
|
t12 += 38 * t28; |
|
t13 += 38 * t29; |
|
t14 += 38 * t30; |
|
// t15 left as is |
|
// first car |
|
c = 1; |
|
v = t0 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t0 = v - c * 65536; |
|
v = t1 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t1 = v - c * 65536; |
|
v = t2 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t2 = v - c * 65536; |
|
v = t3 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t3 = v - c * 65536; |
|
v = t4 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t4 = v - c * 65536; |
|
v = t5 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t5 = v - c * 65536; |
|
v = t6 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t6 = v - c * 65536; |
|
v = t7 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t7 = v - c * 65536; |
|
v = t8 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t8 = v - c * 65536; |
|
v = t9 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t9 = v - c * 65536; |
|
v = t10 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t10 = v - c * 65536; |
|
v = t11 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t11 = v - c * 65536; |
|
v = t12 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t12 = v - c * 65536; |
|
v = t13 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t13 = v - c * 65536; |
|
v = t14 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t14 = v - c * 65536; |
|
v = t15 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t15 = v - c * 65536; |
|
t0 += c - 1 + 37 * (c - 1); |
|
// second car |
|
c = 1; |
|
v = t0 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t0 = v - c * 65536; |
|
v = t1 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t1 = v - c * 65536; |
|
v = t2 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t2 = v - c * 65536; |
|
v = t3 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t3 = v - c * 65536; |
|
v = t4 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t4 = v - c * 65536; |
|
v = t5 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t5 = v - c * 65536; |
|
v = t6 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t6 = v - c * 65536; |
|
v = t7 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t7 = v - c * 65536; |
|
v = t8 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t8 = v - c * 65536; |
|
v = t9 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t9 = v - c * 65536; |
|
v = t10 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t10 = v - c * 65536; |
|
v = t11 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t11 = v - c * 65536; |
|
v = t12 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t12 = v - c * 65536; |
|
v = t13 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t13 = v - c * 65536; |
|
v = t14 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t14 = v - c * 65536; |
|
v = t15 + c + 65535; |
|
c = Math.floor(v / 65536); |
|
t15 = v - c * 65536; |
|
t0 += c - 1 + 37 * (c - 1); |
|
o[0] = t0; |
|
o[1] = t1; |
|
o[2] = t2; |
|
o[3] = t3; |
|
o[4] = t4; |
|
o[5] = t5; |
|
o[6] = t6; |
|
o[7] = t7; |
|
o[8] = t8; |
|
o[9] = t9; |
|
o[10] = t10; |
|
o[11] = t11; |
|
o[12] = t12; |
|
o[13] = t13; |
|
o[14] = t14; |
|
o[15] = t15; |
|
} |
|
|
|
|
|
|
|
var $8866d3403f6374db$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
|
|
$8866d3403f6374db$exports = $iGlOy.kem = $iGlOy.kem || { |
|
}; |
|
var $8866d3403f6374db$var$BigInteger = $iGlOy.jsbn.BigInteger; |
|
/** |
|
* The API for the RSA Key Encapsulation Mechanism (RSA-KEM) from ISO 18033-2. |
|
*/ $iGlOy.kem.rsa = { |
|
}; |
|
/** |
|
* Creates an RSA KEM API object for generating a secret asymmetric key. |
|
* |
|
* The symmetric key may be generated via a call to 'encrypt', which will |
|
* produce a ciphertext to be transmitted to the recipient and a key to be |
|
* kept secret. The ciphertext is a parameter to be passed to 'decrypt' which |
|
* will produce the same secret key for the recipient to use to decrypt a |
|
* message that was encrypted with the secret key. |
|
* |
|
* @param kdf the KDF API to use (eg: new forge.kem.kdf1()). |
|
* @param options the options to use. |
|
* [prng] a custom crypto-secure pseudo-random number generator to use, |
|
* that must define "getBytesSync". |
|
*/ $iGlOy.kem.rsa.create = function(kdf, options) { |
|
options = options || { |
|
}; |
|
var prng = options.prng || $iGlOy.random; |
|
var kem = { |
|
}; |
|
/** |
|
* Generates a secret key and its encapsulation. |
|
* |
|
* @param publicKey the RSA public key to encrypt with. |
|
* @param keyLength the length, in bytes, of the secret key to generate. |
|
* |
|
* @return an object with: |
|
* encapsulation: the ciphertext for generating the secret key, as a |
|
* binary-encoded string of bytes. |
|
* key: the secret key to use for encrypting a message. |
|
*/ kem.encrypt = function(publicKey, keyLength) { |
|
// generate a random r where 1 < r < n |
|
var byteLength = Math.ceil(publicKey.n.bitLength() / 8); |
|
var r; |
|
do r = new $8866d3403f6374db$var$BigInteger($iGlOy.util.bytesToHex(prng.getBytesSync(byteLength)), 16).mod(publicKey.n); |
|
while (r.compareTo($8866d3403f6374db$var$BigInteger.ONE) <= 0) |
|
// prepend r with zeros |
|
r = $iGlOy.util.hexToBytes(r.toString(16)); |
|
var zeros = byteLength - r.length; |
|
if (zeros > 0) r = $iGlOy.util.fillString(String.fromCharCode(0), zeros) + r; |
|
// encrypt the random |
|
var encapsulation = publicKey.encrypt(r, 'NONE'); |
|
// generate the secret key |
|
var key = kdf.generate(r, keyLength); |
|
return { |
|
encapsulation: encapsulation, |
|
key: key |
|
}; |
|
}; |
|
/** |
|
* Decrypts an encapsulated secret key. |
|
* |
|
* @param privateKey the RSA private key to decrypt with. |
|
* @param encapsulation the ciphertext for generating the secret key, as |
|
* a binary-encoded string of bytes. |
|
* @param keyLength the length, in bytes, of the secret key to generate. |
|
* |
|
* @return the secret key as a binary-encoded string of bytes. |
|
*/ kem.decrypt = function(privateKey, encapsulation, keyLength) { |
|
// decrypt the encapsulation and generate the secret key |
|
var r = privateKey.decrypt(encapsulation, 'NONE'); |
|
return kdf.generate(r, keyLength); |
|
}; |
|
return kem; |
|
}; |
|
// TODO: add forge.kem.kdf.create('KDF1', {md: ..., ...}) API? |
|
/** |
|
* Creates a key derivation API object that implements KDF1 per ISO 18033-2. |
|
* |
|
* @param md the hash API to use. |
|
* @param [digestLength] an optional digest length that must be positive and |
|
* less than or equal to md.digestLength. |
|
* |
|
* @return a KDF1 API object. |
|
*/ $iGlOy.kem.kdf1 = function(md, digestLength) { |
|
$8866d3403f6374db$var$_createKDF(this, md, 0, digestLength || md.digestLength); |
|
}; |
|
/** |
|
* Creates a key derivation API object that implements KDF2 per ISO 18033-2. |
|
* |
|
* @param md the hash API to use. |
|
* @param [digestLength] an optional digest length that must be positive and |
|
* less than or equal to md.digestLength. |
|
* |
|
* @return a KDF2 API object. |
|
*/ $iGlOy.kem.kdf2 = function(md, digestLength) { |
|
$8866d3403f6374db$var$_createKDF(this, md, 1, digestLength || md.digestLength); |
|
}; |
|
/** |
|
* Creates a KDF1 or KDF2 API object. |
|
* |
|
* @param md the hash API to use. |
|
* @param counterStart the starting index for the counter. |
|
* @param digestLength the digest length to use. |
|
* |
|
* @return the KDF API object. |
|
*/ function $8866d3403f6374db$var$_createKDF(kdf, md, counterStart, digestLength) { |
|
/** |
|
* Generate a key of the specified length. |
|
* |
|
* @param x the binary-encoded byte string to generate a key from. |
|
* @param length the number of bytes to generate (the size of the key). |
|
* |
|
* @return the key as a binary-encoded string. |
|
*/ kdf.generate = function(x, length) { |
|
var key = new $iGlOy.util.ByteBuffer(); |
|
// run counter from counterStart to ceil(length / Hash.len) |
|
var k = Math.ceil(length / digestLength) + counterStart; |
|
var c = new $iGlOy.util.ByteBuffer(); |
|
for(var i = counterStart; i < k; ++i){ |
|
// I2OSP(i, 4): convert counter to an octet string of 4 octets |
|
c.putInt32(i); |
|
// digest 'x' and the counter and add the result to the key |
|
md.start(); |
|
md.update(x + c.getBytes()); |
|
var hash = md.digest(); |
|
key.putBytes(hash.getBytes(digestLength)); |
|
} |
|
// truncate to the correct key length |
|
key.truncate(key.length() - length); |
|
return key.getBytes(); |
|
}; |
|
} |
|
|
|
|
|
var $4b898e145571f67c$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
/* LOG API */ $4b898e145571f67c$exports = $iGlOy.log = $iGlOy.log || { |
|
}; |
|
/** |
|
* Application logging system. |
|
* |
|
* Each logger level available as it's own function of the form: |
|
* forge.log.level(category, args...) |
|
* The category is an arbitrary string, and the args are the same as |
|
* Firebug's console.log API. By default the call will be output as: |
|
* 'LEVEL [category] <args[0]>, args[1], ...' |
|
* This enables proper % formatting via the first argument. |
|
* Each category is enabled by default but can be enabled or disabled with |
|
* the setCategoryEnabled() function. |
|
*/ // list of known levels |
|
$iGlOy.log.levels = [ |
|
'none', |
|
'error', |
|
'warning', |
|
'info', |
|
'debug', |
|
'verbose', |
|
'max' |
|
]; |
|
// info on the levels indexed by name: |
|
// index: level index |
|
// name: uppercased display name |
|
var $4b898e145571f67c$var$sLevelInfo = { |
|
}; |
|
// list of loggers |
|
var $4b898e145571f67c$var$sLoggers = []; |
|
/** |
|
* Standard console logger. If no console support is enabled this will |
|
* remain null. Check before using. |
|
*/ var $4b898e145571f67c$var$sConsoleLogger = null; |
|
// logger flags |
|
/** |
|
* Lock the level at the current value. Used in cases where user config may |
|
* set the level such that only critical messages are seen but more verbose |
|
* messages are needed for debugging or other purposes. |
|
*/ $iGlOy.log.LEVEL_LOCKED = 2; |
|
/** |
|
* Always call log function. By default, the logging system will check the |
|
* message level against logger.level before calling the log function. This |
|
* flag allows the function to do its own check. |
|
*/ $iGlOy.log.NO_LEVEL_CHECK = 4; |
|
/** |
|
* Perform message interpolation with the passed arguments. "%" style |
|
* fields in log messages will be replaced by arguments as needed. Some |
|
* loggers, such as Firebug, may do this automatically. The original log |
|
* message will be available as 'message' and the interpolated version will |
|
* be available as 'fullMessage'. |
|
*/ $iGlOy.log.INTERPOLATE = 8; |
|
// setup each log level |
|
for(var $4b898e145571f67c$var$i = 0; $4b898e145571f67c$var$i < $iGlOy.log.levels.length; ++$4b898e145571f67c$var$i){ |
|
var $4b898e145571f67c$var$level = $iGlOy.log.levels[$4b898e145571f67c$var$i]; |
|
$4b898e145571f67c$var$sLevelInfo[$4b898e145571f67c$var$level] = { |
|
index: $4b898e145571f67c$var$i, |
|
name: $4b898e145571f67c$var$level.toUpperCase() |
|
}; |
|
} |
|
/** |
|
* Message logger. Will dispatch a message to registered loggers as needed. |
|
* |
|
* @param message message object |
|
*/ $iGlOy.log.logMessage = function(message) { |
|
var messageLevelIndex = $4b898e145571f67c$var$sLevelInfo[message.level].index; |
|
for(var i = 0; i < $4b898e145571f67c$var$sLoggers.length; ++i){ |
|
var logger = $4b898e145571f67c$var$sLoggers[i]; |
|
if (logger.flags & $iGlOy.log.NO_LEVEL_CHECK) logger.f(message); |
|
else { |
|
// get logger level |
|
var loggerLevelIndex = $4b898e145571f67c$var$sLevelInfo[logger.level].index; |
|
// check level |
|
if (messageLevelIndex <= loggerLevelIndex) // message critical enough, call logger |
|
logger.f(logger, message); |
|
} |
|
} |
|
}; |
|
/** |
|
* Sets the 'standard' key on a message object to: |
|
* "LEVEL [category] " + message |
|
* |
|
* @param message a message log object |
|
*/ $iGlOy.log.prepareStandard = function(message) { |
|
if (!('standard' in message)) message.standard = $4b898e145571f67c$var$sLevelInfo[message.level].name + //' ' + +message.timestamp + |
|
' [' + message.category + '] ' + message.message; |
|
}; |
|
/** |
|
* Sets the 'full' key on a message object to the original message |
|
* interpolated via % formatting with the message arguments. |
|
* |
|
* @param message a message log object. |
|
*/ $iGlOy.log.prepareFull = function(message) { |
|
if (!('full' in message)) { |
|
// copy args and insert message at the front |
|
var args = [ |
|
message.message |
|
]; |
|
args = args.concat([]); |
|
// format the message |
|
message.full = $iGlOy.util.format.apply(this, args); |
|
} |
|
}; |
|
/** |
|
* Applies both preparseStandard() and prepareFull() to a message object and |
|
* store result in 'standardFull'. |
|
* |
|
* @param message a message log object. |
|
*/ $iGlOy.log.prepareStandardFull = function(message) { |
|
if (!('standardFull' in message)) { |
|
// FIXME implement 'standardFull' logging |
|
$iGlOy.log.prepareStandard(message); |
|
message.standardFull = message.standard; |
|
} |
|
}; |
|
// levels for which we want functions |
|
var $4b898e145571f67c$var$levels = [ |
|
'error', |
|
'warning', |
|
'info', |
|
'debug', |
|
'verbose' |
|
]; |
|
for(var $4b898e145571f67c$var$i = 0; $4b898e145571f67c$var$i < $4b898e145571f67c$var$levels.length; ++$4b898e145571f67c$var$i)// wrap in a function to ensure proper level var is passed |
|
(function(level) { |
|
// create function for this level |
|
$iGlOy.log[level] = function(category, message /*, args...*/ ) { |
|
// convert arguments to real array, remove category and message |
|
var args = Array.prototype.slice.call(arguments).slice(2); |
|
// create message object |
|
// Note: interpolation and standard formatting is done lazily |
|
var msg = { |
|
timestamp: new Date(), |
|
level: level, |
|
category: category, |
|
message: message, |
|
'arguments': args |
|
}; |
|
// process this message |
|
$iGlOy.log.logMessage(msg); |
|
}; |
|
})($4b898e145571f67c$var$levels[$4b898e145571f67c$var$i]); |
|
/** |
|
* Creates a new logger with specified custom logging function. |
|
* |
|
* The logging function has a signature of: |
|
* function(logger, message) |
|
* logger: current logger |
|
* message: object: |
|
* level: level id |
|
* category: category |
|
* message: string message |
|
* arguments: Array of extra arguments |
|
* fullMessage: interpolated message and arguments if INTERPOLATE flag set |
|
* |
|
* @param logFunction a logging function which takes a log message object |
|
* as a parameter. |
|
* |
|
* @return a logger object. |
|
*/ $iGlOy.log.makeLogger = function(logFunction) { |
|
var logger = { |
|
flags: 0, |
|
f: logFunction |
|
}; |
|
$iGlOy.log.setLevel(logger, 'none'); |
|
return logger; |
|
}; |
|
/** |
|
* Sets the current log level on a logger. |
|
* |
|
* @param logger the target logger. |
|
* @param level the new maximum log level as a string. |
|
* |
|
* @return true if set, false if not. |
|
*/ $iGlOy.log.setLevel = function(logger, level) { |
|
var rval = false; |
|
if (logger && !(logger.flags & $iGlOy.log.LEVEL_LOCKED)) for(var i = 0; i < $iGlOy.log.levels.length; ++i){ |
|
var aValidLevel = $iGlOy.log.levels[i]; |
|
if (level == aValidLevel) { |
|
// set level |
|
logger.level = level; |
|
rval = true; |
|
break; |
|
} |
|
} |
|
return rval; |
|
}; |
|
/** |
|
* Locks the log level at its current value. |
|
* |
|
* @param logger the target logger. |
|
* @param lock boolean lock value, default to true. |
|
*/ $iGlOy.log.lock = function(logger, lock) { |
|
if (typeof lock === 'undefined' || lock) logger.flags |= $iGlOy.log.LEVEL_LOCKED; |
|
else logger.flags &= ~$iGlOy.log.LEVEL_LOCKED; |
|
}; |
|
/** |
|
* Adds a logger. |
|
* |
|
* @param logger the logger object. |
|
*/ $iGlOy.log.addLogger = function(logger) { |
|
$4b898e145571f67c$var$sLoggers.push(logger); |
|
}; |
|
// setup the console logger if possible, else create fake console.log |
|
if (typeof console !== 'undefined' && 'log' in console) { |
|
var $4b898e145571f67c$var$logger; |
|
if (console.error && console.warn && console.info && console.debug) { |
|
// looks like Firebug-style logging is available |
|
// level handlers map |
|
var $4b898e145571f67c$var$levelHandlers = { |
|
error: console.error, |
|
warning: console.warn, |
|
info: console.info, |
|
debug: console.debug, |
|
verbose: console.debug |
|
}; |
|
var $4b898e145571f67c$var$f = function(logger, message) { |
|
$iGlOy.log.prepareStandard(message); |
|
var handler = $4b898e145571f67c$var$levelHandlers[message.level]; |
|
// prepend standard message and concat args |
|
var args = [ |
|
message.standard |
|
]; |
|
args = args.concat(message['arguments'].slice()); |
|
// apply to low-level console function |
|
handler.apply(console, args); |
|
}; |
|
$4b898e145571f67c$var$logger = $iGlOy.log.makeLogger($4b898e145571f67c$var$f); |
|
} else { |
|
// only appear to have basic console.log |
|
var $4b898e145571f67c$var$f = function(logger, message) { |
|
$iGlOy.log.prepareStandardFull(message); |
|
console.log(message.standardFull); |
|
}; |
|
$4b898e145571f67c$var$logger = $iGlOy.log.makeLogger($4b898e145571f67c$var$f); |
|
} |
|
$iGlOy.log.setLevel($4b898e145571f67c$var$logger, 'debug'); |
|
$iGlOy.log.addLogger($4b898e145571f67c$var$logger); |
|
$4b898e145571f67c$var$sConsoleLogger = $4b898e145571f67c$var$logger; |
|
} else // define fake console.log to avoid potential script errors on |
|
// browsers that do not have console logging |
|
console = { |
|
log: function() { |
|
} |
|
}; |
|
/* |
|
* Check for logging control query vars in current URL. |
|
* |
|
* console.level=<level-name> |
|
* Set's the console log level by name. Useful to override defaults and |
|
* allow more verbose logging before a user config is loaded. |
|
* |
|
* console.lock=<true|false> |
|
* Lock the console log level at whatever level it is set at. This is run |
|
* after console.level is processed. Useful to force a level of verbosity |
|
* that could otherwise be limited by a user config. |
|
*/ if ($4b898e145571f67c$var$sConsoleLogger !== null && typeof window !== 'undefined' && window.location) { |
|
var $4b898e145571f67c$var$query = new URL(window.location.href).searchParams; |
|
if ($4b898e145571f67c$var$query.has('console.level')) // set with last value |
|
$iGlOy.log.setLevel($4b898e145571f67c$var$sConsoleLogger, $4b898e145571f67c$var$query.get('console.level').slice(-1)[0]); |
|
if ($4b898e145571f67c$var$query.has('console.lock')) { |
|
// set with last value |
|
var $4b898e145571f67c$var$lock = $4b898e145571f67c$var$query.get('console.lock').slice(-1)[0]; |
|
if ($4b898e145571f67c$var$lock == 'true') $iGlOy.log.lock($4b898e145571f67c$var$sConsoleLogger); |
|
} |
|
} |
|
// provide public access to console logger |
|
$iGlOy.log.consoleLogger = $4b898e145571f67c$var$sConsoleLogger; |
|
|
|
|
|
var $8e579bac14cccf16$exports = {}; |
|
|
|
/** |
|
* Node.js module for all known Forge message digests. |
|
* |
|
* @author Dave Longley |
|
* |
|
* Copyright 2011-2017 Digital Bazaar, Inc. |
|
*/ $8e579bac14cccf16$exports = (parcelRequire("ai0Z9")); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var $e128d865c5cf51a7$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// shortcut for ASN.1 API |
|
var $e128d865c5cf51a7$var$asn1 = $iGlOy.asn1; |
|
// shortcut for PKCS#7 API |
|
var $e128d865c5cf51a7$var$p7 = $e128d865c5cf51a7$exports = $iGlOy.pkcs7 = $iGlOy.pkcs7 || { |
|
}; |
|
/** |
|
* Converts a PKCS#7 message from PEM format. |
|
* |
|
* @param pem the PEM-formatted PKCS#7 message. |
|
* |
|
* @return the PKCS#7 message. |
|
*/ $e128d865c5cf51a7$var$p7.messageFromPem = function(pem) { |
|
var msg = $iGlOy.pem.decode(pem)[0]; |
|
if (msg.type !== 'PKCS7') { |
|
var error = new Error("Could not convert PKCS#7 message from PEM; PEM header type is not \"PKCS#7\"."); |
|
error.headerType = msg.type; |
|
throw error; |
|
} |
|
if (msg.procType && msg.procType.type === 'ENCRYPTED') throw new Error('Could not convert PKCS#7 message from PEM; PEM is encrypted.'); |
|
// convert DER to ASN.1 object |
|
var obj = $e128d865c5cf51a7$var$asn1.fromDer(msg.body); |
|
return $e128d865c5cf51a7$var$p7.messageFromAsn1(obj); |
|
}; |
|
/** |
|
* Converts a PKCS#7 message to PEM format. |
|
* |
|
* @param msg The PKCS#7 message object |
|
* @param maxline The maximum characters per line, defaults to 64. |
|
* |
|
* @return The PEM-formatted PKCS#7 message. |
|
*/ $e128d865c5cf51a7$var$p7.messageToPem = function(msg, maxline) { |
|
// convert to ASN.1, then DER, then PEM-encode |
|
var pemObj = { |
|
type: 'PKCS7', |
|
body: $e128d865c5cf51a7$var$asn1.toDer(msg.toAsn1()).getBytes() |
|
}; |
|
return $iGlOy.pem.encode(pemObj, { |
|
maxline: maxline |
|
}); |
|
}; |
|
/** |
|
* Converts a PKCS#7 message from an ASN.1 object. |
|
* |
|
* @param obj the ASN.1 representation of a ContentInfo. |
|
* |
|
* @return the PKCS#7 message. |
|
*/ $e128d865c5cf51a7$var$p7.messageFromAsn1 = function(obj) { |
|
// validate root level ContentInfo and capture data |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$e128d865c5cf51a7$var$asn1.validate(obj, $e128d865c5cf51a7$var$p7.asn1.contentInfoValidator, capture, errors)) { |
|
var error = new Error("Cannot read PKCS#7 message. ASN.1 object is not an PKCS#7 ContentInfo."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
var contentType = $e128d865c5cf51a7$var$asn1.derToOid(capture.contentType); |
|
var msg; |
|
switch(contentType){ |
|
case $iGlOy.pki.oids.envelopedData: |
|
msg = $e128d865c5cf51a7$var$p7.createEnvelopedData(); |
|
break; |
|
case $iGlOy.pki.oids.encryptedData: |
|
msg = $e128d865c5cf51a7$var$p7.createEncryptedData(); |
|
break; |
|
case $iGlOy.pki.oids.signedData: |
|
msg = $e128d865c5cf51a7$var$p7.createSignedData(); |
|
break; |
|
default: |
|
throw new Error('Cannot read PKCS#7 message. ContentType with OID ' + contentType + ' is not (yet) supported.'); |
|
} |
|
msg.fromAsn1(capture.content.value[0]); |
|
return msg; |
|
}; |
|
$e128d865c5cf51a7$var$p7.createSignedData = function() { |
|
var msg = null; |
|
msg = { |
|
type: $iGlOy.pki.oids.signedData, |
|
version: 1, |
|
certificates: [], |
|
crls: [], |
|
// TODO: add json-formatted signer stuff here? |
|
signers: [], |
|
// populated during sign() |
|
digestAlgorithmIdentifiers: [], |
|
contentInfo: null, |
|
signerInfos: [], |
|
fromAsn1: function(obj) { |
|
// validate SignedData content block and capture data. |
|
$e128d865c5cf51a7$var$_fromAsn1(msg, obj, $e128d865c5cf51a7$var$p7.asn1.signedDataValidator); |
|
msg.certificates = []; |
|
msg.crls = []; |
|
msg.digestAlgorithmIdentifiers = []; |
|
msg.contentInfo = null; |
|
msg.signerInfos = []; |
|
if (msg.rawCapture.certificates) { |
|
var certs = msg.rawCapture.certificates.value; |
|
for(var i = 0; i < certs.length; ++i)msg.certificates.push($iGlOy.pki.certificateFromAsn1(certs[i])); |
|
} |
|
// TODO: parse crls |
|
}, |
|
toAsn1: function() { |
|
// degenerate case with no content |
|
if (!msg.contentInfo) msg.sign(); |
|
var certs = []; |
|
for(var i = 0; i < msg.certificates.length; ++i)certs.push($iGlOy.pki.certificateToAsn1(msg.certificates[i])); |
|
var crls = []; |
|
// TODO: implement CRLs |
|
// [0] SignedData |
|
var signedData = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// Version |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.INTEGER, false, $e128d865c5cf51a7$var$asn1.integerToDer(msg.version).getBytes()), |
|
// DigestAlgorithmIdentifiers |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SET, true, msg.digestAlgorithmIdentifiers), |
|
// ContentInfo |
|
msg.contentInfo |
|
]) |
|
]); |
|
if (certs.length > 0) // [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL |
|
signedData.value[0].value.push($e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, certs)); |
|
if (crls.length > 0) // [1] IMPLICIT CertificateRevocationLists OPTIONAL |
|
signedData.value[0].value.push($e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.CONTEXT_SPECIFIC, 1, true, crls)); |
|
// SignerInfos |
|
signedData.value[0].value.push($e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SET, true, msg.signerInfos)); |
|
// ContentInfo |
|
return $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// ContentType |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer(msg.type).getBytes()), |
|
// [0] SignedData |
|
signedData |
|
]); |
|
}, |
|
/** |
|
* Add (another) entity to list of signers. |
|
* |
|
* Note: If authenticatedAttributes are provided, then, per RFC 2315, |
|
* they must include at least two attributes: content type and |
|
* message digest. The message digest attribute value will be |
|
* auto-calculated during signing and will be ignored if provided. |
|
* |
|
* Here's an example of providing these two attributes: |
|
* |
|
* forge.pkcs7.createSignedData(); |
|
* p7.addSigner({ |
|
* issuer: cert.issuer.attributes, |
|
* serialNumber: cert.serialNumber, |
|
* key: privateKey, |
|
* digestAlgorithm: forge.pki.oids.sha1, |
|
* authenticatedAttributes: [{ |
|
* type: forge.pki.oids.contentType, |
|
* value: forge.pki.oids.data |
|
* }, { |
|
* type: forge.pki.oids.messageDigest |
|
* }] |
|
* }); |
|
* |
|
* TODO: Support [subjectKeyIdentifier] as signer's ID. |
|
* |
|
* @param signer the signer information: |
|
* key the signer's private key. |
|
* [certificate] a certificate containing the public key |
|
* associated with the signer's private key; use this option as |
|
* an alternative to specifying signer.issuer and |
|
* signer.serialNumber. |
|
* [issuer] the issuer attributes (eg: cert.issuer.attributes). |
|
* [serialNumber] the signer's certificate's serial number in |
|
* hexadecimal (eg: cert.serialNumber). |
|
* [digestAlgorithm] the message digest OID, as a string, to use |
|
* (eg: forge.pki.oids.sha1). |
|
* [authenticatedAttributes] an optional array of attributes |
|
* to also sign along with the content. |
|
*/ addSigner: function(signer) { |
|
var issuer = signer.issuer; |
|
var serialNumber = signer.serialNumber; |
|
if (signer.certificate) { |
|
var cert = signer.certificate; |
|
if (typeof cert === 'string') cert = $iGlOy.pki.certificateFromPem(cert); |
|
issuer = cert.issuer.attributes; |
|
serialNumber = cert.serialNumber; |
|
} |
|
var key = signer.key; |
|
if (!key) throw new Error('Could not add PKCS#7 signer; no private key specified.'); |
|
if (typeof key === 'string') key = $iGlOy.pki.privateKeyFromPem(key); |
|
// ensure OID known for digest algorithm |
|
var digestAlgorithm = signer.digestAlgorithm || $iGlOy.pki.oids.sha1; |
|
switch(digestAlgorithm){ |
|
case $iGlOy.pki.oids.sha1: |
|
case $iGlOy.pki.oids.sha256: |
|
case $iGlOy.pki.oids.sha384: |
|
case $iGlOy.pki.oids.sha512: |
|
case $iGlOy.pki.oids.md5: |
|
break; |
|
default: |
|
throw new Error('Could not add PKCS#7 signer; unknown message digest algorithm: ' + digestAlgorithm); |
|
} |
|
// if authenticatedAttributes is present, then the attributes |
|
// must contain at least PKCS #9 content-type and message-digest |
|
var authenticatedAttributes = signer.authenticatedAttributes || []; |
|
if (authenticatedAttributes.length > 0) { |
|
var contentType = false; |
|
var messageDigest = false; |
|
for(var i = 0; i < authenticatedAttributes.length; ++i){ |
|
var attr = authenticatedAttributes[i]; |
|
if (!contentType && attr.type === $iGlOy.pki.oids.contentType) { |
|
contentType = true; |
|
if (messageDigest) break; |
|
continue; |
|
} |
|
if (!messageDigest && attr.type === $iGlOy.pki.oids.messageDigest) { |
|
messageDigest = true; |
|
if (contentType) break; |
|
continue; |
|
} |
|
} |
|
if (!contentType || !messageDigest) throw new Error("Invalid signer.authenticatedAttributes. If signer.authenticatedAttributes is specified, then it must contain at least two attributes, PKCS #9 content-type and PKCS #9 message-digest."); |
|
} |
|
msg.signers.push({ |
|
key: key, |
|
version: 1, |
|
issuer: issuer, |
|
serialNumber: serialNumber, |
|
digestAlgorithm: digestAlgorithm, |
|
signatureAlgorithm: $iGlOy.pki.oids.rsaEncryption, |
|
signature: null, |
|
authenticatedAttributes: authenticatedAttributes, |
|
unauthenticatedAttributes: [] |
|
}); |
|
}, |
|
/** |
|
* Signs the content. |
|
* @param options Options to apply when signing: |
|
* [detached] boolean. If signing should be done in detached mode. Defaults to false. |
|
*/ sign: function(options) { |
|
options = options || { |
|
}; |
|
// auto-generate content info |
|
if (typeof msg.content !== 'object' || msg.contentInfo === null) { |
|
// use Data ContentInfo |
|
msg.contentInfo = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// ContentType |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer($iGlOy.pki.oids.data).getBytes()) |
|
]); |
|
// add actual content, if present |
|
if ('content' in msg) { |
|
var content; |
|
if (msg.content instanceof $iGlOy.util.ByteBuffer) content = msg.content.bytes(); |
|
else if (typeof msg.content === 'string') content = $iGlOy.util.encodeUtf8(msg.content); |
|
if (options.detached) msg.detachedContent = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OCTETSTRING, false, content); |
|
else msg.contentInfo.value.push(// [0] EXPLICIT content |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OCTETSTRING, false, content) |
|
])); |
|
} |
|
} |
|
// no signers, return early (degenerate case for certificate container) |
|
if (msg.signers.length === 0) return; |
|
// generate digest algorithm identifiers |
|
var mds = addDigestAlgorithmIds(); |
|
// generate signerInfos |
|
addSignerInfos(mds); |
|
}, |
|
verify: function() { |
|
throw new Error('PKCS#7 signature verification not yet implemented.'); |
|
}, |
|
/** |
|
* Add a certificate. |
|
* |
|
* @param cert the certificate to add. |
|
*/ addCertificate: function(cert) { |
|
// convert from PEM |
|
if (typeof cert === 'string') cert = $iGlOy.pki.certificateFromPem(cert); |
|
msg.certificates.push(cert); |
|
}, |
|
/** |
|
* Add a certificate revokation list. |
|
* |
|
* @param crl the certificate revokation list to add. |
|
*/ addCertificateRevokationList: function(crl) { |
|
throw new Error('PKCS#7 CRL support not yet implemented.'); |
|
} |
|
}; |
|
function addDigestAlgorithmIds() { |
|
var mds = { |
|
}; |
|
for(var i = 0; i < msg.signers.length; ++i){ |
|
var signer = msg.signers[i]; |
|
var oid = signer.digestAlgorithm; |
|
if (!(oid in mds)) { |
|
// content digest |
|
mds[oid] = $iGlOy.md[$iGlOy.pki.oids[oid]].create(); |
|
} |
|
if (signer.authenticatedAttributes.length === 0) { |
|
// no custom attributes to digest; use content message digest |
|
signer.md = mds[oid]; |
|
} else { |
|
// custom attributes to be digested; use own message digest |
|
// TODO: optimize to just copy message digest state if that |
|
// feature is ever supported with message digests |
|
signer.md = $iGlOy.md[$iGlOy.pki.oids[oid]].create(); |
|
} |
|
} |
|
// add unique digest algorithm identifiers |
|
msg.digestAlgorithmIdentifiers = []; |
|
for(var oid in mds){ |
|
msg.digestAlgorithmIdentifiers.push(// AlgorithmIdentifier |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// algorithm |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer(oid).getBytes()), |
|
// parameters (null) |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.NULL, false, '') |
|
])); |
|
} |
|
return mds; |
|
} |
|
function addSignerInfos(mds) { |
|
var content; |
|
if (msg.detachedContent) { |
|
// Signature has been made in detached mode. |
|
content = msg.detachedContent; |
|
} else { |
|
// Note: ContentInfo is a SEQUENCE with 2 values, second value is |
|
// the content field and is optional for a ContentInfo but required here |
|
// since signers are present |
|
// get ContentInfo content |
|
content = msg.contentInfo.value[1]; |
|
// skip [0] EXPLICIT content wrapper |
|
content = content.value[0]; |
|
} |
|
if (!content) { |
|
throw new Error('Could not sign PKCS#7 message; there is no content to sign.'); |
|
} |
|
// get ContentInfo content type |
|
var contentType = $e128d865c5cf51a7$var$asn1.derToOid(msg.contentInfo.value[0].value); |
|
// serialize content |
|
var bytes = $e128d865c5cf51a7$var$asn1.toDer(content); |
|
// skip identifier and length per RFC 2315 9.3 |
|
// skip identifier (1 byte) |
|
bytes.getByte(); |
|
// read and discard length bytes |
|
$e128d865c5cf51a7$var$asn1.getBerValueLength(bytes); |
|
bytes = bytes.getBytes(); |
|
// digest content DER value bytes |
|
for(var oid in mds){ |
|
mds[oid].start().update(bytes); |
|
} |
|
// sign content |
|
var signingTime = new Date(); |
|
for(var i = 0; i < msg.signers.length; ++i){ |
|
var signer = msg.signers[i]; |
|
if (signer.authenticatedAttributes.length === 0) { |
|
// if ContentInfo content type is not "Data", then |
|
// authenticatedAttributes must be present per RFC 2315 |
|
if (contentType !== $iGlOy.pki.oids.data) { |
|
throw new Error("Invalid signer; authenticatedAttributes must be present when the ContentInfo content type is not PKCS#7 Data."); |
|
} |
|
} else { |
|
// process authenticated attributes |
|
// [0] IMPLICIT |
|
signer.authenticatedAttributesAsn1 = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, []); |
|
// per RFC 2315, attributes are to be digested using a SET container |
|
// not the above [0] IMPLICIT container |
|
var attrsAsn1 = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SET, true, []); |
|
for(var ai = 0; ai < signer.authenticatedAttributes.length; ++ai){ |
|
var attr = signer.authenticatedAttributes[ai]; |
|
if (attr.type === $iGlOy.pki.oids.messageDigest) { |
|
// use content message digest as value |
|
attr.value = mds[signer.digestAlgorithm].digest(); |
|
} else if (attr.type === $iGlOy.pki.oids.signingTime) { |
|
// auto-populate signing time if not already set |
|
if (!attr.value) { |
|
attr.value = signingTime; |
|
} |
|
} |
|
// convert to ASN.1 and push onto Attributes SET (for signing) and |
|
// onto authenticatedAttributesAsn1 to complete SignedData ASN.1 |
|
// TODO: optimize away duplication |
|
attrsAsn1.value.push($e128d865c5cf51a7$var$_attributeToAsn1(attr)); |
|
signer.authenticatedAttributesAsn1.value.push($e128d865c5cf51a7$var$_attributeToAsn1(attr)); |
|
} |
|
// DER-serialize and digest SET OF attributes only |
|
bytes = $e128d865c5cf51a7$var$asn1.toDer(attrsAsn1).getBytes(); |
|
signer.md.start().update(bytes); |
|
} |
|
// sign digest |
|
signer.signature = signer.key.sign(signer.md, 'RSASSA-PKCS1-V1_5'); |
|
} |
|
// add signer info |
|
msg.signerInfos = $e128d865c5cf51a7$var$_signersToAsn1(msg.signers); |
|
} |
|
return msg; |
|
}; |
|
/** |
|
* Creates an empty PKCS#7 message of type EncryptedData. |
|
* |
|
* @return the message. |
|
*/ $e128d865c5cf51a7$var$p7.createEncryptedData = function() { |
|
var msg = null; |
|
msg = { |
|
type: $iGlOy.pki.oids.encryptedData, |
|
version: 0, |
|
encryptedContent: { |
|
algorithm: $iGlOy.pki.oids['aes256-CBC'] |
|
}, |
|
/** |
|
* Reads an EncryptedData content block (in ASN.1 format) |
|
* |
|
* @param obj The ASN.1 representation of the EncryptedData content block |
|
*/ fromAsn1: function(obj) { |
|
// Validate EncryptedData content block and capture data. |
|
$e128d865c5cf51a7$var$_fromAsn1(msg, obj, $e128d865c5cf51a7$var$p7.asn1.encryptedDataValidator); |
|
}, |
|
/** |
|
* Decrypt encrypted content |
|
* |
|
* @param key The (symmetric) key as a byte buffer |
|
*/ decrypt: function(key) { |
|
if (key !== undefined) msg.encryptedContent.key = key; |
|
$e128d865c5cf51a7$var$_decryptContent(msg); |
|
} |
|
}; |
|
return msg; |
|
}; |
|
/** |
|
* Creates an empty PKCS#7 message of type EnvelopedData. |
|
* |
|
* @return the message. |
|
*/ $e128d865c5cf51a7$var$p7.createEnvelopedData = function() { |
|
var msg = null; |
|
msg = { |
|
type: $iGlOy.pki.oids.envelopedData, |
|
version: 0, |
|
recipients: [], |
|
encryptedContent: { |
|
algorithm: $iGlOy.pki.oids['aes256-CBC'] |
|
}, |
|
/** |
|
* Reads an EnvelopedData content block (in ASN.1 format) |
|
* |
|
* @param obj the ASN.1 representation of the EnvelopedData content block. |
|
*/ fromAsn1: function(obj) { |
|
// validate EnvelopedData content block and capture data |
|
var capture = $e128d865c5cf51a7$var$_fromAsn1(msg, obj, $e128d865c5cf51a7$var$p7.asn1.envelopedDataValidator); |
|
msg.recipients = $e128d865c5cf51a7$var$_recipientsFromAsn1(capture.recipientInfos.value); |
|
}, |
|
toAsn1: function() { |
|
// ContentInfo |
|
return $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// ContentType |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer(msg.type).getBytes()), |
|
// [0] EnvelopedData |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// Version |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.INTEGER, false, $e128d865c5cf51a7$var$asn1.integerToDer(msg.version).getBytes()), |
|
// RecipientInfos |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SET, true, $e128d865c5cf51a7$var$_recipientsToAsn1(msg.recipients)), |
|
// EncryptedContentInfo |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, $e128d865c5cf51a7$var$_encryptedContentToAsn1(msg.encryptedContent)) |
|
]) |
|
]) |
|
]); |
|
}, |
|
/** |
|
* Find recipient by X.509 certificate's issuer. |
|
* |
|
* @param cert the certificate with the issuer to look for. |
|
* |
|
* @return the recipient object. |
|
*/ findRecipient: function(cert) { |
|
var sAttr = cert.issuer.attributes; |
|
for(var i = 0; i < msg.recipients.length; ++i){ |
|
var r = msg.recipients[i]; |
|
var rAttr = r.issuer; |
|
if (r.serialNumber !== cert.serialNumber) continue; |
|
if (rAttr.length !== sAttr.length) continue; |
|
var match = true; |
|
for(var j = 0; j < sAttr.length; ++j)if (rAttr[j].type !== sAttr[j].type || rAttr[j].value !== sAttr[j].value) { |
|
match = false; |
|
break; |
|
} |
|
if (match) return r; |
|
} |
|
return null; |
|
}, |
|
/** |
|
* Decrypt enveloped content |
|
* |
|
* @param recipient The recipient object related to the private key |
|
* @param privKey The (RSA) private key object |
|
*/ decrypt: function(recipient, privKey) { |
|
if (msg.encryptedContent.key === undefined && recipient !== undefined && privKey !== undefined) switch(recipient.encryptedContent.algorithm){ |
|
case $iGlOy.pki.oids.rsaEncryption: |
|
case $iGlOy.pki.oids.desCBC: |
|
var key = privKey.decrypt(recipient.encryptedContent.content); |
|
msg.encryptedContent.key = $iGlOy.util.createBuffer(key); |
|
break; |
|
default: |
|
throw new Error("Unsupported asymmetric cipher, OID " + recipient.encryptedContent.algorithm); |
|
} |
|
$e128d865c5cf51a7$var$_decryptContent(msg); |
|
}, |
|
/** |
|
* Add (another) entity to list of recipients. |
|
* |
|
* @param cert The certificate of the entity to add. |
|
*/ addRecipient: function(cert) { |
|
msg.recipients.push({ |
|
version: 0, |
|
issuer: cert.issuer.attributes, |
|
serialNumber: cert.serialNumber, |
|
encryptedContent: { |
|
// We simply assume rsaEncryption here, since forge.pki only |
|
// supports RSA so far. If the PKI module supports other |
|
// ciphers one day, we need to modify this one as well. |
|
algorithm: $iGlOy.pki.oids.rsaEncryption, |
|
key: cert.publicKey |
|
} |
|
}); |
|
}, |
|
/** |
|
* Encrypt enveloped content. |
|
* |
|
* This function supports two optional arguments, cipher and key, which |
|
* can be used to influence symmetric encryption. Unless cipher is |
|
* provided, the cipher specified in encryptedContent.algorithm is used |
|
* (defaults to AES-256-CBC). If no key is provided, encryptedContent.key |
|
* is (re-)used. If that one's not set, a random key will be generated |
|
* automatically. |
|
* |
|
* @param [key] The key to be used for symmetric encryption. |
|
* @param [cipher] The OID of the symmetric cipher to use. |
|
*/ encrypt: function(key, cipher) { |
|
// Part 1: Symmetric encryption |
|
if (msg.encryptedContent.content === undefined) { |
|
cipher = cipher || msg.encryptedContent.algorithm; |
|
key = key || msg.encryptedContent.key; |
|
var keyLen, ivLen, ciphFn; |
|
switch(cipher){ |
|
case $iGlOy.pki.oids['aes128-CBC']: |
|
keyLen = 16; |
|
ivLen = 16; |
|
ciphFn = $iGlOy.aes.createEncryptionCipher; |
|
break; |
|
case $iGlOy.pki.oids['aes192-CBC']: |
|
keyLen = 24; |
|
ivLen = 16; |
|
ciphFn = $iGlOy.aes.createEncryptionCipher; |
|
break; |
|
case $iGlOy.pki.oids['aes256-CBC']: |
|
keyLen = 32; |
|
ivLen = 16; |
|
ciphFn = $iGlOy.aes.createEncryptionCipher; |
|
break; |
|
case $iGlOy.pki.oids['des-EDE3-CBC']: |
|
keyLen = 24; |
|
ivLen = 8; |
|
ciphFn = $iGlOy.des.createEncryptionCipher; |
|
break; |
|
default: |
|
throw new Error('Unsupported symmetric cipher, OID ' + cipher); |
|
} |
|
if (key === undefined) key = $iGlOy.util.createBuffer($iGlOy.random.getBytes(keyLen)); |
|
else if (key.length() != keyLen) throw new Error("Symmetric key has wrong length; got " + key.length() + ' bytes, expected ' + keyLen + '.'); |
|
// Keep a copy of the key & IV in the object, so the caller can |
|
// use it for whatever reason. |
|
msg.encryptedContent.algorithm = cipher; |
|
msg.encryptedContent.key = key; |
|
msg.encryptedContent.parameter = $iGlOy.util.createBuffer($iGlOy.random.getBytes(ivLen)); |
|
var ciph = ciphFn(key); |
|
ciph.start(msg.encryptedContent.parameter.copy()); |
|
ciph.update(msg.content); |
|
// The finish function does PKCS#7 padding by default, therefore |
|
// no action required by us. |
|
if (!ciph.finish()) throw new Error('Symmetric encryption failed.'); |
|
msg.encryptedContent.content = ciph.output; |
|
} |
|
// Part 2: asymmetric encryption for each recipient |
|
for(var i = 0; i < msg.recipients.length; ++i){ |
|
var recipient = msg.recipients[i]; |
|
// Nothing to do, encryption already done. |
|
if (recipient.encryptedContent.content !== undefined) continue; |
|
switch(recipient.encryptedContent.algorithm){ |
|
case $iGlOy.pki.oids.rsaEncryption: |
|
recipient.encryptedContent.content = recipient.encryptedContent.key.encrypt(msg.encryptedContent.key.data); |
|
break; |
|
default: |
|
throw new Error('Unsupported asymmetric cipher, OID ' + recipient.encryptedContent.algorithm); |
|
} |
|
} |
|
} |
|
}; |
|
return msg; |
|
}; |
|
/** |
|
* Converts a single recipient from an ASN.1 object. |
|
* |
|
* @param obj the ASN.1 RecipientInfo. |
|
* |
|
* @return the recipient object. |
|
*/ function $e128d865c5cf51a7$var$_recipientFromAsn1(obj) { |
|
// validate EnvelopedData content block and capture data |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$e128d865c5cf51a7$var$asn1.validate(obj, $e128d865c5cf51a7$var$p7.asn1.recipientInfoValidator, capture, errors)) { |
|
var error = new Error("Cannot read PKCS#7 RecipientInfo. ASN.1 object is not an PKCS#7 RecipientInfo."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
return { |
|
version: capture.version.charCodeAt(0), |
|
issuer: $iGlOy.pki.RDNAttributesAsArray(capture.issuer), |
|
serialNumber: $iGlOy.util.createBuffer(capture.serial).toHex(), |
|
encryptedContent: { |
|
algorithm: $e128d865c5cf51a7$var$asn1.derToOid(capture.encAlgorithm), |
|
parameter: capture.encParameter ? capture.encParameter.value : undefined, |
|
content: capture.encKey |
|
} |
|
}; |
|
} |
|
/** |
|
* Converts a single recipient object to an ASN.1 object. |
|
* |
|
* @param obj the recipient object. |
|
* |
|
* @return the ASN.1 RecipientInfo. |
|
*/ function $e128d865c5cf51a7$var$_recipientToAsn1(obj) { |
|
return $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// Version |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.INTEGER, false, $e128d865c5cf51a7$var$asn1.integerToDer(obj.version).getBytes()), |
|
// IssuerAndSerialNumber |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// Name |
|
$iGlOy.pki.distinguishedNameToAsn1({ |
|
attributes: obj.issuer |
|
}), |
|
// Serial |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.INTEGER, false, $iGlOy.util.hexToBytes(obj.serialNumber)) |
|
]), |
|
// KeyEncryptionAlgorithmIdentifier |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// Algorithm |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer(obj.encryptedContent.algorithm).getBytes()), |
|
// Parameter, force NULL, only RSA supported for now. |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.NULL, false, '') |
|
]), |
|
// EncryptedKey |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OCTETSTRING, false, obj.encryptedContent.content) |
|
]); |
|
} |
|
/** |
|
* Map a set of RecipientInfo ASN.1 objects to recipient objects. |
|
* |
|
* @param infos an array of ASN.1 representations RecipientInfo (i.e. SET OF). |
|
* |
|
* @return an array of recipient objects. |
|
*/ function $e128d865c5cf51a7$var$_recipientsFromAsn1(infos) { |
|
var ret = []; |
|
for(var i = 0; i < infos.length; ++i)ret.push($e128d865c5cf51a7$var$_recipientFromAsn1(infos[i])); |
|
return ret; |
|
} |
|
/** |
|
* Map an array of recipient objects to ASN.1 RecipientInfo objects. |
|
* |
|
* @param recipients an array of recipientInfo objects. |
|
* |
|
* @return an array of ASN.1 RecipientInfos. |
|
*/ function $e128d865c5cf51a7$var$_recipientsToAsn1(recipients) { |
|
var ret = []; |
|
for(var i = 0; i < recipients.length; ++i)ret.push($e128d865c5cf51a7$var$_recipientToAsn1(recipients[i])); |
|
return ret; |
|
} |
|
/** |
|
* Converts a single signer from an ASN.1 object. |
|
* |
|
* @param obj the ASN.1 representation of a SignerInfo. |
|
* |
|
* @return the signer object. |
|
*/ function $e128d865c5cf51a7$var$_signerFromAsn1(obj) { |
|
// validate EnvelopedData content block and capture data |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$e128d865c5cf51a7$var$asn1.validate(obj, $e128d865c5cf51a7$var$p7.asn1.signerInfoValidator, capture, errors)) { |
|
var error = new Error("Cannot read PKCS#7 SignerInfo. ASN.1 object is not an PKCS#7 SignerInfo."); |
|
error.errors = errors; |
|
throw error; |
|
} |
|
var rval = { |
|
version: capture.version.charCodeAt(0), |
|
issuer: $iGlOy.pki.RDNAttributesAsArray(capture.issuer), |
|
serialNumber: $iGlOy.util.createBuffer(capture.serial).toHex(), |
|
digestAlgorithm: $e128d865c5cf51a7$var$asn1.derToOid(capture.digestAlgorithm), |
|
signatureAlgorithm: $e128d865c5cf51a7$var$asn1.derToOid(capture.signatureAlgorithm), |
|
signature: capture.signature, |
|
authenticatedAttributes: [], |
|
unauthenticatedAttributes: [] |
|
}; |
|
// TODO: convert attributes |
|
var authenticatedAttributes = capture.authenticatedAttributes || []; |
|
var unauthenticatedAttributes = capture.unauthenticatedAttributes || []; |
|
return rval; |
|
} |
|
/** |
|
* Converts a single signerInfo object to an ASN.1 object. |
|
* |
|
* @param obj the signerInfo object. |
|
* |
|
* @return the ASN.1 representation of a SignerInfo. |
|
*/ function $e128d865c5cf51a7$var$_signerToAsn1(obj) { |
|
// SignerInfo |
|
var rval = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// version |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.INTEGER, false, $e128d865c5cf51a7$var$asn1.integerToDer(obj.version).getBytes()), |
|
// issuerAndSerialNumber |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// name |
|
$iGlOy.pki.distinguishedNameToAsn1({ |
|
attributes: obj.issuer |
|
}), |
|
// serial |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.INTEGER, false, $iGlOy.util.hexToBytes(obj.serialNumber)) |
|
]), |
|
// digestAlgorithm |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// algorithm |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer(obj.digestAlgorithm).getBytes()), |
|
// parameters (null) |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.NULL, false, '') |
|
]) |
|
]); |
|
// authenticatedAttributes (OPTIONAL) |
|
if (obj.authenticatedAttributesAsn1) // add ASN.1 previously generated during signing |
|
rval.value.push(obj.authenticatedAttributesAsn1); |
|
// digestEncryptionAlgorithm |
|
rval.value.push($e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// algorithm |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer(obj.signatureAlgorithm).getBytes()), |
|
// parameters (null) |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.NULL, false, '') |
|
])); |
|
// encryptedDigest |
|
rval.value.push($e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OCTETSTRING, false, obj.signature)); |
|
// unauthenticatedAttributes (OPTIONAL) |
|
if (obj.unauthenticatedAttributes.length > 0) { |
|
// [1] IMPLICIT |
|
var attrsAsn1 = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.CONTEXT_SPECIFIC, 1, true, []); |
|
for(var i = 0; i < obj.unauthenticatedAttributes.length; ++i){ |
|
var attr = obj.unauthenticatedAttributes[i]; |
|
attrsAsn1.values.push($e128d865c5cf51a7$var$_attributeToAsn1(attr)); |
|
} |
|
rval.value.push(attrsAsn1); |
|
} |
|
return rval; |
|
} |
|
/** |
|
* Map a set of SignerInfo ASN.1 objects to an array of signer objects. |
|
* |
|
* @param signerInfoAsn1s an array of ASN.1 SignerInfos (i.e. SET OF). |
|
* |
|
* @return an array of signers objects. |
|
*/ function $e128d865c5cf51a7$var$_signersFromAsn1(signerInfoAsn1s) { |
|
var ret = []; |
|
for(var i = 0; i < signerInfoAsn1s.length; ++i)ret.push($e128d865c5cf51a7$var$_signerFromAsn1(signerInfoAsn1s[i])); |
|
return ret; |
|
} |
|
/** |
|
* Map an array of signer objects to ASN.1 objects. |
|
* |
|
* @param signers an array of signer objects. |
|
* |
|
* @return an array of ASN.1 SignerInfos. |
|
*/ function $e128d865c5cf51a7$var$_signersToAsn1(signers) { |
|
var ret = []; |
|
for(var i = 0; i < signers.length; ++i)ret.push($e128d865c5cf51a7$var$_signerToAsn1(signers[i])); |
|
return ret; |
|
} |
|
/** |
|
* Convert an attribute object to an ASN.1 Attribute. |
|
* |
|
* @param attr the attribute object. |
|
* |
|
* @return the ASN.1 Attribute. |
|
*/ function $e128d865c5cf51a7$var$_attributeToAsn1(attr) { |
|
var value; |
|
// TODO: generalize to support more attributes |
|
if (attr.type === $iGlOy.pki.oids.contentType) value = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer(attr.value).getBytes()); |
|
else if (attr.type === $iGlOy.pki.oids.messageDigest) value = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OCTETSTRING, false, attr.value.bytes()); |
|
else if (attr.type === $iGlOy.pki.oids.signingTime) { |
|
/* Note per RFC 2985: Dates between 1 January 1950 and 31 December 2049 |
|
(inclusive) MUST be encoded as UTCTime. Any dates with year values |
|
before 1950 or after 2049 MUST be encoded as GeneralizedTime. [Further,] |
|
UTCTime values MUST be expressed in Greenwich Mean Time (Zulu) and MUST |
|
include seconds (i.e., times are YYMMDDHHMMSSZ), even where the |
|
number of seconds is zero. Midnight (GMT) must be represented as |
|
"YYMMDD000000Z". */ // TODO: make these module-level constants |
|
var jan_1_1950 = new Date('1950-01-01T00:00:00Z'); |
|
var jan_1_2050 = new Date('2050-01-01T00:00:00Z'); |
|
var date = attr.value; |
|
if (typeof date === 'string') { |
|
// try to parse date |
|
var timestamp = Date.parse(date); |
|
if (!isNaN(timestamp)) date = new Date(timestamp); |
|
else if (date.length === 13) // YYMMDDHHMMSSZ (13 chars for UTCTime) |
|
date = $e128d865c5cf51a7$var$asn1.utcTimeToDate(date); |
|
else // assume generalized time |
|
date = $e128d865c5cf51a7$var$asn1.generalizedTimeToDate(date); |
|
} |
|
if (date >= jan_1_1950 && date < jan_1_2050) value = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.UTCTIME, false, $e128d865c5cf51a7$var$asn1.dateToUtcTime(date)); |
|
else value = $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.GENERALIZEDTIME, false, $e128d865c5cf51a7$var$asn1.dateToGeneralizedTime(date)); |
|
} |
|
// TODO: expose as common API call |
|
// create a RelativeDistinguishedName set |
|
// each value in the set is an AttributeTypeAndValue first |
|
// containing the type (an OID) and second the value |
|
return $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// AttributeType |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer(attr.type).getBytes()), |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SET, true, [ |
|
// AttributeValue |
|
value |
|
]) |
|
]); |
|
} |
|
/** |
|
* Map messages encrypted content to ASN.1 objects. |
|
* |
|
* @param ec The encryptedContent object of the message. |
|
* |
|
* @return ASN.1 representation of the encryptedContent object (SEQUENCE). |
|
*/ function $e128d865c5cf51a7$var$_encryptedContentToAsn1(ec) { |
|
return [ |
|
// ContentType, always Data for the moment |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer($iGlOy.pki.oids.data).getBytes()), |
|
// ContentEncryptionAlgorithmIdentifier |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.SEQUENCE, true, [ |
|
// Algorithm |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OID, false, $e128d865c5cf51a7$var$asn1.oidToDer(ec.algorithm).getBytes()), |
|
// Parameters (IV) |
|
!ec.parameter ? undefined : $e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OCTETSTRING, false, ec.parameter.getBytes()) |
|
]), |
|
// [0] EncryptedContent |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.CONTEXT_SPECIFIC, 0, true, [ |
|
$e128d865c5cf51a7$var$asn1.create($e128d865c5cf51a7$var$asn1.Class.UNIVERSAL, $e128d865c5cf51a7$var$asn1.Type.OCTETSTRING, false, ec.content.getBytes()) |
|
]) |
|
]; |
|
} |
|
/** |
|
* Reads the "common part" of an PKCS#7 content block (in ASN.1 format) |
|
* |
|
* This function reads the "common part" of the PKCS#7 content blocks |
|
* EncryptedData and EnvelopedData, i.e. version number and symmetrically |
|
* encrypted content block. |
|
* |
|
* The result of the ASN.1 validate and capture process is returned |
|
* to allow the caller to extract further data, e.g. the list of recipients |
|
* in case of a EnvelopedData object. |
|
* |
|
* @param msg the PKCS#7 object to read the data to. |
|
* @param obj the ASN.1 representation of the content block. |
|
* @param validator the ASN.1 structure validator object to use. |
|
* |
|
* @return the value map captured by validator object. |
|
*/ function $e128d865c5cf51a7$var$_fromAsn1(msg, obj, validator) { |
|
var capture = { |
|
}; |
|
var errors = []; |
|
if (!$e128d865c5cf51a7$var$asn1.validate(obj, validator, capture, errors)) { |
|
var error = new Error("Cannot read PKCS#7 message. ASN.1 object is not a supported PKCS#7 message."); |
|
error.errors = error; |
|
throw error; |
|
} |
|
// Check contentType, so far we only support (raw) Data. |
|
var contentType = $e128d865c5cf51a7$var$asn1.derToOid(capture.contentType); |
|
if (contentType !== $iGlOy.pki.oids.data) throw new Error("Unsupported PKCS#7 message. Only wrapped ContentType Data supported."); |
|
if (capture.encryptedContent) { |
|
var content = ''; |
|
if ($iGlOy.util.isArray(capture.encryptedContent)) for(var i = 0; i < capture.encryptedContent.length; ++i){ |
|
if (capture.encryptedContent[i].type !== $e128d865c5cf51a7$var$asn1.Type.OCTETSTRING) throw new Error("Malformed PKCS#7 message, expecting encrypted content constructed of only OCTET STRING objects."); |
|
content += capture.encryptedContent[i].value; |
|
} |
|
else content = capture.encryptedContent; |
|
msg.encryptedContent = { |
|
algorithm: $e128d865c5cf51a7$var$asn1.derToOid(capture.encAlgorithm), |
|
parameter: $iGlOy.util.createBuffer(capture.encParameter.value), |
|
content: $iGlOy.util.createBuffer(content) |
|
}; |
|
} |
|
if (capture.content) { |
|
var content = ''; |
|
if ($iGlOy.util.isArray(capture.content)) for(var i = 0; i < capture.content.length; ++i){ |
|
if (capture.content[i].type !== $e128d865c5cf51a7$var$asn1.Type.OCTETSTRING) throw new Error("Malformed PKCS#7 message, expecting content constructed of only OCTET STRING objects."); |
|
content += capture.content[i].value; |
|
} |
|
else content = capture.content; |
|
msg.content = $iGlOy.util.createBuffer(content); |
|
} |
|
msg.version = capture.version.charCodeAt(0); |
|
msg.rawCapture = capture; |
|
return capture; |
|
} |
|
/** |
|
* Decrypt the symmetrically encrypted content block of the PKCS#7 message. |
|
* |
|
* Decryption is skipped in case the PKCS#7 message object already has a |
|
* (decrypted) content attribute. The algorithm, key and cipher parameters |
|
* (probably the iv) are taken from the encryptedContent attribute of the |
|
* message object. |
|
* |
|
* @param The PKCS#7 message object. |
|
*/ function $e128d865c5cf51a7$var$_decryptContent(msg) { |
|
if (msg.encryptedContent.key === undefined) throw new Error('Symmetric key not available.'); |
|
if (msg.content === undefined) { |
|
var ciph; |
|
switch(msg.encryptedContent.algorithm){ |
|
case $iGlOy.pki.oids['aes128-CBC']: |
|
case $iGlOy.pki.oids['aes192-CBC']: |
|
case $iGlOy.pki.oids['aes256-CBC']: |
|
ciph = $iGlOy.aes.createDecryptionCipher(msg.encryptedContent.key); |
|
break; |
|
case $iGlOy.pki.oids['desCBC']: |
|
case $iGlOy.pki.oids['des-EDE3-CBC']: |
|
ciph = $iGlOy.des.createDecryptionCipher(msg.encryptedContent.key); |
|
break; |
|
default: |
|
throw new Error('Unsupported symmetric cipher, OID ' + msg.encryptedContent.algorithm); |
|
} |
|
ciph.start(msg.encryptedContent.parameter); |
|
ciph.update(msg.encryptedContent.content); |
|
if (!ciph.finish()) throw new Error('Symmetric decryption failed.'); |
|
msg.content = ciph.output; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var $85c6486b1bf8bee8$exports = {}; |
|
|
|
var $iGlOy = parcelRequire("iGlOy"); |
|
|
|
|
|
|
|
|
|
|
|
var $85c6486b1bf8bee8$var$ssh = $85c6486b1bf8bee8$exports = $iGlOy.ssh = $iGlOy.ssh || { |
|
}; |
|
/** |
|
* Encodes (and optionally encrypts) a private RSA key as a Putty PPK file. |
|
* |
|
* @param privateKey the key. |
|
* @param passphrase a passphrase to protect the key (falsy for no encryption). |
|
* @param comment a comment to include in the key file. |
|
* |
|
* @return the PPK file as a string. |
|
*/ $85c6486b1bf8bee8$var$ssh.privateKeyToPutty = function(privateKey, passphrase, comment) { |
|
comment = comment || ''; |
|
passphrase = passphrase || ''; |
|
var algorithm = 'ssh-rsa'; |
|
var encryptionAlgorithm = passphrase === '' ? 'none' : 'aes256-cbc'; |
|
var ppk = 'PuTTY-User-Key-File-2: ' + algorithm + '\r\n'; |
|
ppk += 'Encryption: ' + encryptionAlgorithm + '\r\n'; |
|
ppk += 'Comment: ' + comment + '\r\n'; |
|
// public key into buffer for ppk |
|
var pubbuffer = $iGlOy.util.createBuffer(); |
|
$85c6486b1bf8bee8$var$_addStringToBuffer(pubbuffer, algorithm); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(pubbuffer, privateKey.e); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(pubbuffer, privateKey.n); |
|
// write public key |
|
var pub = $iGlOy.util.encode64(pubbuffer.bytes(), 64); |
|
var length = Math.floor(pub.length / 66) + 1; // 66 = 64 + \r\n |
|
ppk += 'Public-Lines: ' + length + '\r\n'; |
|
ppk += pub; |
|
// private key into a buffer |
|
var privbuffer = $iGlOy.util.createBuffer(); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(privbuffer, privateKey.d); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(privbuffer, privateKey.p); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(privbuffer, privateKey.q); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(privbuffer, privateKey.qInv); |
|
// optionally encrypt the private key |
|
var priv; |
|
if (!passphrase) // use the unencrypted buffer |
|
priv = $iGlOy.util.encode64(privbuffer.bytes(), 64); |
|
else { |
|
// encrypt RSA key using passphrase |
|
var encLen = privbuffer.length() + 16 - 1; |
|
encLen -= encLen % 16; |
|
// pad private key with sha1-d data -- needs to be a multiple of 16 |
|
var padding = $85c6486b1bf8bee8$var$_sha1(privbuffer.bytes()); |
|
padding.truncate(padding.length() - encLen + privbuffer.length()); |
|
privbuffer.putBuffer(padding); |
|
var aeskey = $iGlOy.util.createBuffer(); |
|
aeskey.putBuffer($85c6486b1bf8bee8$var$_sha1('\x00\x00\x00\x00', passphrase)); |
|
aeskey.putBuffer($85c6486b1bf8bee8$var$_sha1('\x00\x00\x00\x01', passphrase)); |
|
// encrypt some bytes using CBC mode |
|
// key is 40 bytes, so truncate *by* 8 bytes |
|
var cipher = $iGlOy.aes.createEncryptionCipher(aeskey.truncate(8), 'CBC'); |
|
cipher.start($iGlOy.util.createBuffer().fillWithByte(0, 16)); |
|
cipher.update(privbuffer.copy()); |
|
cipher.finish(); |
|
var encrypted = cipher.output; |
|
// Note: this appears to differ from Putty -- is forge wrong, or putty? |
|
// due to padding we finish as an exact multiple of 16 |
|
encrypted.truncate(16); // all padding |
|
priv = $iGlOy.util.encode64(encrypted.bytes(), 64); |
|
} |
|
// output private key |
|
length = Math.floor(priv.length / 66) + 1; // 64 + \r\n |
|
ppk += '\r\nPrivate-Lines: ' + length + '\r\n'; |
|
ppk += priv; |
|
// MAC |
|
var mackey = $85c6486b1bf8bee8$var$_sha1('putty-private-key-file-mac-key', passphrase); |
|
var macbuffer = $iGlOy.util.createBuffer(); |
|
$85c6486b1bf8bee8$var$_addStringToBuffer(macbuffer, algorithm); |
|
$85c6486b1bf8bee8$var$_addStringToBuffer(macbuffer, encryptionAlgorithm); |
|
$85c6486b1bf8bee8$var$_addStringToBuffer(macbuffer, comment); |
|
macbuffer.putInt32(pubbuffer.length()); |
|
macbuffer.putBuffer(pubbuffer); |
|
macbuffer.putInt32(privbuffer.length()); |
|
macbuffer.putBuffer(privbuffer); |
|
var hmac = $iGlOy.hmac.create(); |
|
hmac.start('sha1', mackey); |
|
hmac.update(macbuffer.bytes()); |
|
ppk += '\r\nPrivate-MAC: ' + hmac.digest().toHex() + '\r\n'; |
|
return ppk; |
|
}; |
|
/** |
|
* Encodes a public RSA key as an OpenSSH file. |
|
* |
|
* @param key the key. |
|
* @param comment a comment. |
|
* |
|
* @return the public key in OpenSSH format. |
|
*/ $85c6486b1bf8bee8$var$ssh.publicKeyToOpenSSH = function(key, comment) { |
|
var type = 'ssh-rsa'; |
|
comment = comment || ''; |
|
var buffer = $iGlOy.util.createBuffer(); |
|
$85c6486b1bf8bee8$var$_addStringToBuffer(buffer, type); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(buffer, key.e); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(buffer, key.n); |
|
return type + ' ' + $iGlOy.util.encode64(buffer.bytes()) + ' ' + comment; |
|
}; |
|
/** |
|
* Encodes a private RSA key as an OpenSSH file. |
|
* |
|
* @param key the key. |
|
* @param passphrase a passphrase to protect the key (falsy for no encryption). |
|
* |
|
* @return the public key in OpenSSH format. |
|
*/ $85c6486b1bf8bee8$var$ssh.privateKeyToOpenSSH = function(privateKey, passphrase) { |
|
if (!passphrase) return $iGlOy.pki.privateKeyToPem(privateKey); |
|
// OpenSSH private key is just a legacy format, it seems |
|
return $iGlOy.pki.encryptRsaPrivateKey(privateKey, passphrase, { |
|
legacy: true, |
|
algorithm: 'aes128' |
|
}); |
|
}; |
|
/** |
|
* Gets the SSH fingerprint for the given public key. |
|
* |
|
* @param options the options to use. |
|
* [md] the message digest object to use (defaults to forge.md.md5). |
|
* [encoding] an alternative output encoding, such as 'hex' |
|
* (defaults to none, outputs a byte buffer). |
|
* [delimiter] the delimiter to use between bytes for 'hex' encoded |
|
* output, eg: ':' (defaults to none). |
|
* |
|
* @return the fingerprint as a byte buffer or other encoding based on options. |
|
*/ $85c6486b1bf8bee8$var$ssh.getPublicKeyFingerprint = function(key, options) { |
|
options = options || { |
|
}; |
|
var md = options.md || $iGlOy.md.md5.create(); |
|
var type = 'ssh-rsa'; |
|
var buffer = $iGlOy.util.createBuffer(); |
|
$85c6486b1bf8bee8$var$_addStringToBuffer(buffer, type); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(buffer, key.e); |
|
$85c6486b1bf8bee8$var$_addBigIntegerToBuffer(buffer, key.n); |
|
// hash public key bytes |
|
md.start(); |
|
md.update(buffer.getBytes()); |
|
var digest = md.digest(); |
|
if (options.encoding === 'hex') { |
|
var hex = digest.toHex(); |
|
if (options.delimiter) return hex.match(/.{2}/g).join(options.delimiter); |
|
return hex; |
|
} else if (options.encoding === 'binary') return digest.getBytes(); |
|
else if (options.encoding) throw new Error('Unknown encoding "' + options.encoding + '".'); |
|
return digest; |
|
}; |
|
/** |
|
* Adds len(val) then val to a buffer. |
|
* |
|
* @param buffer the buffer to add to. |
|
* @param val a big integer. |
|
*/ function $85c6486b1bf8bee8$var$_addBigIntegerToBuffer(buffer, val) { |
|
var hexVal = val.toString(16); |
|
// ensure 2s complement +ve |
|
if (hexVal[0] >= '8') hexVal = '00' + hexVal; |
|
var bytes = $iGlOy.util.hexToBytes(hexVal); |
|
buffer.putInt32(bytes.length); |
|
buffer.putBytes(bytes); |
|
} |
|
/** |
|
* Adds len(val) then val to a buffer. |
|
* |
|
* @param buffer the buffer to add to. |
|
* @param val a string. |
|
*/ function $85c6486b1bf8bee8$var$_addStringToBuffer(buffer, val) { |
|
buffer.putInt32(val.length); |
|
buffer.putString(val); |
|
} |
|
/** |
|
* Hashes the arguments into one value using SHA-1. |
|
* |
|
* @return the sha1 hash of the provided arguments. |
|
*/ function $85c6486b1bf8bee8$var$_sha1() { |
|
var sha = $iGlOy.md.sha1.create(); |
|
var num = arguments.length; |
|
for(var i = 0; i < num; ++i)sha.update(arguments[i]); |
|
return sha.digest(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function $c6cbdbdbaf0fafc1$export$2e2bcd8739ae039(fs, cacheDir, host) { |
|
let certDirectory = cacheDir; |
|
const privateKeyPath = ($parcel$interopDefault($8C1kk$path)).join(certDirectory, 'private.pem'); |
|
const certPath = ($parcel$interopDefault($8C1kk$path)).join(certDirectory, 'primary.crt'); |
|
const cachedKey = await fs.exists(privateKeyPath) && await fs.readFile(privateKeyPath); |
|
const cachedCert = await fs.exists(certPath) && await fs.readFile(certPath); |
|
if (cachedKey && cachedCert) return { |
|
key: cachedKey, |
|
cert: cachedCert |
|
}; |
|
($parcel$interopDefault($8C1kk$parcellogger)).progress('Generating SSL Certificate...'); |
|
const pki = (/*@__PURE__*/$parcel$interopDefault($99e85628b30fe009$exports)).pki; |
|
const keys = pki.rsa.generateKeyPair(2048); |
|
const cert = pki.createCertificate(); |
|
cert.publicKey = keys.publicKey; |
|
cert.serialNumber = Date.now().toString(); |
|
cert.validity.notBefore = new Date(); |
|
cert.validity.notAfter = new Date(); |
|
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); |
|
const attrs = [ |
|
{ |
|
name: 'commonName', |
|
value: 'parceljs.org' |
|
}, |
|
{ |
|
name: 'countryName', |
|
value: 'US' |
|
}, |
|
{ |
|
shortName: 'ST', |
|
value: 'Virginia' |
|
}, |
|
{ |
|
name: 'localityName', |
|
value: 'Blacksburg' |
|
}, |
|
{ |
|
name: 'organizationName', |
|
value: 'parcelBundler' |
|
}, |
|
{ |
|
shortName: 'OU', |
|
value: 'Test' |
|
} |
|
]; |
|
let altNames = [ |
|
{ |
|
type: 2, |
|
// DNS |
|
value: 'localhost' |
|
}, |
|
{ |
|
type: 7, |
|
// IP |
|
ip: '127.0.0.1' |
|
} |
|
]; |
|
if (host) altNames.push({ |
|
type: 2, |
|
// DNS |
|
value: host |
|
}); |
|
cert.setSubject(attrs); |
|
cert.setIssuer(attrs); |
|
cert.setExtensions([ |
|
{ |
|
name: 'basicConstraints', |
|
cA: false |
|
}, |
|
{ |
|
name: 'keyUsage', |
|
keyCertSign: true, |
|
digitalSignature: true, |
|
nonRepudiation: true, |
|
keyEncipherment: true, |
|
dataEncipherment: true |
|
}, |
|
{ |
|
name: 'extKeyUsage', |
|
serverAuth: true, |
|
clientAuth: true, |
|
codeSigning: true, |
|
emailProtection: true, |
|
timeStamping: true |
|
}, |
|
{ |
|
name: 'nsCertType', |
|
client: true, |
|
server: true, |
|
email: true, |
|
objsign: true, |
|
sslCA: true, |
|
emailCA: true, |
|
objCA: true |
|
}, |
|
{ |
|
name: 'subjectAltName', |
|
altNames: altNames |
|
}, |
|
{ |
|
name: 'subjectKeyIdentifier' |
|
} |
|
]); |
|
cert.sign(keys.privateKey, (/*@__PURE__*/$parcel$interopDefault($99e85628b30fe009$exports)).md.sha256.create()); |
|
const privPem = pki.privateKeyToPem(keys.privateKey); |
|
const certPem = pki.certificateToPem(cert); |
|
await fs.mkdirp(certDirectory); |
|
await fs.writeFile(privateKeyPath, privPem); |
|
await fs.writeFile(certPath, certPem); |
|
return { |
|
key: privPem, |
|
cert: certPem |
|
}; |
|
} |
|
|
|
|
|
async function $186980c178984fd2$export$2e2bcd8739ae039(fs, options) { |
|
try { |
|
let cert = await fs.readFile(options.cert); |
|
let key = await fs.readFile(options.key); |
|
return { |
|
key: key, |
|
cert: cert |
|
}; |
|
} catch (err) { |
|
throw new Error('Certificate and/or key not found'); |
|
} |
|
} |
|
|
|
|
|
var $5aee5a8e09e874bf$exports = {}; |
|
var $49a059b76f641953$exports = {}; |
|
/*! |
|
* is-extglob <https://github.com/jonschlinkert/is-extglob> |
|
* |
|
* Copyright (c) 2014-2016, Jon Schlinkert. |
|
* Licensed under the MIT License. |
|
*/ $49a059b76f641953$exports = function isExtglob(str) { |
|
if (typeof str !== 'string' || str === '') return false; |
|
var match; |
|
while(match = /(\\).|([@?!+*]\(.*\))/g.exec(str)){ |
|
if (match[2]) return true; |
|
str = str.slice(match.index + match[0].length); |
|
} |
|
return false; |
|
}; |
|
|
|
|
|
var $5aee5a8e09e874bf$var$chars = { |
|
'{': '}', |
|
'(': ')', |
|
'[': ']' |
|
}; |
|
var $5aee5a8e09e874bf$var$strictCheck = function(str) { |
|
if (str[0] === '!') return true; |
|
var index = 0; |
|
var pipeIndex = -2; |
|
var closeSquareIndex = -2; |
|
var closeCurlyIndex = -2; |
|
var closeParenIndex = -2; |
|
var backSlashIndex = -2; |
|
while(index < str.length){ |
|
if (str[index] === '*') return true; |
|
if (str[index + 1] === '?' && /[\].+)]/.test(str[index])) return true; |
|
if (closeSquareIndex !== -1 && str[index] === '[' && str[index + 1] !== ']') { |
|
if (closeSquareIndex < index) closeSquareIndex = str.indexOf(']', index); |
|
if (closeSquareIndex > index) { |
|
if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) return true; |
|
backSlashIndex = str.indexOf('\\', index); |
|
if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) return true; |
|
} |
|
} |
|
if (closeCurlyIndex !== -1 && str[index] === '{' && str[index + 1] !== '}') { |
|
closeCurlyIndex = str.indexOf('}', index); |
|
if (closeCurlyIndex > index) { |
|
backSlashIndex = str.indexOf('\\', index); |
|
if (backSlashIndex === -1 || backSlashIndex > closeCurlyIndex) return true; |
|
} |
|
} |
|
if (closeParenIndex !== -1 && str[index] === '(' && str[index + 1] === '?' && /[:!=]/.test(str[index + 2]) && str[index + 3] !== ')') { |
|
closeParenIndex = str.indexOf(')', index); |
|
if (closeParenIndex > index) { |
|
backSlashIndex = str.indexOf('\\', index); |
|
if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) return true; |
|
} |
|
} |
|
if (pipeIndex !== -1 && str[index] === '(' && str[index + 1] !== '|') { |
|
if (pipeIndex < index) pipeIndex = str.indexOf('|', index); |
|
if (pipeIndex !== -1 && str[pipeIndex + 1] !== ')') { |
|
closeParenIndex = str.indexOf(')', pipeIndex); |
|
if (closeParenIndex > pipeIndex) { |
|
backSlashIndex = str.indexOf('\\', pipeIndex); |
|
if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) return true; |
|
} |
|
} |
|
} |
|
if (str[index] === '\\') { |
|
var open = str[index + 1]; |
|
index += 2; |
|
var close = $5aee5a8e09e874bf$var$chars[open]; |
|
if (close) { |
|
var n = str.indexOf(close, index); |
|
if (n !== -1) index = n + 1; |
|
} |
|
if (str[index] === '!') return true; |
|
} else index++; |
|
} |
|
return false; |
|
}; |
|
var $5aee5a8e09e874bf$var$relaxedCheck = function(str) { |
|
if (str[0] === '!') return true; |
|
var index = 0; |
|
while(index < str.length){ |
|
if (/[*?{}()[\]]/.test(str[index])) return true; |
|
if (str[index] === '\\') { |
|
var open = str[index + 1]; |
|
index += 2; |
|
var close = $5aee5a8e09e874bf$var$chars[open]; |
|
if (close) { |
|
var n = str.indexOf(close, index); |
|
if (n !== -1) index = n + 1; |
|
} |
|
if (str[index] === '!') return true; |
|
} else index++; |
|
} |
|
return false; |
|
}; |
|
$5aee5a8e09e874bf$exports = function isGlob(str, options) { |
|
if (typeof str !== 'string' || str === '') return false; |
|
if ($49a059b76f641953$exports(str)) return true; |
|
var check = $5aee5a8e09e874bf$var$strictCheck; |
|
// optionally relax check |
|
if (options && options.strict === false) check = $5aee5a8e09e874bf$var$relaxedCheck; |
|
return check(str); |
|
}; |
|
|
|
|
|
var $b57e78be4f7a2622$exports = {}; |
|
"use strict"; |
|
var $d436392a45e5b9b4$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($d436392a45e5b9b4$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $1b5b082adfcf5f99$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($1b5b082adfcf5f99$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $23d0e316ca6ff843$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($23d0e316ca6ff843$exports, "__esModule", { |
|
value: true |
|
}); |
|
function $23d0e316ca6ff843$var$flatten(items) { |
|
return items.reduce((collection, item)=>[].concat(collection, item) |
|
, []); |
|
} |
|
$23d0e316ca6ff843$exports.flatten = $23d0e316ca6ff843$var$flatten; |
|
|
|
|
|
$1b5b082adfcf5f99$exports.array = $23d0e316ca6ff843$exports; |
|
var $6eea3630cce07c06$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($6eea3630cce07c06$exports, "__esModule", { |
|
value: true |
|
}); |
|
function $6eea3630cce07c06$var$isEnoentCodeError(error) { |
|
return error.code === 'ENOENT'; |
|
} |
|
$6eea3630cce07c06$exports.isEnoentCodeError = $6eea3630cce07c06$var$isEnoentCodeError; |
|
|
|
|
|
$1b5b082adfcf5f99$exports.errno = $6eea3630cce07c06$exports; |
|
var $e88efb70f4f04277$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($e88efb70f4f04277$exports, "__esModule", { |
|
value: true |
|
}); |
|
class $e88efb70f4f04277$var$DirentFromStats { |
|
constructor(name, stats){ |
|
this.name = name; |
|
this.isBlockDevice = stats.isBlockDevice.bind(stats); |
|
this.isCharacterDevice = stats.isCharacterDevice.bind(stats); |
|
this.isDirectory = stats.isDirectory.bind(stats); |
|
this.isFIFO = stats.isFIFO.bind(stats); |
|
this.isFile = stats.isFile.bind(stats); |
|
this.isSocket = stats.isSocket.bind(stats); |
|
this.isSymbolicLink = stats.isSymbolicLink.bind(stats); |
|
} |
|
} |
|
function $e88efb70f4f04277$var$createDirentFromStats(name, stats) { |
|
return new $e88efb70f4f04277$var$DirentFromStats(name, stats); |
|
} |
|
$e88efb70f4f04277$exports.createDirentFromStats = $e88efb70f4f04277$var$createDirentFromStats; |
|
|
|
|
|
$1b5b082adfcf5f99$exports.fs = $e88efb70f4f04277$exports; |
|
var $01c89d3b8f966493$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($01c89d3b8f966493$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
const $01c89d3b8f966493$var$UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([*?|(){}[\]]|^!|[@+!](?=\())/g; |
|
/**
|
|
* Designed to work only with simple paths: `dir\\file`.
|
|
*/ function $01c89d3b8f966493$var$unixify(filepath) { |
|
return filepath.replace(/\\/g, '/'); |
|
} |
|
$01c89d3b8f966493$exports.unixify = $01c89d3b8f966493$var$unixify; |
|
function $01c89d3b8f966493$var$makeAbsolute(cwd, filepath) { |
|
return $8C1kk$path.resolve(cwd, filepath); |
|
} |
|
$01c89d3b8f966493$exports.makeAbsolute = $01c89d3b8f966493$var$makeAbsolute; |
|
function $01c89d3b8f966493$var$escape(pattern) { |
|
return pattern.replace($01c89d3b8f966493$var$UNESCAPED_GLOB_SYMBOLS_RE, '\\$2'); |
|
} |
|
$01c89d3b8f966493$exports.escape = $01c89d3b8f966493$var$escape; |
|
|
|
|
|
$1b5b082adfcf5f99$exports.path = $01c89d3b8f966493$exports; |
|
var $e1fc146aea519a53$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($e1fc146aea519a53$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
var $99a21639ca3a03fc$exports = {}; |
|
'use strict'; |
|
|
|
|
|
var $99a21639ca3a03fc$var$pathPosixDirname = $8C1kk$path.posix.dirname; |
|
|
|
var $99a21639ca3a03fc$var$isWin32 = $8C1kk$os.platform() === 'win32'; |
|
var $99a21639ca3a03fc$var$slash = '/'; |
|
var $99a21639ca3a03fc$var$backslash = /\\/g; |
|
var $99a21639ca3a03fc$var$enclosure = /[\{\[].*[\}\]]$/; |
|
var $99a21639ca3a03fc$var$globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; |
|
var $99a21639ca3a03fc$var$escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; |
|
/** |
|
* @param {string} str |
|
* @param {Object} opts |
|
* @param {boolean} [opts.flipBackslashes=true] |
|
* @returns {string} |
|
*/ $99a21639ca3a03fc$exports = function globParent(str, opts) { |
|
var options = Object.assign({ |
|
flipBackslashes: true |
|
}, opts); |
|
// flip windows path separators |
|
if (options.flipBackslashes && $99a21639ca3a03fc$var$isWin32 && str.indexOf($99a21639ca3a03fc$var$slash) < 0) str = str.replace($99a21639ca3a03fc$var$backslash, $99a21639ca3a03fc$var$slash); |
|
// special case for strings ending in enclosure containing path separator |
|
if ($99a21639ca3a03fc$var$enclosure.test(str)) str += $99a21639ca3a03fc$var$slash; |
|
// preserves full path in case of trailing path separator |
|
str += 'a'; |
|
// remove path parts that are globby |
|
do str = $99a21639ca3a03fc$var$pathPosixDirname(str); |
|
while ($5aee5a8e09e874bf$exports(str) || $99a21639ca3a03fc$var$globby.test(str)) |
|
// remove escape chars and return result |
|
return str.replace($99a21639ca3a03fc$var$escaped, '$1'); |
|
}; |
|
|
|
|
|
var $fec3b4fc54d3756a$exports = {}; |
|
'use strict'; |
|
|
|
var $fec07f13db1e462a$exports = {}; |
|
'use strict'; |
|
var $156a1a36db86ccbd$exports = {}; |
|
'use strict'; |
|
var $d0a07df29ef1b0fa$export$a287f47fed4544b8; |
|
/** |
|
* Find a node of the given type |
|
*/ var $d0a07df29ef1b0fa$export$71aa6c912b956294; |
|
/** |
|
* Find a node of the given type |
|
*/ var $d0a07df29ef1b0fa$export$fbadac39f36b1e16; |
|
/** |
|
* Escape the given node with '\\' before node.value |
|
*/ var $d0a07df29ef1b0fa$export$92e39b1e2c1e6e56; |
|
/** |
|
* Returns true if the given brace node should be enclosed in literal braces |
|
*/ var $d0a07df29ef1b0fa$export$ea0f721b77fd5acc; |
|
/** |
|
* Returns true if a brace node is invalid. |
|
*/ var $d0a07df29ef1b0fa$export$25a78c310c11373f; |
|
/** |
|
* Returns true if a node is an open or close node |
|
*/ var $d0a07df29ef1b0fa$export$582fc44003e67ec6; |
|
/** |
|
* Reduce an array of text nodes. |
|
*/ var $d0a07df29ef1b0fa$export$533b26079ad0b4b; |
|
/** |
|
* Flatten an array |
|
*/ var $d0a07df29ef1b0fa$export$bffa455ba8c619a6; |
|
'use strict'; |
|
$d0a07df29ef1b0fa$export$a287f47fed4544b8 = (num)=>{ |
|
if (typeof num === 'number') return Number.isInteger(num); |
|
if (typeof num === 'string' && num.trim() !== '') return Number.isInteger(Number(num)); |
|
return false; |
|
}; |
|
$d0a07df29ef1b0fa$export$71aa6c912b956294 = (node1, type)=>node1.nodes.find((node)=>node.type === type |
|
) |
|
; |
|
$d0a07df29ef1b0fa$export$fbadac39f36b1e16 = (min, max, step = 1, limit)=>{ |
|
if (limit === false) return false; |
|
if (!$d0a07df29ef1b0fa$export$a287f47fed4544b8(min) || !$d0a07df29ef1b0fa$export$a287f47fed4544b8(max)) return false; |
|
return (Number(max) - Number(min)) / Number(step) >= limit; |
|
}; |
|
$d0a07df29ef1b0fa$export$92e39b1e2c1e6e56 = (block, n = 0, type)=>{ |
|
let node = block.nodes[n]; |
|
if (!node) return; |
|
if (type && node.type === type || node.type === 'open' || node.type === 'close') { |
|
if (node.escaped !== true) { |
|
node.value = '\\' + node.value; |
|
node.escaped = true; |
|
} |
|
} |
|
}; |
|
$d0a07df29ef1b0fa$export$ea0f721b77fd5acc = (node)=>{ |
|
if (node.type !== 'brace') return false; |
|
if (node.commas >> 0 + node.ranges >> 0 === 0) { |
|
node.invalid = true; |
|
return true; |
|
} |
|
return false; |
|
}; |
|
$d0a07df29ef1b0fa$export$25a78c310c11373f = (block)=>{ |
|
if (block.type !== 'brace') return false; |
|
if (block.invalid === true || block.dollar) return true; |
|
if (block.commas >> 0 + block.ranges >> 0 === 0) { |
|
block.invalid = true; |
|
return true; |
|
} |
|
if (block.open !== true || block.close !== true) { |
|
block.invalid = true; |
|
return true; |
|
} |
|
return false; |
|
}; |
|
$d0a07df29ef1b0fa$export$582fc44003e67ec6 = (node)=>{ |
|
if (node.type === 'open' || node.type === 'close') return true; |
|
return node.open === true || node.close === true; |
|
}; |
|
$d0a07df29ef1b0fa$export$533b26079ad0b4b = (nodes)=>nodes.reduce((acc, node)=>{ |
|
if (node.type === 'text') acc.push(node.value); |
|
if (node.type === 'range') node.type = 'text'; |
|
return acc; |
|
}, []) |
|
; |
|
$d0a07df29ef1b0fa$export$bffa455ba8c619a6 = (...args)=>{ |
|
const result = []; |
|
const flat = (arr)=>{ |
|
for(let i = 0; i < arr.length; i++){ |
|
let ele = arr[i]; |
|
Array.isArray(ele) ? flat(ele, result) : ele !== void 0 && result.push(ele); |
|
} |
|
return result; |
|
}; |
|
flat(args); |
|
return result; |
|
}; |
|
|
|
|
|
$156a1a36db86ccbd$exports = (ast, options = { |
|
})=>{ |
|
let stringify = (node, parent = { |
|
})=>{ |
|
let invalidBlock = options.escapeInvalid && $d0a07df29ef1b0fa$export$25a78c310c11373f(parent); |
|
let invalidNode = node.invalid === true && options.escapeInvalid === true; |
|
let output = ''; |
|
if (node.value) { |
|
if ((invalidBlock || invalidNode) && $d0a07df29ef1b0fa$export$582fc44003e67ec6(node)) return '\\' + node.value; |
|
return node.value; |
|
} |
|
if (node.value) return node.value; |
|
if (node.nodes) for (let child of node.nodes)output += stringify(child); |
|
return output; |
|
}; |
|
return stringify(ast); |
|
}; |
|
|
|
|
|
var $c82bd34878224845$exports = {}; |
|
'use strict'; |
|
var $834b1889a72cf074$exports = {}; |
|
/*! |
|
* fill-range <https://github.com/jonschlinkert/fill-range> |
|
* |
|
* Copyright (c) 2014-present, Jon Schlinkert. |
|
* Licensed under the MIT License. |
|
*/ 'use strict'; |
|
|
|
var $07628d57aabb0c0b$exports = {}; |
|
/*! |
|
* to-regex-range <https://github.com/micromatch/to-regex-range> |
|
* |
|
* Copyright (c) 2015-present, Jon Schlinkert. |
|
* Released under the MIT License. |
|
*/ 'use strict'; |
|
var $547fcdd6252500ec$exports = {}; |
|
/*! |
|
* is-number <https://github.com/jonschlinkert/is-number> |
|
* |
|
* Copyright (c) 2014-present, Jon Schlinkert. |
|
* Released under the MIT License. |
|
*/ 'use strict'; |
|
$547fcdd6252500ec$exports = function(num) { |
|
if (typeof num === 'number') return num - num === 0; |
|
if (typeof num === 'string' && num.trim() !== '') return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); |
|
return false; |
|
}; |
|
|
|
|
|
const $07628d57aabb0c0b$var$toRegexRange = (min, max, options)=>{ |
|
if ($547fcdd6252500ec$exports(min) === false) throw new TypeError('toRegexRange: expected the first argument to be a number'); |
|
if (max === void 0 || min === max) return String(min); |
|
if ($547fcdd6252500ec$exports(max) === false) throw new TypeError('toRegexRange: expected the second argument to be a number.'); |
|
let opts = { |
|
relaxZeros: true, |
|
...options |
|
}; |
|
if (typeof opts.strictZeros === 'boolean') opts.relaxZeros = opts.strictZeros === false; |
|
let relax = String(opts.relaxZeros); |
|
let shorthand = String(opts.shorthand); |
|
let capture = String(opts.capture); |
|
let wrap = String(opts.wrap); |
|
let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; |
|
if ($07628d57aabb0c0b$var$toRegexRange.cache.hasOwnProperty(cacheKey)) return $07628d57aabb0c0b$var$toRegexRange.cache[cacheKey].result; |
|
let a = Math.min(min, max); |
|
let b = Math.max(min, max); |
|
if (Math.abs(a - b) === 1) { |
|
let result = min + '|' + max; |
|
if (opts.capture) return `(${result})`; |
|
if (opts.wrap === false) return result; |
|
return `(?:${result})`; |
|
} |
|
let isPadded = $07628d57aabb0c0b$var$hasPadding(min) || $07628d57aabb0c0b$var$hasPadding(max); |
|
let state = { |
|
min: min, |
|
max: max, |
|
a: a, |
|
b: b |
|
}; |
|
let positives = []; |
|
let negatives = []; |
|
if (isPadded) { |
|
state.isPadded = isPadded; |
|
state.maxLen = String(state.max).length; |
|
} |
|
if (a < 0) { |
|
let newMin = b < 0 ? Math.abs(b) : 1; |
|
negatives = $07628d57aabb0c0b$var$splitToPatterns(newMin, Math.abs(a), state, opts); |
|
a = state.a = 0; |
|
} |
|
if (b >= 0) positives = $07628d57aabb0c0b$var$splitToPatterns(a, b, state, opts); |
|
state.negatives = negatives; |
|
state.positives = positives; |
|
state.result = $07628d57aabb0c0b$var$collatePatterns(negatives, positives, opts); |
|
if (opts.capture === true) state.result = `(${state.result})`; |
|
else if (opts.wrap !== false && positives.length + negatives.length > 1) state.result = `(?:${state.result})`; |
|
$07628d57aabb0c0b$var$toRegexRange.cache[cacheKey] = state; |
|
return state.result; |
|
}; |
|
function $07628d57aabb0c0b$var$collatePatterns(neg, pos, options) { |
|
let onlyNegative = $07628d57aabb0c0b$var$filterPatterns(neg, pos, '-', false, options) || []; |
|
let onlyPositive = $07628d57aabb0c0b$var$filterPatterns(pos, neg, '', false, options) || []; |
|
let intersected = $07628d57aabb0c0b$var$filterPatterns(neg, pos, '-?', true, options) || []; |
|
let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); |
|
return subpatterns.join('|'); |
|
} |
|
function $07628d57aabb0c0b$var$splitToRanges(min, max) { |
|
let nines = 1; |
|
let zeros = 1; |
|
let stop = $07628d57aabb0c0b$var$countNines(min, nines); |
|
let stops = new Set([ |
|
max |
|
]); |
|
while(min <= stop && stop <= max){ |
|
stops.add(stop); |
|
nines += 1; |
|
stop = $07628d57aabb0c0b$var$countNines(min, nines); |
|
} |
|
stop = $07628d57aabb0c0b$var$countZeros(max + 1, zeros) - 1; |
|
while(min < stop && stop <= max){ |
|
stops.add(stop); |
|
zeros += 1; |
|
stop = $07628d57aabb0c0b$var$countZeros(max + 1, zeros) - 1; |
|
} |
|
stops = [ |
|
...stops |
|
]; |
|
stops.sort($07628d57aabb0c0b$var$compare); |
|
return stops; |
|
} |
|
/** |
|
* Convert a range to a regex pattern |
|
* @param {Number} `start` |
|
* @param {Number} `stop` |
|
* @return {String} |
|
*/ function $07628d57aabb0c0b$var$rangeToPattern(start, stop, options) { |
|
if (start === stop) return { |
|
pattern: start, |
|
count: [], |
|
digits: 0 |
|
}; |
|
let zipped = $07628d57aabb0c0b$var$zip(start, stop); |
|
let digits = zipped.length; |
|
let pattern = ''; |
|
let count = 0; |
|
for(let i = 0; i < digits; i++){ |
|
let [startDigit, stopDigit] = zipped[i]; |
|
if (startDigit === stopDigit) pattern += startDigit; |
|
else if (startDigit !== '0' || stopDigit !== '9') pattern += $07628d57aabb0c0b$var$toCharacterClass(startDigit, stopDigit, options); |
|
else count++; |
|
} |
|
if (count) pattern += options.shorthand === true ? '\\d' : '[0-9]'; |
|
return { |
|
pattern: pattern, |
|
count: [ |
|
count |
|
], |
|
digits: digits |
|
}; |
|
} |
|
function $07628d57aabb0c0b$var$splitToPatterns(min, max, tok, options) { |
|
let ranges = $07628d57aabb0c0b$var$splitToRanges(min, max); |
|
let tokens = []; |
|
let start = min; |
|
let prev; |
|
for(let i = 0; i < ranges.length; i++){ |
|
let max = ranges[i]; |
|
let obj = $07628d57aabb0c0b$var$rangeToPattern(String(start), String(max), options); |
|
let zeros = ''; |
|
if (!tok.isPadded && prev && prev.pattern === obj.pattern) { |
|
if (prev.count.length > 1) prev.count.pop(); |
|
prev.count.push(obj.count[0]); |
|
prev.string = prev.pattern + $07628d57aabb0c0b$var$toQuantifier(prev.count); |
|
start = max + 1; |
|
continue; |
|
} |
|
if (tok.isPadded) zeros = $07628d57aabb0c0b$var$padZeros(max, tok, options); |
|
obj.string = zeros + obj.pattern + $07628d57aabb0c0b$var$toQuantifier(obj.count); |
|
tokens.push(obj); |
|
start = max + 1; |
|
prev = obj; |
|
} |
|
return tokens; |
|
} |
|
function $07628d57aabb0c0b$var$filterPatterns(arr, comparison, prefix, intersection, options) { |
|
let result = []; |
|
for (let ele of arr){ |
|
let { string: string } = ele; |
|
// only push if _both_ are negative... |
|
if (!intersection && !$07628d57aabb0c0b$var$contains(comparison, 'string', string)) result.push(prefix + string); |
|
// or _both_ are positive |
|
if (intersection && $07628d57aabb0c0b$var$contains(comparison, 'string', string)) result.push(prefix + string); |
|
} |
|
return result; |
|
} |
|
/** |
|
* Zip strings |
|
*/ function $07628d57aabb0c0b$var$zip(a, b) { |
|
let arr = []; |
|
for(let i = 0; i < a.length; i++)arr.push([ |
|
a[i], |
|
b[i] |
|
]); |
|
return arr; |
|
} |
|
function $07628d57aabb0c0b$var$compare(a, b) { |
|
return a > b ? 1 : b > a ? -1 : 0; |
|
} |
|
function $07628d57aabb0c0b$var$contains(arr, key, val) { |
|
return arr.some((ele)=>ele[key] === val |
|
); |
|
} |
|
function $07628d57aabb0c0b$var$countNines(min, len) { |
|
return Number(String(min).slice(0, -len) + '9'.repeat(len)); |
|
} |
|
function $07628d57aabb0c0b$var$countZeros(integer, zeros) { |
|
return integer - integer % Math.pow(10, zeros); |
|
} |
|
function $07628d57aabb0c0b$var$toQuantifier(digits) { |
|
let [start = 0, stop = ''] = digits; |
|
if (stop || start > 1) return `{${start + (stop ? ',' + stop : '')}}`; |
|
return ''; |
|
} |
|
function $07628d57aabb0c0b$var$toCharacterClass(a, b, options) { |
|
return `[${a}${b - a === 1 ? '' : '-'}${b}]`; |
|
} |
|
function $07628d57aabb0c0b$var$hasPadding(str) { |
|
return /^-?(0+)\d/.test(str); |
|
} |
|
function $07628d57aabb0c0b$var$padZeros(value, tok, options) { |
|
if (!tok.isPadded) return value; |
|
let diff = Math.abs(tok.maxLen - String(value).length); |
|
let relax = options.relaxZeros !== false; |
|
switch(diff){ |
|
case 0: |
|
return ''; |
|
case 1: |
|
return relax ? '0?' : '0'; |
|
case 2: |
|
return relax ? '0{0,2}' : '00'; |
|
default: |
|
return relax ? `0{0,${diff}}` : `0{${diff}}`; |
|
} |
|
} |
|
/** |
|
* Cache |
|
*/ $07628d57aabb0c0b$var$toRegexRange.cache = { |
|
}; |
|
$07628d57aabb0c0b$var$toRegexRange.clearCache = ()=>$07628d57aabb0c0b$var$toRegexRange.cache = { |
|
} |
|
; |
|
/** |
|
* Expose `toRegexRange` |
|
*/ $07628d57aabb0c0b$exports = $07628d57aabb0c0b$var$toRegexRange; |
|
|
|
|
|
const $834b1889a72cf074$var$isObject = (val)=>val !== null && typeof val === 'object' && !Array.isArray(val) |
|
; |
|
const $834b1889a72cf074$var$transform = (toNumber)=>{ |
|
return (value)=>toNumber === true ? Number(value) : String(value) |
|
; |
|
}; |
|
const $834b1889a72cf074$var$isValidValue = (value)=>{ |
|
return typeof value === 'number' || typeof value === 'string' && value !== ''; |
|
}; |
|
const $834b1889a72cf074$var$isNumber = (num)=>Number.isInteger(+num) |
|
; |
|
const $834b1889a72cf074$var$zeros = (input)=>{ |
|
let value = `${input}`; |
|
let index = -1; |
|
if (value[0] === '-') value = value.slice(1); |
|
if (value === '0') return false; |
|
while(value[++index] === '0'); |
|
return index > 0; |
|
}; |
|
const $834b1889a72cf074$var$stringify = (start, end, options)=>{ |
|
if (typeof start === 'string' || typeof end === 'string') return true; |
|
return options.stringify === true; |
|
}; |
|
const $834b1889a72cf074$var$pad = (input, maxLength, toNumber)=>{ |
|
if (maxLength > 0) { |
|
let dash = input[0] === '-' ? '-' : ''; |
|
if (dash) input = input.slice(1); |
|
input = dash + input.padStart(dash ? maxLength - 1 : maxLength, '0'); |
|
} |
|
if (toNumber === false) return String(input); |
|
return input; |
|
}; |
|
const $834b1889a72cf074$var$toMaxLen = (input, maxLength)=>{ |
|
let negative = input[0] === '-' ? '-' : ''; |
|
if (negative) { |
|
input = input.slice(1); |
|
maxLength--; |
|
} |
|
while(input.length < maxLength)input = '0' + input; |
|
return negative ? '-' + input : input; |
|
}; |
|
const $834b1889a72cf074$var$toSequence = (parts, options)=>{ |
|
parts.negatives.sort((a, b)=>a < b ? -1 : a > b ? 1 : 0 |
|
); |
|
parts.positives.sort((a, b)=>a < b ? -1 : a > b ? 1 : 0 |
|
); |
|
let prefix = options.capture ? '' : '?:'; |
|
let positives = ''; |
|
let negatives = ''; |
|
let result; |
|
if (parts.positives.length) positives = parts.positives.join('|'); |
|
if (parts.negatives.length) negatives = `-(${prefix}${parts.negatives.join('|')})`; |
|
if (positives && negatives) result = `${positives}|${negatives}`; |
|
else result = positives || negatives; |
|
if (options.wrap) return `(${prefix}${result})`; |
|
return result; |
|
}; |
|
const $834b1889a72cf074$var$toRange = (a, b, isNumbers, options)=>{ |
|
if (isNumbers) return $07628d57aabb0c0b$exports(a, b, { |
|
wrap: false, |
|
...options |
|
}); |
|
let start = String.fromCharCode(a); |
|
if (a === b) return start; |
|
let stop = String.fromCharCode(b); |
|
return `[${start}-${stop}]`; |
|
}; |
|
const $834b1889a72cf074$var$toRegex = (start, end, options)=>{ |
|
if (Array.isArray(start)) { |
|
let wrap = options.wrap === true; |
|
let prefix = options.capture ? '' : '?:'; |
|
return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); |
|
} |
|
return $07628d57aabb0c0b$exports(start, end, options); |
|
}; |
|
const $834b1889a72cf074$var$rangeError = (...args)=>{ |
|
return new RangeError('Invalid range arguments: ' + $8C1kk$util.inspect(...args)); |
|
}; |
|
const $834b1889a72cf074$var$invalidRange = (start, end, options)=>{ |
|
if (options.strictRanges === true) throw $834b1889a72cf074$var$rangeError([ |
|
start, |
|
end |
|
]); |
|
return []; |
|
}; |
|
const $834b1889a72cf074$var$invalidStep = (step, options)=>{ |
|
if (options.strictRanges === true) throw new TypeError(`Expected step "${step}" to be a number`); |
|
return []; |
|
}; |
|
const $834b1889a72cf074$var$fillNumbers = (start, end, step = 1, options = { |
|
})=>{ |
|
let a = Number(start); |
|
let b = Number(end); |
|
if (!Number.isInteger(a) || !Number.isInteger(b)) { |
|
if (options.strictRanges === true) throw $834b1889a72cf074$var$rangeError([ |
|
start, |
|
end |
|
]); |
|
return []; |
|
} |
|
// fix negative zero |
|
if (a === 0) a = 0; |
|
if (b === 0) b = 0; |
|
let descending = a > b; |
|
let startString = String(start); |
|
let endString = String(end); |
|
let stepString = String(step); |
|
step = Math.max(Math.abs(step), 1); |
|
let padded = $834b1889a72cf074$var$zeros(startString) || $834b1889a72cf074$var$zeros(endString) || $834b1889a72cf074$var$zeros(stepString); |
|
let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; |
|
let toNumber = padded === false && $834b1889a72cf074$var$stringify(start, end, options) === false; |
|
let format = options.transform || $834b1889a72cf074$var$transform(toNumber); |
|
if (options.toRegex && step === 1) return $834b1889a72cf074$var$toRange($834b1889a72cf074$var$toMaxLen(start, maxLen), $834b1889a72cf074$var$toMaxLen(end, maxLen), true, options); |
|
let parts = { |
|
negatives: [], |
|
positives: [] |
|
}; |
|
let push = (num)=>parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)) |
|
; |
|
let range = []; |
|
let index = 0; |
|
while(descending ? a >= b : a <= b){ |
|
if (options.toRegex === true && step > 1) push(a); |
|
else range.push($834b1889a72cf074$var$pad(format(a, index), maxLen, toNumber)); |
|
a = descending ? a - step : a + step; |
|
index++; |
|
} |
|
if (options.toRegex === true) return step > 1 ? $834b1889a72cf074$var$toSequence(parts, options) : $834b1889a72cf074$var$toRegex(range, null, { |
|
wrap: false, |
|
...options |
|
}); |
|
return range; |
|
}; |
|
const $834b1889a72cf074$var$fillLetters = (start, end, step = 1, options = { |
|
})=>{ |
|
if (!$834b1889a72cf074$var$isNumber(start) && start.length > 1 || !$834b1889a72cf074$var$isNumber(end) && end.length > 1) return $834b1889a72cf074$var$invalidRange(start, end, options); |
|
let format = options.transform || ((val)=>String.fromCharCode(val) |
|
); |
|
let a = `${start}`.charCodeAt(0); |
|
let b = `${end}`.charCodeAt(0); |
|
let descending = a > b; |
|
let min = Math.min(a, b); |
|
let max = Math.max(a, b); |
|
if (options.toRegex && step === 1) return $834b1889a72cf074$var$toRange(min, max, false, options); |
|
let range = []; |
|
let index = 0; |
|
while(descending ? a >= b : a <= b){ |
|
range.push(format(a, index)); |
|
a = descending ? a - step : a + step; |
|
index++; |
|
} |
|
if (options.toRegex === true) return $834b1889a72cf074$var$toRegex(range, null, { |
|
wrap: false, |
|
options: options |
|
}); |
|
return range; |
|
}; |
|
const $834b1889a72cf074$var$fill = (start, end, step, options = { |
|
})=>{ |
|
if (end == null && $834b1889a72cf074$var$isValidValue(start)) return [ |
|
start |
|
]; |
|
if (!$834b1889a72cf074$var$isValidValue(start) || !$834b1889a72cf074$var$isValidValue(end)) return $834b1889a72cf074$var$invalidRange(start, end, options); |
|
if (typeof step === 'function') return $834b1889a72cf074$var$fill(start, end, 1, { |
|
transform: step |
|
}); |
|
if ($834b1889a72cf074$var$isObject(step)) return $834b1889a72cf074$var$fill(start, end, 0, step); |
|
let opts = { |
|
...options |
|
}; |
|
if (opts.capture === true) opts.wrap = true; |
|
step = step || opts.step || 1; |
|
if (!$834b1889a72cf074$var$isNumber(step)) { |
|
if (step != null && !$834b1889a72cf074$var$isObject(step)) return $834b1889a72cf074$var$invalidStep(step, opts); |
|
return $834b1889a72cf074$var$fill(start, end, 1, step); |
|
} |
|
if ($834b1889a72cf074$var$isNumber(start) && $834b1889a72cf074$var$isNumber(end)) return $834b1889a72cf074$var$fillNumbers(start, end, step, opts); |
|
return $834b1889a72cf074$var$fillLetters(start, end, Math.max(Math.abs(step), 1), opts); |
|
}; |
|
$834b1889a72cf074$exports = $834b1889a72cf074$var$fill; |
|
|
|
|
|
|
|
const $c82bd34878224845$var$compile = (ast, options = { |
|
})=>{ |
|
let walk = (node, parent = { |
|
})=>{ |
|
let invalidBlock = $d0a07df29ef1b0fa$export$25a78c310c11373f(parent); |
|
let invalidNode = node.invalid === true && options.escapeInvalid === true; |
|
let invalid = invalidBlock === true || invalidNode === true; |
|
let prefix = options.escapeInvalid === true ? '\\' : ''; |
|
let output = ''; |
|
if (node.isOpen === true) return prefix + node.value; |
|
if (node.isClose === true) return prefix + node.value; |
|
if (node.type === 'open') return invalid ? prefix + node.value : '('; |
|
if (node.type === 'close') return invalid ? prefix + node.value : ')'; |
|
if (node.type === 'comma') return node.prev.type === 'comma' ? '' : invalid ? node.value : '|'; |
|
if (node.value) return node.value; |
|
if (node.nodes && node.ranges > 0) { |
|
let args = $d0a07df29ef1b0fa$export$533b26079ad0b4b(node.nodes); |
|
let range = $834b1889a72cf074$exports(...args, { |
|
...options, |
|
wrap: false, |
|
toRegex: true |
|
}); |
|
if (range.length !== 0) return args.length > 1 && range.length > 1 ? `(${range})` : range; |
|
} |
|
if (node.nodes) for (let child of node.nodes)output += walk(child, node); |
|
return output; |
|
}; |
|
return walk(ast); |
|
}; |
|
$c82bd34878224845$exports = $c82bd34878224845$var$compile; |
|
|
|
|
|
var $9d3fbdd0cb3873b2$exports = {}; |
|
'use strict'; |
|
|
|
|
|
|
|
const $9d3fbdd0cb3873b2$var$append = (queue = '', stash = '', enclose = false)=>{ |
|
let result = []; |
|
queue = [].concat(queue); |
|
stash = [].concat(stash); |
|
if (!stash.length) return queue; |
|
if (!queue.length) return enclose ? $d0a07df29ef1b0fa$export$bffa455ba8c619a6(stash).map((ele)=>`{${ele}}` |
|
) : stash; |
|
for (let item of queue){ |
|
if (Array.isArray(item)) for (let value of item)result.push($9d3fbdd0cb3873b2$var$append(value, stash, enclose)); |
|
else for (let ele of stash){ |
|
if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; |
|
result.push(Array.isArray(ele) ? $9d3fbdd0cb3873b2$var$append(item, ele, enclose) : item + ele); |
|
} |
|
} |
|
return $d0a07df29ef1b0fa$export$bffa455ba8c619a6(result); |
|
}; |
|
const $9d3fbdd0cb3873b2$var$expand = (ast, options = { |
|
})=>{ |
|
let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit; |
|
let walk = (node, parent = { |
|
})=>{ |
|
node.queue = []; |
|
let p = parent; |
|
let q = parent.queue; |
|
while(p.type !== 'brace' && p.type !== 'root' && p.parent){ |
|
p = p.parent; |
|
q = p.queue; |
|
} |
|
if (node.invalid || node.dollar) { |
|
q.push($9d3fbdd0cb3873b2$var$append(q.pop(), $156a1a36db86ccbd$exports(node, options))); |
|
return; |
|
} |
|
if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { |
|
q.push($9d3fbdd0cb3873b2$var$append(q.pop(), [ |
|
'{}' |
|
])); |
|
return; |
|
} |
|
if (node.nodes && node.ranges > 0) { |
|
let args = $d0a07df29ef1b0fa$export$533b26079ad0b4b(node.nodes); |
|
if ($d0a07df29ef1b0fa$export$fbadac39f36b1e16(...args, options.step, rangeLimit)) throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); |
|
let range = $834b1889a72cf074$exports(...args, options); |
|
if (range.length === 0) range = $156a1a36db86ccbd$exports(node, options); |
|
q.push($9d3fbdd0cb3873b2$var$append(q.pop(), range)); |
|
node.nodes = []; |
|
return; |
|
} |
|
let enclose = $d0a07df29ef1b0fa$export$ea0f721b77fd5acc(node); |
|
let queue = node.queue; |
|
let block = node; |
|
while(block.type !== 'brace' && block.type !== 'root' && block.parent){ |
|
block = block.parent; |
|
queue = block.queue; |
|
} |
|
for(let i = 0; i < node.nodes.length; i++){ |
|
let child = node.nodes[i]; |
|
if (child.type === 'comma' && node.type === 'brace') { |
|
if (i === 1) queue.push(''); |
|
queue.push(''); |
|
continue; |
|
} |
|
if (child.type === 'close') { |
|
q.push($9d3fbdd0cb3873b2$var$append(q.pop(), queue, enclose)); |
|
continue; |
|
} |
|
if (child.value && child.type !== 'open') { |
|
queue.push($9d3fbdd0cb3873b2$var$append(queue.pop(), child.value)); |
|
continue; |
|
} |
|
if (child.nodes) walk(child, node); |
|
} |
|
return queue; |
|
}; |
|
return $d0a07df29ef1b0fa$export$bffa455ba8c619a6(walk(ast)); |
|
}; |
|
$9d3fbdd0cb3873b2$exports = $9d3fbdd0cb3873b2$var$expand; |
|
|
|
|
|
var $88c0a7901dd4a8c2$exports = {}; |
|
'use strict'; |
|
|
|
var $f1bb1ac16e435177$exports = {}; |
|
'use strict'; |
|
$f1bb1ac16e435177$exports = { |
|
MAX_LENGTH: 65536, |
|
// Digits |
|
CHAR_0: '0', |
|
/* 0 */ CHAR_9: '9', |
|
/* 9 */ // Alphabet chars. |
|
CHAR_UPPERCASE_A: 'A', |
|
/* A */ CHAR_LOWERCASE_A: 'a', |
|
/* a */ CHAR_UPPERCASE_Z: 'Z', |
|
/* Z */ CHAR_LOWERCASE_Z: 'z', |
|
/* z */ CHAR_LEFT_PARENTHESES: '(', |
|
/* ( */ CHAR_RIGHT_PARENTHESES: ')', |
|
/* ) */ CHAR_ASTERISK: '*', |
|
/* * */ // Non-alphabetic chars. |
|
CHAR_AMPERSAND: '&', |
|
/* & */ CHAR_AT: '@', |
|
/* @ */ CHAR_BACKSLASH: '\\', |
|
/* \ */ CHAR_BACKTICK: '`', |
|
/* ` */ CHAR_CARRIAGE_RETURN: '\r', |
|
/* \r */ CHAR_CIRCUMFLEX_ACCENT: '^', |
|
/* ^ */ CHAR_COLON: ':', |
|
/* : */ CHAR_COMMA: ',', |
|
/* , */ CHAR_DOLLAR: '$', |
|
/* . */ CHAR_DOT: '.', |
|
/* . */ CHAR_DOUBLE_QUOTE: '"', |
|
/* " */ CHAR_EQUAL: '=', |
|
/* = */ CHAR_EXCLAMATION_MARK: '!', |
|
/* ! */ CHAR_FORM_FEED: '\f', |
|
/* \f */ CHAR_FORWARD_SLASH: '/', |
|
/* / */ CHAR_HASH: '#', |
|
/* # */ CHAR_HYPHEN_MINUS: '-', |
|
/* - */ CHAR_LEFT_ANGLE_BRACKET: '<', |
|
/* < */ CHAR_LEFT_CURLY_BRACE: '{', |
|
/* { */ CHAR_LEFT_SQUARE_BRACKET: '[', |
|
/* [ */ CHAR_LINE_FEED: '\n', |
|
/* \n */ CHAR_NO_BREAK_SPACE: '\u00A0', |
|
/* \u00A0 */ CHAR_PERCENT: '%', |
|
/* % */ CHAR_PLUS: '+', |
|
/* + */ CHAR_QUESTION_MARK: '?', |
|
/* ? */ CHAR_RIGHT_ANGLE_BRACKET: '>', |
|
/* > */ CHAR_RIGHT_CURLY_BRACE: '}', |
|
/* } */ CHAR_RIGHT_SQUARE_BRACKET: ']', |
|
/* ] */ CHAR_SEMICOLON: ';', |
|
/* ; */ CHAR_SINGLE_QUOTE: '\'', |
|
/* ' */ CHAR_SPACE: ' ', |
|
/* */ CHAR_TAB: '\t', |
|
/* \t */ CHAR_UNDERSCORE: '_', |
|
/* _ */ CHAR_VERTICAL_LINE: '|', |
|
/* | */ CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ |
|
}; |
|
|
|
|
|
var $88c0a7901dd4a8c2$require$MAX_LENGTH = $f1bb1ac16e435177$exports.MAX_LENGTH; |
|
var $88c0a7901dd4a8c2$require$CHAR_BACKSLASH = $f1bb1ac16e435177$exports.CHAR_BACKSLASH; |
|
var $88c0a7901dd4a8c2$require$CHAR_BACKTICK = $f1bb1ac16e435177$exports.CHAR_BACKTICK; |
|
var $88c0a7901dd4a8c2$require$CHAR_COMMA = $f1bb1ac16e435177$exports.CHAR_COMMA; |
|
var $88c0a7901dd4a8c2$require$CHAR_DOT = $f1bb1ac16e435177$exports.CHAR_DOT; |
|
var $88c0a7901dd4a8c2$require$CHAR_LEFT_PARENTHESES = $f1bb1ac16e435177$exports.CHAR_LEFT_PARENTHESES; |
|
var $88c0a7901dd4a8c2$require$CHAR_RIGHT_PARENTHESES = $f1bb1ac16e435177$exports.CHAR_RIGHT_PARENTHESES; |
|
var $88c0a7901dd4a8c2$require$CHAR_LEFT_CURLY_BRACE = $f1bb1ac16e435177$exports.CHAR_LEFT_CURLY_BRACE; |
|
var $88c0a7901dd4a8c2$require$CHAR_RIGHT_CURLY_BRACE = $f1bb1ac16e435177$exports.CHAR_RIGHT_CURLY_BRACE; |
|
var $88c0a7901dd4a8c2$require$CHAR_LEFT_SQUARE_BRACKET = $f1bb1ac16e435177$exports.CHAR_LEFT_SQUARE_BRACKET; |
|
var $88c0a7901dd4a8c2$require$CHAR_RIGHT_SQUARE_BRACKET = $f1bb1ac16e435177$exports.CHAR_RIGHT_SQUARE_BRACKET; |
|
var $88c0a7901dd4a8c2$require$CHAR_DOUBLE_QUOTE = $f1bb1ac16e435177$exports.CHAR_DOUBLE_QUOTE; |
|
var $88c0a7901dd4a8c2$require$CHAR_SINGLE_QUOTE = $f1bb1ac16e435177$exports.CHAR_SINGLE_QUOTE; |
|
var $88c0a7901dd4a8c2$require$CHAR_NO_BREAK_SPACE = $f1bb1ac16e435177$exports.CHAR_NO_BREAK_SPACE; |
|
var $88c0a7901dd4a8c2$require$CHAR_ZERO_WIDTH_NOBREAK_SPACE = $f1bb1ac16e435177$exports.CHAR_ZERO_WIDTH_NOBREAK_SPACE; |
|
/** |
|
* parse |
|
*/ const $88c0a7901dd4a8c2$var$parse = (input, options = { |
|
})=>{ |
|
if (typeof input !== 'string') throw new TypeError('Expected a string'); |
|
let opts = options || { |
|
}; |
|
let max = typeof opts.maxLength === 'number' ? Math.min($88c0a7901dd4a8c2$require$MAX_LENGTH, opts.maxLength) : $88c0a7901dd4a8c2$require$MAX_LENGTH; |
|
if (input.length > max) throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); |
|
let ast = { |
|
type: 'root', |
|
input: input, |
|
nodes: [] |
|
}; |
|
let stack = [ |
|
ast |
|
]; |
|
let block = ast; |
|
let prev = ast; |
|
let brackets = 0; |
|
let length = input.length; |
|
let index = 0; |
|
let depth = 0; |
|
let value; |
|
let memo = { |
|
}; |
|
/** |
|
* Helpers |
|
*/ const advance = ()=>input[index++] |
|
; |
|
const push = (node)=>{ |
|
if (node.type === 'text' && prev.type === 'dot') prev.type = 'text'; |
|
if (prev && prev.type === 'text' && node.type === 'text') { |
|
prev.value += node.value; |
|
return; |
|
} |
|
block.nodes.push(node); |
|
node.parent = block; |
|
node.prev = prev; |
|
prev = node; |
|
return node; |
|
}; |
|
push({ |
|
type: 'bos' |
|
}); |
|
while(index < length){ |
|
block = stack[stack.length - 1]; |
|
value = advance(); |
|
/** |
|
* Invalid chars |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === $88c0a7901dd4a8c2$require$CHAR_NO_BREAK_SPACE) continue; |
|
/** |
|
* Escaped chars |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_BACKSLASH) { |
|
push({ |
|
type: 'text', |
|
value: (options.keepEscaping ? value : '') + advance() |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Right square bracket (literal): ']' |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_RIGHT_SQUARE_BRACKET) { |
|
push({ |
|
type: 'text', |
|
value: '\\' + value |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Left square bracket: '[' |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_LEFT_SQUARE_BRACKET) { |
|
brackets++; |
|
let closed = true; |
|
let next; |
|
while(index < length && (next = advance())){ |
|
value += next; |
|
if (next === $88c0a7901dd4a8c2$require$CHAR_LEFT_SQUARE_BRACKET) { |
|
brackets++; |
|
continue; |
|
} |
|
if (next === $88c0a7901dd4a8c2$require$CHAR_BACKSLASH) { |
|
value += advance(); |
|
continue; |
|
} |
|
if (next === $88c0a7901dd4a8c2$require$CHAR_RIGHT_SQUARE_BRACKET) { |
|
brackets--; |
|
if (brackets === 0) break; |
|
} |
|
} |
|
push({ |
|
type: 'text', |
|
value: value |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Parentheses |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_LEFT_PARENTHESES) { |
|
block = push({ |
|
type: 'paren', |
|
nodes: [] |
|
}); |
|
stack.push(block); |
|
push({ |
|
type: 'text', |
|
value: value |
|
}); |
|
continue; |
|
} |
|
if (value === $88c0a7901dd4a8c2$require$CHAR_RIGHT_PARENTHESES) { |
|
if (block.type !== 'paren') { |
|
push({ |
|
type: 'text', |
|
value: value |
|
}); |
|
continue; |
|
} |
|
block = stack.pop(); |
|
push({ |
|
type: 'text', |
|
value: value |
|
}); |
|
block = stack[stack.length - 1]; |
|
continue; |
|
} |
|
/** |
|
* Quotes: '|"|` |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_DOUBLE_QUOTE || value === $88c0a7901dd4a8c2$require$CHAR_SINGLE_QUOTE || value === $88c0a7901dd4a8c2$require$CHAR_BACKTICK) { |
|
let open = value; |
|
let next; |
|
if (options.keepQuotes !== true) value = ''; |
|
while(index < length && (next = advance())){ |
|
if (next === $88c0a7901dd4a8c2$require$CHAR_BACKSLASH) { |
|
value += next + advance(); |
|
continue; |
|
} |
|
if (next === open) { |
|
if (options.keepQuotes === true) value += next; |
|
break; |
|
} |
|
value += next; |
|
} |
|
push({ |
|
type: 'text', |
|
value: value |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Left curly brace: '{' |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_LEFT_CURLY_BRACE) { |
|
depth++; |
|
let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; |
|
let brace = { |
|
type: 'brace', |
|
open: true, |
|
close: false, |
|
dollar: dollar, |
|
depth: depth, |
|
commas: 0, |
|
ranges: 0, |
|
nodes: [] |
|
}; |
|
block = push(brace); |
|
stack.push(block); |
|
push({ |
|
type: 'open', |
|
value: value |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Right curly brace: '}' |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_RIGHT_CURLY_BRACE) { |
|
if (block.type !== 'brace') { |
|
push({ |
|
type: 'text', |
|
value: value |
|
}); |
|
continue; |
|
} |
|
let type = 'close'; |
|
block = stack.pop(); |
|
block.close = true; |
|
push({ |
|
type: type, |
|
value: value |
|
}); |
|
depth--; |
|
block = stack[stack.length - 1]; |
|
continue; |
|
} |
|
/** |
|
* Comma: ',' |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_COMMA && depth > 0) { |
|
if (block.ranges > 0) { |
|
block.ranges = 0; |
|
let open = block.nodes.shift(); |
|
block.nodes = [ |
|
open, |
|
{ |
|
type: 'text', |
|
value: $156a1a36db86ccbd$exports(block) |
|
} |
|
]; |
|
} |
|
push({ |
|
type: 'comma', |
|
value: value |
|
}); |
|
block.commas++; |
|
continue; |
|
} |
|
/** |
|
* Dot: '.' |
|
*/ if (value === $88c0a7901dd4a8c2$require$CHAR_DOT && depth > 0 && block.commas === 0) { |
|
let siblings = block.nodes; |
|
if (depth === 0 || siblings.length === 0) { |
|
push({ |
|
type: 'text', |
|
value: value |
|
}); |
|
continue; |
|
} |
|
if (prev.type === 'dot') { |
|
block.range = []; |
|
prev.value += value; |
|
prev.type = 'range'; |
|
if (block.nodes.length !== 3 && block.nodes.length !== 5) { |
|
block.invalid = true; |
|
block.ranges = 0; |
|
prev.type = 'text'; |
|
continue; |
|
} |
|
block.ranges++; |
|
block.args = []; |
|
continue; |
|
} |
|
if (prev.type === 'range') { |
|
siblings.pop(); |
|
let before = siblings[siblings.length - 1]; |
|
before.value += prev.value + value; |
|
prev = before; |
|
block.ranges--; |
|
continue; |
|
} |
|
push({ |
|
type: 'dot', |
|
value: value |
|
}); |
|
continue; |
|
} |
|
/** |
|
* Text |
|
*/ push({ |
|
type: 'text', |
|
value: value |
|
}); |
|
} |
|
// Mark imbalanced braces and brackets as invalid |
|
do { |
|
block = stack.pop(); |
|
if (block.type !== 'root') { |
|
block.nodes.forEach((node)=>{ |
|
if (!node.nodes) { |
|
if (node.type === 'open') node.isOpen = true; |
|
if (node.type === 'close') node.isClose = true; |
|
if (!node.nodes) node.type = 'text'; |
|
node.invalid = true; |
|
} |
|
}); |
|
// get the location of the block on parent.nodes (block's siblings) |
|
let parent = stack[stack.length - 1]; |
|
let index = parent.nodes.indexOf(block); |
|
// replace the (invalid) block with it's nodes |
|
parent.nodes.splice(index, 1, ...block.nodes); |
|
} |
|
}while (stack.length > 0) |
|
push({ |
|
type: 'eos' |
|
}); |
|
return ast; |
|
}; |
|
$88c0a7901dd4a8c2$exports = $88c0a7901dd4a8c2$var$parse; |
|
|
|
|
|
/** |
|
* Expand the given pattern or create a regex-compatible string. |
|
* |
|
* ```js |
|
* const braces = require('braces'); |
|
* console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] |
|
* console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] |
|
* ``` |
|
* @param {String} `str` |
|
* @param {Object} `options` |
|
* @return {String} |
|
* @api public |
|
*/ const $fec07f13db1e462a$var$braces = (input, options = { |
|
})=>{ |
|
let output = []; |
|
if (Array.isArray(input)) for (let pattern of input){ |
|
let result = $fec07f13db1e462a$var$braces.create(pattern, options); |
|
if (Array.isArray(result)) output.push(...result); |
|
else output.push(result); |
|
} |
|
else output = [].concat($fec07f13db1e462a$var$braces.create(input, options)); |
|
if (options && options.expand === true && options.nodupes === true) output = [ |
|
...new Set(output) |
|
]; |
|
return output; |
|
}; |
|
/** |
|
* Parse the given `str` with the given `options`. |
|
* |
|
* ```js |
|
* // braces.parse(pattern, [, options]); |
|
* const ast = braces.parse('a/{b,c}/d'); |
|
* console.log(ast); |
|
* ``` |
|
* @param {String} pattern Brace pattern to parse |
|
* @param {Object} options |
|
* @return {Object} Returns an AST |
|
* @api public |
|
*/ $fec07f13db1e462a$var$braces.parse = (input, options = { |
|
})=>$88c0a7901dd4a8c2$exports(input, options) |
|
; |
|
/** |
|
* Creates a braces string from an AST, or an AST node. |
|
* |
|
* ```js |
|
* const braces = require('braces'); |
|
* let ast = braces.parse('foo/{a,b}/bar'); |
|
* console.log(stringify(ast.nodes[2])); //=> '{a,b}' |
|
* ``` |
|
* @param {String} `input` Brace pattern or AST. |
|
* @param {Object} `options` |
|
* @return {Array} Returns an array of expanded values. |
|
* @api public |
|
*/ $fec07f13db1e462a$var$braces.stringify = (input, options = { |
|
})=>{ |
|
if (typeof input === 'string') return $156a1a36db86ccbd$exports($fec07f13db1e462a$var$braces.parse(input, options), options); |
|
return $156a1a36db86ccbd$exports(input, options); |
|
}; |
|
/** |
|
* Compiles a brace pattern into a regex-compatible, optimized string. |
|
* This method is called by the main [braces](#braces) function by default. |
|
* |
|
* ```js |
|
* const braces = require('braces'); |
|
* console.log(braces.compile('a/{b,c}/d')); |
|
* //=> ['a/(b|c)/d'] |
|
* ``` |
|
* @param {String} `input` Brace pattern or AST. |
|
* @param {Object} `options` |
|
* @return {Array} Returns an array of expanded values. |
|
* @api public |
|
*/ $fec07f13db1e462a$var$braces.compile = (input, options = { |
|
})=>{ |
|
if (typeof input === 'string') input = $fec07f13db1e462a$var$braces.parse(input, options); |
|
return $c82bd34878224845$exports(input, options); |
|
}; |
|
/** |
|
* Expands a brace pattern into an array. This method is called by the |
|
* main [braces](#braces) function when `options.expand` is true. Before |
|
* using this method it's recommended that you read the [performance notes](#performance)) |
|
* and advantages of using [.compile](#compile) instead. |
|
* |
|
* ```js |
|
* const braces = require('braces'); |
|
* console.log(braces.expand('a/{b,c}/d')); |
|
* //=> ['a/b/d', 'a/c/d']; |
|
* ``` |
|
* @param {String} `pattern` Brace pattern |
|
* @param {Object} `options` |
|
* @return {Array} Returns an array of expanded values. |
|
* @api public |
|
*/ $fec07f13db1e462a$var$braces.expand = (input, options = { |
|
})=>{ |
|
if (typeof input === 'string') input = $fec07f13db1e462a$var$braces.parse(input, options); |
|
let result = $9d3fbdd0cb3873b2$exports(input, options); |
|
// filter out empty strings if specified |
|
if (options.noempty === true) result = result.filter(Boolean); |
|
// filter out duplicates if specified |
|
if (options.nodupes === true) result = [ |
|
...new Set(result) |
|
]; |
|
return result; |
|
}; |
|
/** |
|
* Processes a brace pattern and returns either an expanded array |
|
* (if `options.expand` is true), a highly optimized regex-compatible string. |
|
* This method is called by the main [braces](#braces) function. |
|
* |
|
* ```js |
|
* const braces = require('braces'); |
|
* console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) |
|
* //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' |
|
* ``` |
|
* @param {String} `pattern` Brace pattern |
|
* @param {Object} `options` |
|
* @return {Array} Returns an array of expanded values. |
|
* @api public |
|
*/ $fec07f13db1e462a$var$braces.create = (input, options = { |
|
})=>{ |
|
if (input === '' || input.length < 3) return [ |
|
input |
|
]; |
|
return options.expand !== true ? $fec07f13db1e462a$var$braces.compile(input, options) : $fec07f13db1e462a$var$braces.expand(input, options); |
|
}; |
|
/** |
|
* Expose "braces" |
|
*/ $fec07f13db1e462a$exports = $fec07f13db1e462a$var$braces; |
|
|
|
|
|
var $2af609aa204f1181$exports = {}; |
|
'use strict'; |
|
|
|
$2af609aa204f1181$exports = (parcelRequire("4997P")); |
|
|
|
|
|
|
|
var $5MQDC = parcelRequire("5MQDC"); |
|
const $fec3b4fc54d3756a$var$isEmptyString = (val)=>val === '' || val === './' |
|
; |
|
/** |
|
* Returns an array of strings that match one or more glob patterns. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm(list, patterns[, options]); |
|
* |
|
* console.log(mm(['a.js', 'a.txt'], ['*.js'])); |
|
* //=> [ 'a.js' ] |
|
* ``` |
|
* @param {String|Array<string>} `list` List of strings to match. |
|
* @param {String|Array<string>} `patterns` One or more glob patterns to use for matching. |
|
* @param {Object} `options` See available [options](#options) |
|
* @return {Array} Returns an array of matches |
|
* @summary false |
|
* @api public |
|
*/ const $fec3b4fc54d3756a$var$micromatch = (list, patterns, options)=>{ |
|
patterns = [].concat(patterns); |
|
list = [].concat(list); |
|
let omit = new Set(); |
|
let keep = new Set(); |
|
let items = new Set(); |
|
let negatives = 0; |
|
let onResult = (state)=>{ |
|
items.add(state.output); |
|
if (options && options.onResult) options.onResult(state); |
|
}; |
|
for(let i = 0; i < patterns.length; i++){ |
|
let isMatch = $2af609aa204f1181$exports(String(patterns[i]), { |
|
...options, |
|
onResult: onResult |
|
}, true); |
|
let negated = isMatch.state.negated || isMatch.state.negatedExtglob; |
|
if (negated) negatives++; |
|
for (let item of list){ |
|
let matched = isMatch(item, true); |
|
let match = negated ? !matched.isMatch : matched.isMatch; |
|
if (!match) continue; |
|
if (negated) omit.add(matched.output); |
|
else { |
|
omit.delete(matched.output); |
|
keep.add(matched.output); |
|
} |
|
} |
|
} |
|
let result = negatives === patterns.length ? [ |
|
...items |
|
] : [ |
|
...keep |
|
]; |
|
let matches = result.filter((item)=>!omit.has(item) |
|
); |
|
if (options && matches.length === 0) { |
|
if (options.failglob === true) throw new Error(`No matches found for "${patterns.join(', ')}"`); |
|
if (options.nonull === true || options.nullglob === true) return options.unescape ? patterns.map((p)=>p.replace(/\\/g, '') |
|
) : patterns; |
|
} |
|
return matches; |
|
}; |
|
/** |
|
* Backwards compatibility |
|
*/ $fec3b4fc54d3756a$var$micromatch.match = $fec3b4fc54d3756a$var$micromatch; |
|
/** |
|
* Returns a matcher function from the given glob `pattern` and `options`. |
|
* The returned function takes a string to match as its only argument and returns |
|
* true if the string is a match. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm.matcher(pattern[, options]); |
|
* |
|
* const isMatch = mm.matcher('*.!(*a)'); |
|
* console.log(isMatch('a.a')); //=> false |
|
* console.log(isMatch('a.b')); //=> true |
|
* ``` |
|
* @param {String} `pattern` Glob pattern |
|
* @param {Object} `options` |
|
* @return {Function} Returns a matcher function. |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.matcher = (pattern, options)=>$2af609aa204f1181$exports(pattern, options) |
|
; |
|
/** |
|
* Returns true if **any** of the given glob `patterns` match the specified `string`. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm.isMatch(string, patterns[, options]); |
|
* |
|
* console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true |
|
* console.log(mm.isMatch('a.a', 'b.*')); //=> false |
|
* ``` |
|
* @param {String} `str` The string to test. |
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching. |
|
* @param {Object} `[options]` See available [options](#options). |
|
* @return {Boolean} Returns true if any patterns match `str` |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.isMatch = (str, patterns, options)=>$2af609aa204f1181$exports(patterns, options)(str) |
|
; |
|
/** |
|
* Backwards compatibility |
|
*/ $fec3b4fc54d3756a$var$micromatch.any = $fec3b4fc54d3756a$var$micromatch.isMatch; |
|
/** |
|
* Returns a list of strings that _**do not match any**_ of the given `patterns`. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm.not(list, patterns[, options]); |
|
* |
|
* console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); |
|
* //=> ['b.b', 'c.c'] |
|
* ``` |
|
* @param {Array} `list` Array of strings to match. |
|
* @param {String|Array} `patterns` One or more glob pattern to use for matching. |
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed |
|
* @return {Array} Returns an array of strings that **do not match** the given patterns. |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.not = (list, patterns, options = { |
|
})=>{ |
|
patterns = [].concat(patterns).map(String); |
|
let result = new Set(); |
|
let items = []; |
|
let onResult = (state)=>{ |
|
if (options.onResult) options.onResult(state); |
|
items.push(state.output); |
|
}; |
|
let matches = $fec3b4fc54d3756a$var$micromatch(list, patterns, { |
|
...options, |
|
onResult: onResult |
|
}); |
|
for (let item of items)if (!matches.includes(item)) result.add(item); |
|
return [ |
|
...result |
|
]; |
|
}; |
|
/** |
|
* Returns true if the given `string` contains the given pattern. Similar |
|
* to [.isMatch](#isMatch) but the pattern can match any part of the string. |
|
* |
|
* ```js |
|
* var mm = require('micromatch'); |
|
* // mm.contains(string, pattern[, options]); |
|
* |
|
* console.log(mm.contains('aa/bb/cc', '*b')); |
|
* //=> true |
|
* console.log(mm.contains('aa/bb/cc', '*d')); |
|
* //=> false |
|
* ``` |
|
* @param {String} `str` The string to match. |
|
* @param {String|Array} `patterns` Glob pattern to use for matching. |
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed |
|
* @return {Boolean} Returns true if any of the patterns matches any part of `str`. |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.contains = (str, pattern, options)=>{ |
|
if (typeof str !== 'string') throw new TypeError(`Expected a string: "${$8C1kk$util.inspect(str)}"`); |
|
if (Array.isArray(pattern)) return pattern.some((p)=>$fec3b4fc54d3756a$var$micromatch.contains(str, p, options) |
|
); |
|
if (typeof pattern === 'string') { |
|
if ($fec3b4fc54d3756a$var$isEmptyString(str) || $fec3b4fc54d3756a$var$isEmptyString(pattern)) return false; |
|
if (str.includes(pattern) || str.startsWith('./') && str.slice(2).includes(pattern)) return true; |
|
} |
|
return $fec3b4fc54d3756a$var$micromatch.isMatch(str, pattern, { |
|
...options, |
|
contains: true |
|
}); |
|
}; |
|
/** |
|
* Filter the keys of the given object with the given `glob` pattern |
|
* and `options`. Does not attempt to match nested keys. If you need this feature, |
|
* use [glob-object][] instead. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm.matchKeys(object, patterns[, options]); |
|
* |
|
* const obj = { aa: 'a', ab: 'b', ac: 'c' }; |
|
* console.log(mm.matchKeys(obj, '*b')); |
|
* //=> { ab: 'b' } |
|
* ``` |
|
* @param {Object} `object` The object with keys to filter. |
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching. |
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed |
|
* @return {Object} Returns an object with only keys that match the given patterns. |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.matchKeys = (obj, patterns, options)=>{ |
|
if (!$5MQDC.isObject(obj)) throw new TypeError('Expected the first argument to be an object'); |
|
let keys = $fec3b4fc54d3756a$var$micromatch(Object.keys(obj), patterns, options); |
|
let res = { |
|
}; |
|
for (let key of keys)res[key] = obj[key]; |
|
return res; |
|
}; |
|
/** |
|
* Returns true if some of the strings in the given `list` match any of the given glob `patterns`. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm.some(list, patterns[, options]); |
|
* |
|
* console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); |
|
* // true |
|
* console.log(mm.some(['foo.js'], ['*.js', '!foo.js'])); |
|
* // false |
|
* ``` |
|
* @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found. |
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching. |
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed |
|
* @return {Boolean} Returns true if any `patterns` matches any of the strings in `list` |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.some = (list, patterns, options)=>{ |
|
let items = [].concat(list); |
|
for (let pattern of [].concat(patterns)){ |
|
let isMatch = $2af609aa204f1181$exports(String(pattern), options); |
|
if (items.some((item)=>isMatch(item) |
|
)) return true; |
|
} |
|
return false; |
|
}; |
|
/** |
|
* Returns true if every string in the given `list` matches |
|
* any of the given glob `patterns`. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm.every(list, patterns[, options]); |
|
* |
|
* console.log(mm.every('foo.js', ['foo.js'])); |
|
* // true |
|
* console.log(mm.every(['foo.js', 'bar.js'], ['*.js'])); |
|
* // true |
|
* console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); |
|
* // false |
|
* console.log(mm.every(['foo.js'], ['*.js', '!foo.js'])); |
|
* // false |
|
* ``` |
|
* @param {String|Array} `list` The string or array of strings to test. |
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching. |
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed |
|
* @return {Boolean} Returns true if all `patterns` matches all of the strings in `list` |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.every = (list, patterns, options)=>{ |
|
let items = [].concat(list); |
|
for (let pattern of [].concat(patterns)){ |
|
let isMatch = $2af609aa204f1181$exports(String(pattern), options); |
|
if (!items.every((item)=>isMatch(item) |
|
)) return false; |
|
} |
|
return true; |
|
}; |
|
/** |
|
* Returns true if **all** of the given `patterns` match |
|
* the specified string. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm.all(string, patterns[, options]); |
|
* |
|
* console.log(mm.all('foo.js', ['foo.js'])); |
|
* // true |
|
* |
|
* console.log(mm.all('foo.js', ['*.js', '!foo.js'])); |
|
* // false |
|
* |
|
* console.log(mm.all('foo.js', ['*.js', 'foo.js'])); |
|
* // true |
|
* |
|
* console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js'])); |
|
* // true |
|
* ``` |
|
* @param {String|Array} `str` The string to test. |
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching. |
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed |
|
* @return {Boolean} Returns true if any patterns match `str` |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.all = (str, patterns, options)=>{ |
|
if (typeof str !== 'string') throw new TypeError(`Expected a string: "${$8C1kk$util.inspect(str)}"`); |
|
return [].concat(patterns).every((p)=>$2af609aa204f1181$exports(p, options)(str) |
|
); |
|
}; |
|
/** |
|
* Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm.capture(pattern, string[, options]); |
|
* |
|
* console.log(mm.capture('test/*.js', 'test/foo.js')); |
|
* //=> ['foo'] |
|
* console.log(mm.capture('test/*.js', 'foo/bar.css')); |
|
* //=> null |
|
* ``` |
|
* @param {String} `glob` Glob pattern to use for matching. |
|
* @param {String} `input` String to match |
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed |
|
* @return {Array|null} Returns an array of captures if the input matches the glob pattern, otherwise `null`. |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.capture = (glob, input, options)=>{ |
|
let posix = $5MQDC.isWindows(options); |
|
let regex = $2af609aa204f1181$exports.makeRe(String(glob), { |
|
...options, |
|
capture: true |
|
}); |
|
let match = regex.exec(posix ? $5MQDC.toPosixSlashes(input) : input); |
|
if (match) return match.slice(1).map((v)=>v === void 0 ? '' : v |
|
); |
|
}; |
|
/** |
|
* Create a regular expression from the given glob `pattern`. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* // mm.makeRe(pattern[, options]); |
|
* |
|
* console.log(mm.makeRe('*.js')); |
|
* //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ |
|
* ``` |
|
* @param {String} `pattern` A glob pattern to convert to regex. |
|
* @param {Object} `options` |
|
* @return {RegExp} Returns a regex created from the given pattern. |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.makeRe = (...args)=>$2af609aa204f1181$exports.makeRe(...args) |
|
; |
|
/** |
|
* Scan a glob pattern to separate the pattern into segments. Used |
|
* by the [split](#split) method. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* const state = mm.scan(pattern[, options]); |
|
* ``` |
|
* @param {String} `pattern` |
|
* @param {Object} `options` |
|
* @return {Object} Returns an object with |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.scan = (...args)=>$2af609aa204f1181$exports.scan(...args) |
|
; |
|
/** |
|
* Parse a glob pattern to create the source string for a regular |
|
* expression. |
|
* |
|
* ```js |
|
* const mm = require('micromatch'); |
|
* const state = mm(pattern[, options]); |
|
* ``` |
|
* @param {String} `glob` |
|
* @param {Object} `options` |
|
* @return {Object} Returns an object with useful properties and output to be used as regex source string. |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.parse = (patterns, options)=>{ |
|
let res = []; |
|
for (let pattern of [].concat(patterns || []))for (let str of $fec07f13db1e462a$exports(String(pattern), options))res.push($2af609aa204f1181$exports.parse(str, options)); |
|
return res; |
|
}; |
|
/** |
|
* Process the given brace `pattern`. |
|
* |
|
* ```js |
|
* const { braces } = require('micromatch'); |
|
* console.log(braces('foo/{a,b,c}/bar')); |
|
* //=> [ 'foo/(a|b|c)/bar' ] |
|
* |
|
* console.log(braces('foo/{a,b,c}/bar', { expand: true })); |
|
* //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ] |
|
* ``` |
|
* @param {String} `pattern` String with brace pattern to process. |
|
* @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options. |
|
* @return {Array} |
|
* @api public |
|
*/ $fec3b4fc54d3756a$var$micromatch.braces = (pattern, options)=>{ |
|
if (typeof pattern !== 'string') throw new TypeError('Expected a string'); |
|
if (options && options.nobrace === true || !/\{.*\}/.test(pattern)) return [ |
|
pattern |
|
]; |
|
return $fec07f13db1e462a$exports(pattern, options); |
|
}; |
|
/** |
|
* Expand braces |
|
*/ $fec3b4fc54d3756a$var$micromatch.braceExpand = (pattern, options)=>{ |
|
if (typeof pattern !== 'string') throw new TypeError('Expected a string'); |
|
return $fec3b4fc54d3756a$var$micromatch.braces(pattern, { |
|
...options, |
|
expand: true |
|
}); |
|
}; |
|
/** |
|
* Expose micromatch |
|
*/ $fec3b4fc54d3756a$exports = $fec3b4fc54d3756a$var$micromatch; |
|
|
|
|
|
const $e1fc146aea519a53$var$GLOBSTAR = '**'; |
|
const $e1fc146aea519a53$var$ESCAPE_SYMBOL = '\\'; |
|
const $e1fc146aea519a53$var$COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/; |
|
const $e1fc146aea519a53$var$REGEX_CHARACTER_CLASS_SYMBOLS_RE = /\[.*]/; |
|
const $e1fc146aea519a53$var$REGEX_GROUP_SYMBOLS_RE = /(?:^|[^@!*?+])\(.*\|.*\)/; |
|
const $e1fc146aea519a53$var$GLOB_EXTENSION_SYMBOLS_RE = /[@!*?+]\(.*\)/; |
|
const $e1fc146aea519a53$var$BRACE_EXPANSIONS_SYMBOLS_RE = /{.*(?:,|\.\.).*}/; |
|
function $e1fc146aea519a53$var$isStaticPattern(pattern, options = { |
|
}) { |
|
return !$e1fc146aea519a53$var$isDynamicPattern(pattern, options); |
|
} |
|
$e1fc146aea519a53$exports.isStaticPattern = $e1fc146aea519a53$var$isStaticPattern; |
|
function $e1fc146aea519a53$var$isDynamicPattern(pattern, options = { |
|
}) { |
|
/**
|
|
* When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check
|
|
* filepath directly (without read directory).
|
|
*/ if (options.caseSensitiveMatch === false || pattern.includes($e1fc146aea519a53$var$ESCAPE_SYMBOL)) return true; |
|
if ($e1fc146aea519a53$var$COMMON_GLOB_SYMBOLS_RE.test(pattern) || $e1fc146aea519a53$var$REGEX_CHARACTER_CLASS_SYMBOLS_RE.test(pattern) || $e1fc146aea519a53$var$REGEX_GROUP_SYMBOLS_RE.test(pattern)) return true; |
|
if (options.extglob !== false && $e1fc146aea519a53$var$GLOB_EXTENSION_SYMBOLS_RE.test(pattern)) return true; |
|
if (options.braceExpansion !== false && $e1fc146aea519a53$var$BRACE_EXPANSIONS_SYMBOLS_RE.test(pattern)) return true; |
|
return false; |
|
} |
|
$e1fc146aea519a53$exports.isDynamicPattern = $e1fc146aea519a53$var$isDynamicPattern; |
|
function $e1fc146aea519a53$var$convertToPositivePattern(pattern) { |
|
return $e1fc146aea519a53$var$isNegativePattern(pattern) ? pattern.slice(1) : pattern; |
|
} |
|
$e1fc146aea519a53$exports.convertToPositivePattern = $e1fc146aea519a53$var$convertToPositivePattern; |
|
function $e1fc146aea519a53$var$convertToNegativePattern(pattern) { |
|
return '!' + pattern; |
|
} |
|
$e1fc146aea519a53$exports.convertToNegativePattern = $e1fc146aea519a53$var$convertToNegativePattern; |
|
function $e1fc146aea519a53$var$isNegativePattern(pattern) { |
|
return pattern.startsWith('!') && pattern[1] !== '('; |
|
} |
|
$e1fc146aea519a53$exports.isNegativePattern = $e1fc146aea519a53$var$isNegativePattern; |
|
function $e1fc146aea519a53$var$isPositivePattern(pattern) { |
|
return !$e1fc146aea519a53$var$isNegativePattern(pattern); |
|
} |
|
$e1fc146aea519a53$exports.isPositivePattern = $e1fc146aea519a53$var$isPositivePattern; |
|
function $e1fc146aea519a53$var$getNegativePatterns(patterns) { |
|
return patterns.filter($e1fc146aea519a53$var$isNegativePattern); |
|
} |
|
$e1fc146aea519a53$exports.getNegativePatterns = $e1fc146aea519a53$var$getNegativePatterns; |
|
function $e1fc146aea519a53$var$getPositivePatterns(patterns) { |
|
return patterns.filter($e1fc146aea519a53$var$isPositivePattern); |
|
} |
|
$e1fc146aea519a53$exports.getPositivePatterns = $e1fc146aea519a53$var$getPositivePatterns; |
|
function $e1fc146aea519a53$var$getBaseDirectory(pattern) { |
|
return $99a21639ca3a03fc$exports(pattern, { |
|
flipBackslashes: false |
|
}); |
|
} |
|
$e1fc146aea519a53$exports.getBaseDirectory = $e1fc146aea519a53$var$getBaseDirectory; |
|
function $e1fc146aea519a53$var$hasGlobStar(pattern) { |
|
return pattern.includes($e1fc146aea519a53$var$GLOBSTAR); |
|
} |
|
$e1fc146aea519a53$exports.hasGlobStar = $e1fc146aea519a53$var$hasGlobStar; |
|
function $e1fc146aea519a53$var$endsWithSlashGlobStar(pattern) { |
|
return pattern.endsWith('/' + $e1fc146aea519a53$var$GLOBSTAR); |
|
} |
|
$e1fc146aea519a53$exports.endsWithSlashGlobStar = $e1fc146aea519a53$var$endsWithSlashGlobStar; |
|
function $e1fc146aea519a53$var$isAffectDepthOfReadingPattern(pattern) { |
|
const basename = $8C1kk$path.basename(pattern); |
|
return $e1fc146aea519a53$var$endsWithSlashGlobStar(pattern) || $e1fc146aea519a53$var$isStaticPattern(basename); |
|
} |
|
$e1fc146aea519a53$exports.isAffectDepthOfReadingPattern = $e1fc146aea519a53$var$isAffectDepthOfReadingPattern; |
|
function $e1fc146aea519a53$var$getNaiveDepth(pattern) { |
|
const base = $e1fc146aea519a53$var$getBaseDirectory(pattern); |
|
const patternDepth = pattern.split('/').length; |
|
const patternBaseDepth = base.split('/').length; |
|
/**
|
|
* This is a hack for pattern that has no base directory.
|
|
*
|
|
* This is related to the `*\something\*` pattern.
|
|
*/ if (base === '.') return patternDepth - patternBaseDepth; |
|
return patternDepth - patternBaseDepth - 1; |
|
} |
|
$e1fc146aea519a53$exports.getNaiveDepth = $e1fc146aea519a53$var$getNaiveDepth; |
|
function $e1fc146aea519a53$var$getMaxNaivePatternsDepth(patterns) { |
|
return patterns.reduce((max, pattern)=>{ |
|
const depth = $e1fc146aea519a53$var$getNaiveDepth(pattern); |
|
return depth > max ? depth : max; |
|
}, 0); |
|
} |
|
$e1fc146aea519a53$exports.getMaxNaivePatternsDepth = $e1fc146aea519a53$var$getMaxNaivePatternsDepth; |
|
function $e1fc146aea519a53$var$makeRe(pattern, options) { |
|
return $fec3b4fc54d3756a$exports.makeRe(pattern, options); |
|
} |
|
$e1fc146aea519a53$exports.makeRe = $e1fc146aea519a53$var$makeRe; |
|
function $e1fc146aea519a53$var$convertPatternsToRe(patterns, options) { |
|
return patterns.map((pattern)=>$e1fc146aea519a53$var$makeRe(pattern, options) |
|
); |
|
} |
|
$e1fc146aea519a53$exports.convertPatternsToRe = $e1fc146aea519a53$var$convertPatternsToRe; |
|
function $e1fc146aea519a53$var$matchAny(entry, patternsRe) { |
|
const filepath = entry.replace(/^\.[\\/]/, ''); |
|
return patternsRe.some((patternRe)=>patternRe.test(filepath) |
|
); |
|
} |
|
$e1fc146aea519a53$exports.matchAny = $e1fc146aea519a53$var$matchAny; |
|
|
|
|
|
$1b5b082adfcf5f99$exports.pattern = $e1fc146aea519a53$exports; |
|
var $57725c4b56279319$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($57725c4b56279319$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $62a8baa648172408$exports = {}; |
|
'use strict'; |
|
|
|
const $62a8baa648172408$var$PassThrough = $8C1kk$stream.PassThrough; |
|
const $62a8baa648172408$var$slice = Array.prototype.slice; |
|
$62a8baa648172408$exports = $62a8baa648172408$var$merge2; |
|
function $62a8baa648172408$var$merge2() { |
|
const streamsQueue = []; |
|
let merging = false; |
|
const args = $62a8baa648172408$var$slice.call(arguments); |
|
let options = args[args.length - 1]; |
|
if (options && !Array.isArray(options) && options.pipe == null) args.pop(); |
|
else options = { |
|
}; |
|
const doEnd = options.end !== false; |
|
if (options.objectMode == null) options.objectMode = true; |
|
if (options.highWaterMark == null) options.highWaterMark = 65536; |
|
const mergedStream = $62a8baa648172408$var$PassThrough(options); |
|
function addStream() { |
|
for(let i = 0, len = arguments.length; i < len; i++)streamsQueue.push($62a8baa648172408$var$pauseStreams(arguments[i], options)); |
|
mergeStream(); |
|
return this; |
|
} |
|
function mergeStream() { |
|
if (merging) return; |
|
merging = true; |
|
let streams = streamsQueue.shift(); |
|
if (!streams) { |
|
process.nextTick(endStream); |
|
return; |
|
} |
|
if (!Array.isArray(streams)) streams = [ |
|
streams |
|
]; |
|
let pipesCount = streams.length + 1; |
|
function next() { |
|
if (--pipesCount > 0) return; |
|
merging = false; |
|
mergeStream(); |
|
} |
|
function pipe(stream) { |
|
function onend() { |
|
stream.removeListener('merge2UnpipeEnd', onend); |
|
stream.removeListener('end', onend); |
|
next(); |
|
} |
|
// skip ended stream |
|
if (stream._readableState.endEmitted) return next(); |
|
stream.on('merge2UnpipeEnd', onend); |
|
stream.on('end', onend); |
|
stream.pipe(mergedStream, { |
|
end: false |
|
}); |
|
// compatible for old stream |
|
stream.resume(); |
|
} |
|
for(let i = 0; i < streams.length; i++)pipe(streams[i]); |
|
next(); |
|
} |
|
function endStream() { |
|
merging = false; |
|
// emit 'queueDrain' when all streams merged. |
|
mergedStream.emit('queueDrain'); |
|
return doEnd && mergedStream.end(); |
|
} |
|
mergedStream.setMaxListeners(0); |
|
mergedStream.add = addStream; |
|
mergedStream.on('unpipe', function(stream) { |
|
stream.emit('merge2UnpipeEnd'); |
|
}); |
|
if (args.length) addStream.apply(null, args); |
|
return mergedStream; |
|
} |
|
// check and pause streams for pipe. |
|
function $62a8baa648172408$var$pauseStreams(streams, options) { |
|
if (!Array.isArray(streams)) { |
|
// Backwards-compat with old-style streams |
|
if (!streams._readableState && streams.pipe) streams = streams.pipe($62a8baa648172408$var$PassThrough(options)); |
|
if (!streams._readableState || !streams.pause || !streams.pipe) throw new Error('Only readable stream can be merged.'); |
|
streams.pause(); |
|
} else for(let i = 0, len = streams.length; i < len; i++)streams[i] = $62a8baa648172408$var$pauseStreams(streams[i], options); |
|
return streams; |
|
} |
|
|
|
|
|
function $57725c4b56279319$var$merge(streams) { |
|
const mergedStream = $62a8baa648172408$exports(streams); |
|
streams.forEach((stream)=>{ |
|
stream.once('error', (error)=>mergedStream.emit('error', error) |
|
); |
|
}); |
|
mergedStream.once('close', ()=>$57725c4b56279319$var$propagateCloseEventToSources(streams) |
|
); |
|
mergedStream.once('end', ()=>$57725c4b56279319$var$propagateCloseEventToSources(streams) |
|
); |
|
return mergedStream; |
|
} |
|
$57725c4b56279319$exports.merge = $57725c4b56279319$var$merge; |
|
function $57725c4b56279319$var$propagateCloseEventToSources(streams) { |
|
streams.forEach((stream)=>stream.emit('close') |
|
); |
|
} |
|
|
|
|
|
$1b5b082adfcf5f99$exports.stream = $57725c4b56279319$exports; |
|
|
|
|
|
function $d436392a45e5b9b4$var$generate(patterns, settings) { |
|
const positivePatterns = $d436392a45e5b9b4$var$getPositivePatterns(patterns); |
|
const negativePatterns = $d436392a45e5b9b4$var$getNegativePatternsAsPositive(patterns, settings.ignore); |
|
const staticPatterns = positivePatterns.filter((pattern)=>$1b5b082adfcf5f99$exports.pattern.isStaticPattern(pattern, settings) |
|
); |
|
const dynamicPatterns = positivePatterns.filter((pattern)=>$1b5b082adfcf5f99$exports.pattern.isDynamicPattern(pattern, settings) |
|
); |
|
const staticTasks = $d436392a45e5b9b4$var$convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false); |
|
const dynamicTasks = $d436392a45e5b9b4$var$convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true); |
|
return staticTasks.concat(dynamicTasks); |
|
} |
|
$d436392a45e5b9b4$exports.generate = $d436392a45e5b9b4$var$generate; |
|
function $d436392a45e5b9b4$var$convertPatternsToTasks(positive, negative, dynamic) { |
|
const positivePatternsGroup = $d436392a45e5b9b4$var$groupPatternsByBaseDirectory(positive); |
|
// When we have a global group – there is no reason to divide the patterns into independent tasks. |
|
// In this case, the global task covers the rest. |
|
if ('.' in positivePatternsGroup) { |
|
const task = $d436392a45e5b9b4$var$convertPatternGroupToTask('.', positive, negative, dynamic); |
|
return [ |
|
task |
|
]; |
|
} |
|
return $d436392a45e5b9b4$var$convertPatternGroupsToTasks(positivePatternsGroup, negative, dynamic); |
|
} |
|
$d436392a45e5b9b4$exports.convertPatternsToTasks = $d436392a45e5b9b4$var$convertPatternsToTasks; |
|
function $d436392a45e5b9b4$var$getPositivePatterns(patterns) { |
|
return $1b5b082adfcf5f99$exports.pattern.getPositivePatterns(patterns); |
|
} |
|
$d436392a45e5b9b4$exports.getPositivePatterns = $d436392a45e5b9b4$var$getPositivePatterns; |
|
function $d436392a45e5b9b4$var$getNegativePatternsAsPositive(patterns, ignore) { |
|
const negative = $1b5b082adfcf5f99$exports.pattern.getNegativePatterns(patterns).concat(ignore); |
|
const positive = negative.map($1b5b082adfcf5f99$exports.pattern.convertToPositivePattern); |
|
return positive; |
|
} |
|
$d436392a45e5b9b4$exports.getNegativePatternsAsPositive = $d436392a45e5b9b4$var$getNegativePatternsAsPositive; |
|
function $d436392a45e5b9b4$var$groupPatternsByBaseDirectory(patterns) { |
|
const group = { |
|
}; |
|
return patterns.reduce((collection, pattern)=>{ |
|
const base = $1b5b082adfcf5f99$exports.pattern.getBaseDirectory(pattern); |
|
if (base in collection) collection[base].push(pattern); |
|
else collection[base] = [ |
|
pattern |
|
]; |
|
return collection; |
|
}, group); |
|
} |
|
$d436392a45e5b9b4$exports.groupPatternsByBaseDirectory = $d436392a45e5b9b4$var$groupPatternsByBaseDirectory; |
|
function $d436392a45e5b9b4$var$convertPatternGroupsToTasks(positive, negative, dynamic) { |
|
return Object.keys(positive).map((base)=>{ |
|
return $d436392a45e5b9b4$var$convertPatternGroupToTask(base, positive[base], negative, dynamic); |
|
}); |
|
} |
|
$d436392a45e5b9b4$exports.convertPatternGroupsToTasks = $d436392a45e5b9b4$var$convertPatternGroupsToTasks; |
|
function $d436392a45e5b9b4$var$convertPatternGroupToTask(base, positive, negative, dynamic) { |
|
return { |
|
dynamic: dynamic, |
|
positive: positive, |
|
negative: negative, |
|
base: base, |
|
patterns: [].concat(positive, negative.map($1b5b082adfcf5f99$exports.pattern.convertToNegativePattern)) |
|
}; |
|
} |
|
$d436392a45e5b9b4$exports.convertPatternGroupToTask = $d436392a45e5b9b4$var$convertPatternGroupToTask; |
|
|
|
|
|
var $5e8aeb81d3971f46$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($5e8aeb81d3971f46$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $f93330d45af3b4cf$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($f93330d45af3b4cf$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
var $6c0caade5edaab5b$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($6c0caade5edaab5b$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $4fbfd3060e7caace$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($4fbfd3060e7caace$exports, "__esModule", { |
|
value: true |
|
}); |
|
function $4fbfd3060e7caace$var$read(path, settings, callback) { |
|
settings.fs.lstat(path, (lstatError, lstat)=>{ |
|
if (lstatError !== null) return $4fbfd3060e7caace$var$callFailureCallback(callback, lstatError); |
|
if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) return $4fbfd3060e7caace$var$callSuccessCallback(callback, lstat); |
|
settings.fs.stat(path, (statError, stat)=>{ |
|
if (statError !== null) { |
|
if (settings.throwErrorOnBrokenSymbolicLink) return $4fbfd3060e7caace$var$callFailureCallback(callback, statError); |
|
return $4fbfd3060e7caace$var$callSuccessCallback(callback, lstat); |
|
} |
|
if (settings.markSymbolicLink) stat.isSymbolicLink = ()=>true |
|
; |
|
$4fbfd3060e7caace$var$callSuccessCallback(callback, stat); |
|
}); |
|
}); |
|
} |
|
$4fbfd3060e7caace$exports.read = $4fbfd3060e7caace$var$read; |
|
function $4fbfd3060e7caace$var$callFailureCallback(callback, error) { |
|
callback(error); |
|
} |
|
function $4fbfd3060e7caace$var$callSuccessCallback(callback, result) { |
|
callback(null, result); |
|
} |
|
|
|
|
|
var $dc5606dc29aa77a7$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($dc5606dc29aa77a7$exports, "__esModule", { |
|
value: true |
|
}); |
|
function $dc5606dc29aa77a7$var$read(path, settings) { |
|
const lstat = settings.fs.lstatSync(path); |
|
if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) return lstat; |
|
try { |
|
const stat = settings.fs.statSync(path); |
|
if (settings.markSymbolicLink) stat.isSymbolicLink = ()=>true |
|
; |
|
return stat; |
|
} catch (error) { |
|
if (!settings.throwErrorOnBrokenSymbolicLink) return lstat; |
|
throw error; |
|
} |
|
} |
|
$dc5606dc29aa77a7$exports.read = $dc5606dc29aa77a7$var$read; |
|
|
|
|
|
var $ef1fb79f0bdf5fd9$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($ef1fb79f0bdf5fd9$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $63feca573ea7b7b0$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($63feca573ea7b7b0$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
$63feca573ea7b7b0$exports.FILE_SYSTEM_ADAPTER = { |
|
lstat: $8C1kk$fs.lstat, |
|
stat: $8C1kk$fs.stat, |
|
lstatSync: $8C1kk$fs.lstatSync, |
|
statSync: $8C1kk$fs.statSync |
|
}; |
|
function $63feca573ea7b7b0$var$createFileSystemAdapter(fsMethods) { |
|
if (fsMethods === undefined) return $63feca573ea7b7b0$exports.FILE_SYSTEM_ADAPTER; |
|
return Object.assign(Object.assign({ |
|
}, $63feca573ea7b7b0$exports.FILE_SYSTEM_ADAPTER), fsMethods); |
|
} |
|
$63feca573ea7b7b0$exports.createFileSystemAdapter = $63feca573ea7b7b0$var$createFileSystemAdapter; |
|
|
|
|
|
class $ef1fb79f0bdf5fd9$var$Settings { |
|
constructor(_options = { |
|
}){ |
|
this._options = _options; |
|
this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true); |
|
this.fs = $63feca573ea7b7b0$exports.createFileSystemAdapter(this._options.fs); |
|
this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false); |
|
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); |
|
} |
|
_getValue(option, value) { |
|
return option === undefined ? value : option; |
|
} |
|
} |
|
$ef1fb79f0bdf5fd9$exports.default = $ef1fb79f0bdf5fd9$var$Settings; |
|
|
|
|
|
$6c0caade5edaab5b$exports.Settings = $ef1fb79f0bdf5fd9$exports.default; |
|
function $6c0caade5edaab5b$var$stat(path, optionsOrSettingsOrCallback, callback) { |
|
if (typeof optionsOrSettingsOrCallback === 'function') return $4fbfd3060e7caace$exports.read(path, $6c0caade5edaab5b$var$getSettings(), optionsOrSettingsOrCallback); |
|
$4fbfd3060e7caace$exports.read(path, $6c0caade5edaab5b$var$getSettings(optionsOrSettingsOrCallback), callback); |
|
} |
|
$6c0caade5edaab5b$exports.stat = $6c0caade5edaab5b$var$stat; |
|
function $6c0caade5edaab5b$var$statSync(path, optionsOrSettings) { |
|
const settings = $6c0caade5edaab5b$var$getSettings(optionsOrSettings); |
|
return $dc5606dc29aa77a7$exports.read(path, settings); |
|
} |
|
$6c0caade5edaab5b$exports.statSync = $6c0caade5edaab5b$var$statSync; |
|
function $6c0caade5edaab5b$var$getSettings(settingsOrOptions = { |
|
}) { |
|
if (settingsOrOptions instanceof $ef1fb79f0bdf5fd9$exports.default) return settingsOrOptions; |
|
return new $ef1fb79f0bdf5fd9$exports.default(settingsOrOptions); |
|
} |
|
|
|
|
|
var $798d916015b2c927$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($798d916015b2c927$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $dbc0921597fb36f9$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($dbc0921597fb36f9$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $2fa2a8e52edb0b77$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($2fa2a8e52edb0b77$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
var $6e9dd7fa450f205e$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($6e9dd7fa450f205e$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $214d283d2b9ddc47$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($214d283d2b9ddc47$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
var $464bce01c537cfdb$exports = {}; |
|
$464bce01c537cfdb$exports = $464bce01c537cfdb$var$runParallel; |
|
function $464bce01c537cfdb$var$runParallel(tasks, cb) { |
|
var results, pending, keys; |
|
var isSync = true; |
|
if (Array.isArray(tasks)) { |
|
results = []; |
|
pending = tasks.length; |
|
} else { |
|
keys = Object.keys(tasks); |
|
results = { |
|
}; |
|
pending = keys.length; |
|
} |
|
function done(err) { |
|
function end() { |
|
if (cb) cb(err, results); |
|
cb = null; |
|
} |
|
if (isSync) process.nextTick(end); |
|
else end(); |
|
} |
|
function each(i, err, result) { |
|
results[i] = result; |
|
if (--pending === 0 || err) done(err); |
|
} |
|
if (!pending) // empty |
|
done(null); |
|
else if (keys) // object |
|
keys.forEach(function(key) { |
|
tasks[key](function(err, result) { |
|
each(key, err, result); |
|
}); |
|
}); |
|
else // array |
|
tasks.forEach(function(task, i) { |
|
task(function(err, result) { |
|
each(i, err, result); |
|
}); |
|
}); |
|
isSync = false; |
|
} |
|
|
|
|
|
var $48b2fc7e240f8d0a$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($48b2fc7e240f8d0a$exports, "__esModule", { |
|
value: true |
|
}); |
|
const $48b2fc7e240f8d0a$var$NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.'); |
|
const $48b2fc7e240f8d0a$var$MAJOR_VERSION = parseInt($48b2fc7e240f8d0a$var$NODE_PROCESS_VERSION_PARTS[0], 10); |
|
const $48b2fc7e240f8d0a$var$MINOR_VERSION = parseInt($48b2fc7e240f8d0a$var$NODE_PROCESS_VERSION_PARTS[1], 10); |
|
const $48b2fc7e240f8d0a$var$SUPPORTED_MAJOR_VERSION = 10; |
|
const $48b2fc7e240f8d0a$var$SUPPORTED_MINOR_VERSION = 10; |
|
const $48b2fc7e240f8d0a$var$IS_MATCHED_BY_MAJOR = $48b2fc7e240f8d0a$var$MAJOR_VERSION > $48b2fc7e240f8d0a$var$SUPPORTED_MAJOR_VERSION; |
|
const $48b2fc7e240f8d0a$var$IS_MATCHED_BY_MAJOR_AND_MINOR = $48b2fc7e240f8d0a$var$MAJOR_VERSION === $48b2fc7e240f8d0a$var$SUPPORTED_MAJOR_VERSION && $48b2fc7e240f8d0a$var$MINOR_VERSION >= $48b2fc7e240f8d0a$var$SUPPORTED_MINOR_VERSION; |
|
/**
|
|
* IS `true` for Node.js 10.10 and greater.
|
|
*/ $48b2fc7e240f8d0a$exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = $48b2fc7e240f8d0a$var$IS_MATCHED_BY_MAJOR || $48b2fc7e240f8d0a$var$IS_MATCHED_BY_MAJOR_AND_MINOR; |
|
|
|
|
|
var $9072c856789f321b$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($9072c856789f321b$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $785ad51956fbd1c9$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($785ad51956fbd1c9$exports, "__esModule", { |
|
value: true |
|
}); |
|
class $785ad51956fbd1c9$var$DirentFromStats { |
|
constructor(name, stats){ |
|
this.name = name; |
|
this.isBlockDevice = stats.isBlockDevice.bind(stats); |
|
this.isCharacterDevice = stats.isCharacterDevice.bind(stats); |
|
this.isDirectory = stats.isDirectory.bind(stats); |
|
this.isFIFO = stats.isFIFO.bind(stats); |
|
this.isFile = stats.isFile.bind(stats); |
|
this.isSocket = stats.isSocket.bind(stats); |
|
this.isSymbolicLink = stats.isSymbolicLink.bind(stats); |
|
} |
|
} |
|
function $785ad51956fbd1c9$var$createDirentFromStats(name, stats) { |
|
return new $785ad51956fbd1c9$var$DirentFromStats(name, stats); |
|
} |
|
$785ad51956fbd1c9$exports.createDirentFromStats = $785ad51956fbd1c9$var$createDirentFromStats; |
|
|
|
|
|
$9072c856789f321b$exports.fs = $785ad51956fbd1c9$exports; |
|
|
|
|
|
function $214d283d2b9ddc47$var$read(directory, settings, callback) { |
|
if (!settings.stats && $48b2fc7e240f8d0a$exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES) return $214d283d2b9ddc47$var$readdirWithFileTypes(directory, settings, callback); |
|
return $214d283d2b9ddc47$var$readdir(directory, settings, callback); |
|
} |
|
$214d283d2b9ddc47$exports.read = $214d283d2b9ddc47$var$read; |
|
function $214d283d2b9ddc47$var$readdirWithFileTypes(directory, settings, callback) { |
|
settings.fs.readdir(directory, { |
|
withFileTypes: true |
|
}, (readdirError, dirents)=>{ |
|
if (readdirError !== null) return $214d283d2b9ddc47$var$callFailureCallback(callback, readdirError); |
|
const entries = dirents.map((dirent)=>({ |
|
dirent: dirent, |
|
name: dirent.name, |
|
path: `${directory}${settings.pathSegmentSeparator}${dirent.name}` |
|
}) |
|
); |
|
if (!settings.followSymbolicLinks) return $214d283d2b9ddc47$var$callSuccessCallback(callback, entries); |
|
const tasks = entries.map((entry)=>$214d283d2b9ddc47$var$makeRplTaskEntry(entry, settings) |
|
); |
|
$464bce01c537cfdb$exports(tasks, (rplError, rplEntries)=>{ |
|
if (rplError !== null) return $214d283d2b9ddc47$var$callFailureCallback(callback, rplError); |
|
$214d283d2b9ddc47$var$callSuccessCallback(callback, rplEntries); |
|
}); |
|
}); |
|
} |
|
$214d283d2b9ddc47$exports.readdirWithFileTypes = $214d283d2b9ddc47$var$readdirWithFileTypes; |
|
function $214d283d2b9ddc47$var$makeRplTaskEntry(entry, settings) { |
|
return (done)=>{ |
|
if (!entry.dirent.isSymbolicLink()) return done(null, entry); |
|
settings.fs.stat(entry.path, (statError, stats)=>{ |
|
if (statError !== null) { |
|
if (settings.throwErrorOnBrokenSymbolicLink) return done(statError); |
|
return done(null, entry); |
|
} |
|
entry.dirent = $9072c856789f321b$exports.fs.createDirentFromStats(entry.name, stats); |
|
return done(null, entry); |
|
}); |
|
}; |
|
} |
|
function $214d283d2b9ddc47$var$readdir(directory, settings, callback) { |
|
settings.fs.readdir(directory, (readdirError, names)=>{ |
|
if (readdirError !== null) return $214d283d2b9ddc47$var$callFailureCallback(callback, readdirError); |
|
const filepaths = names.map((name)=>`${directory}${settings.pathSegmentSeparator}${name}` |
|
); |
|
const tasks = filepaths.map((filepath)=>{ |
|
return (done)=>$6c0caade5edaab5b$exports.stat(filepath, settings.fsStatSettings, done) |
|
; |
|
}); |
|
$464bce01c537cfdb$exports(tasks, (rplError, results)=>{ |
|
if (rplError !== null) return $214d283d2b9ddc47$var$callFailureCallback(callback, rplError); |
|
const entries = []; |
|
names.forEach((name, index)=>{ |
|
const stats = results[index]; |
|
const entry = { |
|
name: name, |
|
path: filepaths[index], |
|
dirent: $9072c856789f321b$exports.fs.createDirentFromStats(name, stats) |
|
}; |
|
if (settings.stats) entry.stats = stats; |
|
entries.push(entry); |
|
}); |
|
$214d283d2b9ddc47$var$callSuccessCallback(callback, entries); |
|
}); |
|
}); |
|
} |
|
$214d283d2b9ddc47$exports.readdir = $214d283d2b9ddc47$var$readdir; |
|
function $214d283d2b9ddc47$var$callFailureCallback(callback, error) { |
|
callback(error); |
|
} |
|
function $214d283d2b9ddc47$var$callSuccessCallback(callback, result) { |
|
callback(null, result); |
|
} |
|
|
|
|
|
var $b552b4f86bca374b$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($b552b4f86bca374b$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
|
|
|
|
function $b552b4f86bca374b$var$read(directory, settings) { |
|
if (!settings.stats && $48b2fc7e240f8d0a$exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES) return $b552b4f86bca374b$var$readdirWithFileTypes(directory, settings); |
|
return $b552b4f86bca374b$var$readdir(directory, settings); |
|
} |
|
$b552b4f86bca374b$exports.read = $b552b4f86bca374b$var$read; |
|
function $b552b4f86bca374b$var$readdirWithFileTypes(directory, settings) { |
|
const dirents = settings.fs.readdirSync(directory, { |
|
withFileTypes: true |
|
}); |
|
return dirents.map((dirent)=>{ |
|
const entry = { |
|
dirent: dirent, |
|
name: dirent.name, |
|
path: `${directory}${settings.pathSegmentSeparator}${dirent.name}` |
|
}; |
|
if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) try { |
|
const stats = settings.fs.statSync(entry.path); |
|
entry.dirent = $9072c856789f321b$exports.fs.createDirentFromStats(entry.name, stats); |
|
} catch (error) { |
|
if (settings.throwErrorOnBrokenSymbolicLink) throw error; |
|
} |
|
return entry; |
|
}); |
|
} |
|
$b552b4f86bca374b$exports.readdirWithFileTypes = $b552b4f86bca374b$var$readdirWithFileTypes; |
|
function $b552b4f86bca374b$var$readdir(directory, settings) { |
|
const names = settings.fs.readdirSync(directory); |
|
return names.map((name)=>{ |
|
const entryPath = `${directory}${settings.pathSegmentSeparator}${name}`; |
|
const stats = $6c0caade5edaab5b$exports.statSync(entryPath, settings.fsStatSettings); |
|
const entry = { |
|
name: name, |
|
path: entryPath, |
|
dirent: $9072c856789f321b$exports.fs.createDirentFromStats(name, stats) |
|
}; |
|
if (settings.stats) entry.stats = stats; |
|
return entry; |
|
}); |
|
} |
|
$b552b4f86bca374b$exports.readdir = $b552b4f86bca374b$var$readdir; |
|
|
|
|
|
var $3dcdbb61bc2266b4$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($3dcdbb61bc2266b4$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
|
|
var $150cb26c808670af$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($150cb26c808670af$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
$150cb26c808670af$exports.FILE_SYSTEM_ADAPTER = { |
|
lstat: $8C1kk$fs.lstat, |
|
stat: $8C1kk$fs.stat, |
|
lstatSync: $8C1kk$fs.lstatSync, |
|
statSync: $8C1kk$fs.statSync, |
|
readdir: $8C1kk$fs.readdir, |
|
readdirSync: $8C1kk$fs.readdirSync |
|
}; |
|
function $150cb26c808670af$var$createFileSystemAdapter(fsMethods) { |
|
if (fsMethods === undefined) return $150cb26c808670af$exports.FILE_SYSTEM_ADAPTER; |
|
return Object.assign(Object.assign({ |
|
}, $150cb26c808670af$exports.FILE_SYSTEM_ADAPTER), fsMethods); |
|
} |
|
$150cb26c808670af$exports.createFileSystemAdapter = $150cb26c808670af$var$createFileSystemAdapter; |
|
|
|
|
|
class $3dcdbb61bc2266b4$var$Settings { |
|
constructor(_options = { |
|
}){ |
|
this._options = _options; |
|
this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false); |
|
this.fs = $150cb26c808670af$exports.createFileSystemAdapter(this._options.fs); |
|
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, $8C1kk$path.sep); |
|
this.stats = this._getValue(this._options.stats, false); |
|
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); |
|
this.fsStatSettings = new $6c0caade5edaab5b$exports.Settings({ |
|
followSymbolicLink: this.followSymbolicLinks, |
|
fs: this.fs, |
|
throwErrorOnBrokenSymbolicLink: this.throwErrorOnBrokenSymbolicLink |
|
}); |
|
} |
|
_getValue(option, value) { |
|
return option === undefined ? value : option; |
|
} |
|
} |
|
$3dcdbb61bc2266b4$exports.default = $3dcdbb61bc2266b4$var$Settings; |
|
|
|
|
|
$6e9dd7fa450f205e$exports.Settings = $3dcdbb61bc2266b4$exports.default; |
|
function $6e9dd7fa450f205e$var$scandir(path, optionsOrSettingsOrCallback, callback) { |
|
if (typeof optionsOrSettingsOrCallback === 'function') return $214d283d2b9ddc47$exports.read(path, $6e9dd7fa450f205e$var$getSettings(), optionsOrSettingsOrCallback); |
|
$214d283d2b9ddc47$exports.read(path, $6e9dd7fa450f205e$var$getSettings(optionsOrSettingsOrCallback), callback); |
|
} |
|
$6e9dd7fa450f205e$exports.scandir = $6e9dd7fa450f205e$var$scandir; |
|
function $6e9dd7fa450f205e$var$scandirSync(path, optionsOrSettings) { |
|
const settings = $6e9dd7fa450f205e$var$getSettings(optionsOrSettings); |
|
return $b552b4f86bca374b$exports.read(path, settings); |
|
} |
|
$6e9dd7fa450f205e$exports.scandirSync = $6e9dd7fa450f205e$var$scandirSync; |
|
function $6e9dd7fa450f205e$var$getSettings(settingsOrOptions = { |
|
}) { |
|
if (settingsOrOptions instanceof $3dcdbb61bc2266b4$exports.default) return settingsOrOptions; |
|
return new $3dcdbb61bc2266b4$exports.default(settingsOrOptions); |
|
} |
|
|
|
|
|
var $4609f2cae016f1ac$exports = {}; |
|
'use strict'; |
|
var $e955c806e75ef6f8$exports = {}; |
|
'use strict'; |
|
function $e955c806e75ef6f8$var$reusify(Constructor) { |
|
var head = new Constructor(); |
|
var tail = head; |
|
function get() { |
|
var current = head; |
|
if (current.next) head = current.next; |
|
else { |
|
head = new Constructor(); |
|
tail = head; |
|
} |
|
current.next = null; |
|
return current; |
|
} |
|
function release(obj) { |
|
tail.next = obj; |
|
tail = obj; |
|
} |
|
return { |
|
get: get, |
|
release: release |
|
}; |
|
} |
|
$e955c806e75ef6f8$exports = $e955c806e75ef6f8$var$reusify; |
|
|
|
|
|
function $4609f2cae016f1ac$var$fastqueue(context, worker, concurrency) { |
|
if (typeof context === 'function') { |
|
concurrency = worker; |
|
worker = context; |
|
context = null; |
|
} |
|
var cache = $e955c806e75ef6f8$exports($4609f2cae016f1ac$var$Task); |
|
var queueHead = null; |
|
var queueTail = null; |
|
var _running = 0; |
|
var self = { |
|
push: push, |
|
drain: $4609f2cae016f1ac$var$noop, |
|
saturated: $4609f2cae016f1ac$var$noop, |
|
pause: pause, |
|
paused: false, |
|
concurrency: concurrency, |
|
running: running, |
|
resume: resume, |
|
idle: idle, |
|
length: length, |
|
unshift: unshift, |
|
empty: $4609f2cae016f1ac$var$noop, |
|
kill: kill, |
|
killAndDrain: killAndDrain |
|
}; |
|
function running() { |
|
return _running; |
|
} |
|
function pause() { |
|
self.paused = true; |
|
} |
|
function length() { |
|
var current = queueHead; |
|
var counter = 0; |
|
while(current){ |
|
current = current.next; |
|
counter++; |
|
} |
|
return counter; |
|
} |
|
function resume() { |
|
if (!self.paused) return; |
|
self.paused = false; |
|
for(var i = 0; i < self.concurrency; i++){ |
|
_running++; |
|
release(); |
|
} |
|
} |
|
function idle() { |
|
return _running === 0 && self.length() === 0; |
|
} |
|
function push(value, done) { |
|
var current = cache.get(); |
|
current.context = context; |
|
current.release = release; |
|
current.value = value; |
|
current.callback = done || $4609f2cae016f1ac$var$noop; |
|
if (_running === self.concurrency || self.paused) { |
|
if (queueTail) { |
|
queueTail.next = current; |
|
queueTail = current; |
|
} else { |
|
queueHead = current; |
|
queueTail = current; |
|
self.saturated(); |
|
} |
|
} else { |
|
_running++; |
|
worker.call(context, current.value, current.worked); |
|
} |
|
} |
|
function unshift(value, done) { |
|
var current = cache.get(); |
|
current.context = context; |
|
current.release = release; |
|
current.value = value; |
|
current.callback = done || $4609f2cae016f1ac$var$noop; |
|
if (_running === self.concurrency || self.paused) { |
|
if (queueHead) { |
|
current.next = queueHead; |
|
queueHead = current; |
|
} else { |
|
queueHead = current; |
|
queueTail = current; |
|
self.saturated(); |
|
} |
|
} else { |
|
_running++; |
|
worker.call(context, current.value, current.worked); |
|
} |
|
} |
|
function release(holder) { |
|
if (holder) { |
|
cache.release(holder); |
|
} |
|
var next = queueHead; |
|
if (next) { |
|
if (!self.paused) { |
|
if (queueTail === queueHead) { |
|
queueTail = null; |
|
} |
|
queueHead = next.next; |
|
next.next = null; |
|
worker.call(context, next.value, next.worked); |
|
if (queueTail === null) { |
|
self.empty(); |
|
} |
|
} else { |
|
_running--; |
|
} |
|
} else if (--_running === 0) { |
|
self.drain(); |
|
} |
|
} |
|
function kill() { |
|
queueHead = null; |
|
queueTail = null; |
|
self.drain = $4609f2cae016f1ac$var$noop; |
|
} |
|
function killAndDrain() { |
|
queueHead = null; |
|
queueTail = null; |
|
self.drain(); |
|
self.drain = $4609f2cae016f1ac$var$noop; |
|
} |
|
return self; |
|
} |
|
function $4609f2cae016f1ac$var$noop() { |
|
} |
|
function $4609f2cae016f1ac$var$Task() { |
|
this.value = null; |
|
this.callback = $4609f2cae016f1ac$var$noop; |
|
this.next = null; |
|
this.release = $4609f2cae016f1ac$var$noop; |
|
this.context = null; |
|
var self = this; |
|
this.worked = function worked(err, result) { |
|
var callback = self.callback; |
|
self.value = null; |
|
self.callback = $4609f2cae016f1ac$var$noop; |
|
callback.call(self.context, err, result); |
|
self.release(self); |
|
}; |
|
} |
|
$4609f2cae016f1ac$exports = $4609f2cae016f1ac$var$fastqueue; |
|
|
|
|
|
var $e6d58630eaa29e9b$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($e6d58630eaa29e9b$exports, "__esModule", { |
|
value: true |
|
}); |
|
function $e6d58630eaa29e9b$var$isFatalError(settings, error) { |
|
if (settings.errorFilter === null) return true; |
|
return !settings.errorFilter(error); |
|
} |
|
$e6d58630eaa29e9b$exports.isFatalError = $e6d58630eaa29e9b$var$isFatalError; |
|
function $e6d58630eaa29e9b$var$isAppliedFilter(filter, value) { |
|
return filter === null || filter(value); |
|
} |
|
$e6d58630eaa29e9b$exports.isAppliedFilter = $e6d58630eaa29e9b$var$isAppliedFilter; |
|
function $e6d58630eaa29e9b$var$replacePathSegmentSeparator(filepath, separator) { |
|
return filepath.split(/[\\/]/).join(separator); |
|
} |
|
$e6d58630eaa29e9b$exports.replacePathSegmentSeparator = $e6d58630eaa29e9b$var$replacePathSegmentSeparator; |
|
function $e6d58630eaa29e9b$var$joinPathSegments(a, b, separator) { |
|
if (a === '') return b; |
|
return a + separator + b; |
|
} |
|
$e6d58630eaa29e9b$exports.joinPathSegments = $e6d58630eaa29e9b$var$joinPathSegments; |
|
|
|
|
|
var $e2f1a4546d061960$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($e2f1a4546d061960$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
class $e2f1a4546d061960$var$Reader { |
|
constructor(_root, _settings){ |
|
this._root = _root; |
|
this._settings = _settings; |
|
this._root = $e6d58630eaa29e9b$exports.replacePathSegmentSeparator(_root, _settings.pathSegmentSeparator); |
|
} |
|
} |
|
$e2f1a4546d061960$exports.default = $e2f1a4546d061960$var$Reader; |
|
|
|
|
|
class $2fa2a8e52edb0b77$var$AsyncReader extends $e2f1a4546d061960$exports.default { |
|
constructor(_root, _settings){ |
|
super(_root, _settings); |
|
this._settings = _settings; |
|
this._scandir = $6e9dd7fa450f205e$exports.scandir; |
|
this._emitter = new $8C1kk$events.EventEmitter(); |
|
this._queue = $4609f2cae016f1ac$exports(this._worker.bind(this), this._settings.concurrency); |
|
this._isFatalError = false; |
|
this._isDestroyed = false; |
|
this._queue.drain = ()=>{ |
|
if (!this._isFatalError) this._emitter.emit('end'); |
|
}; |
|
} |
|
read() { |
|
this._isFatalError = false; |
|
this._isDestroyed = false; |
|
setImmediate(()=>{ |
|
this._pushToQueue(this._root, this._settings.basePath); |
|
}); |
|
return this._emitter; |
|
} |
|
destroy() { |
|
if (this._isDestroyed) throw new Error('The reader is already destroyed'); |
|
this._isDestroyed = true; |
|
this._queue.killAndDrain(); |
|
} |
|
onEntry(callback) { |
|
this._emitter.on('entry', callback); |
|
} |
|
onError(callback) { |
|
this._emitter.once('error', callback); |
|
} |
|
onEnd(callback) { |
|
this._emitter.once('end', callback); |
|
} |
|
_pushToQueue(directory, base) { |
|
const queueItem = { |
|
directory: directory, |
|
base: base |
|
}; |
|
this._queue.push(queueItem, (error)=>{ |
|
if (error !== null) this._handleError(error); |
|
}); |
|
} |
|
_worker(item, done) { |
|
this._scandir(item.directory, this._settings.fsScandirSettings, (error, entries)=>{ |
|
if (error !== null) return done(error, undefined); |
|
for (const entry of entries)this._handleEntry(entry, item.base); |
|
done(null, undefined); |
|
}); |
|
} |
|
_handleError(error) { |
|
if (!$e6d58630eaa29e9b$exports.isFatalError(this._settings, error)) return; |
|
this._isFatalError = true; |
|
this._isDestroyed = true; |
|
this._emitter.emit('error', error); |
|
} |
|
_handleEntry(entry, base) { |
|
if (this._isDestroyed || this._isFatalError) return; |
|
const fullpath = entry.path; |
|
if (base !== undefined) entry.path = $e6d58630eaa29e9b$exports.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); |
|
if ($e6d58630eaa29e9b$exports.isAppliedFilter(this._settings.entryFilter, entry)) this._emitEntry(entry); |
|
if (entry.dirent.isDirectory() && $e6d58630eaa29e9b$exports.isAppliedFilter(this._settings.deepFilter, entry)) this._pushToQueue(fullpath, entry.path); |
|
} |
|
_emitEntry(entry) { |
|
this._emitter.emit('entry', entry); |
|
} |
|
} |
|
$2fa2a8e52edb0b77$exports.default = $2fa2a8e52edb0b77$var$AsyncReader; |
|
|
|
|
|
class $dbc0921597fb36f9$var$AsyncProvider { |
|
constructor(_root, _settings){ |
|
this._root = _root; |
|
this._settings = _settings; |
|
this._reader = new $2fa2a8e52edb0b77$exports.default(this._root, this._settings); |
|
this._storage = new Set(); |
|
} |
|
read(callback) { |
|
this._reader.onError((error)=>{ |
|
$dbc0921597fb36f9$var$callFailureCallback(callback, error); |
|
}); |
|
this._reader.onEntry((entry)=>{ |
|
this._storage.add(entry); |
|
}); |
|
this._reader.onEnd(()=>{ |
|
$dbc0921597fb36f9$var$callSuccessCallback(callback, [ |
|
...this._storage |
|
]); |
|
}); |
|
this._reader.read(); |
|
} |
|
} |
|
$dbc0921597fb36f9$exports.default = $dbc0921597fb36f9$var$AsyncProvider; |
|
function $dbc0921597fb36f9$var$callFailureCallback(callback, error) { |
|
callback(error); |
|
} |
|
function $dbc0921597fb36f9$var$callSuccessCallback(callback, entries) { |
|
callback(null, entries); |
|
} |
|
|
|
|
|
var $c2173b46cba09dea$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($c2173b46cba09dea$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
|
|
class $c2173b46cba09dea$var$StreamProvider { |
|
constructor(_root, _settings){ |
|
this._root = _root; |
|
this._settings = _settings; |
|
this._reader = new $2fa2a8e52edb0b77$exports.default(this._root, this._settings); |
|
this._stream = new $8C1kk$stream.Readable({ |
|
objectMode: true, |
|
read: ()=>{ |
|
}, |
|
destroy: this._reader.destroy.bind(this._reader) |
|
}); |
|
} |
|
read() { |
|
this._reader.onError((error)=>{ |
|
this._stream.emit('error', error); |
|
}); |
|
this._reader.onEntry((entry)=>{ |
|
this._stream.push(entry); |
|
}); |
|
this._reader.onEnd(()=>{ |
|
this._stream.push(null); |
|
}); |
|
this._reader.read(); |
|
return this._stream; |
|
} |
|
} |
|
$c2173b46cba09dea$exports.default = $c2173b46cba09dea$var$StreamProvider; |
|
|
|
|
|
var $639287b46e0c7770$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($639287b46e0c7770$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $61c03480cb6054e8$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($61c03480cb6054e8$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
|
|
|
|
class $61c03480cb6054e8$var$SyncReader extends $e2f1a4546d061960$exports.default { |
|
constructor(){ |
|
super(...arguments); |
|
this._scandir = $6e9dd7fa450f205e$exports.scandirSync; |
|
this._storage = new Set(); |
|
this._queue = new Set(); |
|
} |
|
read() { |
|
this._pushToQueue(this._root, this._settings.basePath); |
|
this._handleQueue(); |
|
return [ |
|
...this._storage |
|
]; |
|
} |
|
_pushToQueue(directory, base) { |
|
this._queue.add({ |
|
directory: directory, |
|
base: base |
|
}); |
|
} |
|
_handleQueue() { |
|
for (const item of this._queue.values())this._handleDirectory(item.directory, item.base); |
|
} |
|
_handleDirectory(directory, base) { |
|
try { |
|
const entries = this._scandir(directory, this._settings.fsScandirSettings); |
|
for (const entry of entries)this._handleEntry(entry, base); |
|
} catch (error) { |
|
this._handleError(error); |
|
} |
|
} |
|
_handleError(error) { |
|
if (!$e6d58630eaa29e9b$exports.isFatalError(this._settings, error)) return; |
|
throw error; |
|
} |
|
_handleEntry(entry, base) { |
|
const fullpath = entry.path; |
|
if (base !== undefined) entry.path = $e6d58630eaa29e9b$exports.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); |
|
if ($e6d58630eaa29e9b$exports.isAppliedFilter(this._settings.entryFilter, entry)) this._pushToStorage(entry); |
|
if (entry.dirent.isDirectory() && $e6d58630eaa29e9b$exports.isAppliedFilter(this._settings.deepFilter, entry)) this._pushToQueue(fullpath, entry.path); |
|
} |
|
_pushToStorage(entry) { |
|
this._storage.add(entry); |
|
} |
|
} |
|
$61c03480cb6054e8$exports.default = $61c03480cb6054e8$var$SyncReader; |
|
|
|
|
|
class $639287b46e0c7770$var$SyncProvider { |
|
constructor(_root, _settings){ |
|
this._root = _root; |
|
this._settings = _settings; |
|
this._reader = new $61c03480cb6054e8$exports.default(this._root, this._settings); |
|
} |
|
read() { |
|
return this._reader.read(); |
|
} |
|
} |
|
$639287b46e0c7770$exports.default = $639287b46e0c7770$var$SyncProvider; |
|
|
|
|
|
var $a0b78a2e01019234$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($a0b78a2e01019234$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
|
|
class $a0b78a2e01019234$var$Settings { |
|
constructor(_options = { |
|
}){ |
|
this._options = _options; |
|
this.basePath = this._getValue(this._options.basePath, undefined); |
|
this.concurrency = this._getValue(this._options.concurrency, Infinity); |
|
this.deepFilter = this._getValue(this._options.deepFilter, null); |
|
this.entryFilter = this._getValue(this._options.entryFilter, null); |
|
this.errorFilter = this._getValue(this._options.errorFilter, null); |
|
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, $8C1kk$path.sep); |
|
this.fsScandirSettings = new $6e9dd7fa450f205e$exports.Settings({ |
|
followSymbolicLinks: this._options.followSymbolicLinks, |
|
fs: this._options.fs, |
|
pathSegmentSeparator: this._options.pathSegmentSeparator, |
|
stats: this._options.stats, |
|
throwErrorOnBrokenSymbolicLink: this._options.throwErrorOnBrokenSymbolicLink |
|
}); |
|
} |
|
_getValue(option, value) { |
|
return option === undefined ? value : option; |
|
} |
|
} |
|
$a0b78a2e01019234$exports.default = $a0b78a2e01019234$var$Settings; |
|
|
|
|
|
$798d916015b2c927$exports.Settings = $a0b78a2e01019234$exports.default; |
|
function $798d916015b2c927$var$walk(directory, optionsOrSettingsOrCallback, callback) { |
|
if (typeof optionsOrSettingsOrCallback === 'function') return new $dbc0921597fb36f9$exports.default(directory, $798d916015b2c927$var$getSettings()).read(optionsOrSettingsOrCallback); |
|
new $dbc0921597fb36f9$exports.default(directory, $798d916015b2c927$var$getSettings(optionsOrSettingsOrCallback)).read(callback); |
|
} |
|
$798d916015b2c927$exports.walk = $798d916015b2c927$var$walk; |
|
function $798d916015b2c927$var$walkSync(directory, optionsOrSettings) { |
|
const settings = $798d916015b2c927$var$getSettings(optionsOrSettings); |
|
const provider = new $639287b46e0c7770$exports.default(directory, settings); |
|
return provider.read(); |
|
} |
|
$798d916015b2c927$exports.walkSync = $798d916015b2c927$var$walkSync; |
|
function $798d916015b2c927$var$walkStream(directory, optionsOrSettings) { |
|
const settings = $798d916015b2c927$var$getSettings(optionsOrSettings); |
|
const provider = new $c2173b46cba09dea$exports.default(directory, settings); |
|
return provider.read(); |
|
} |
|
$798d916015b2c927$exports.walkStream = $798d916015b2c927$var$walkStream; |
|
function $798d916015b2c927$var$getSettings(settingsOrOptions = { |
|
}) { |
|
if (settingsOrOptions instanceof $a0b78a2e01019234$exports.default) return settingsOrOptions; |
|
return new $a0b78a2e01019234$exports.default(settingsOrOptions); |
|
} |
|
|
|
|
|
var $595889d33eb55b58$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($595889d33eb55b58$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
|
|
|
|
class $595889d33eb55b58$var$Reader { |
|
constructor(_settings){ |
|
this._settings = _settings; |
|
this._fsStatSettings = new $6c0caade5edaab5b$exports.Settings({ |
|
followSymbolicLink: this._settings.followSymbolicLinks, |
|
fs: this._settings.fs, |
|
throwErrorOnBrokenSymbolicLink: this._settings.followSymbolicLinks |
|
}); |
|
} |
|
_getFullEntryPath(filepath) { |
|
return $8C1kk$path.resolve(this._settings.cwd, filepath); |
|
} |
|
_makeEntry(stats, pattern) { |
|
const entry = { |
|
name: pattern, |
|
path: pattern, |
|
dirent: $1b5b082adfcf5f99$exports.fs.createDirentFromStats(pattern, stats) |
|
}; |
|
if (this._settings.stats) entry.stats = stats; |
|
return entry; |
|
} |
|
_isFatalError(error) { |
|
return !$1b5b082adfcf5f99$exports.errno.isEnoentCodeError(error) && !this._settings.suppressErrors; |
|
} |
|
} |
|
$595889d33eb55b58$exports.default = $595889d33eb55b58$var$Reader; |
|
|
|
|
|
class $f93330d45af3b4cf$var$ReaderStream extends $595889d33eb55b58$exports.default { |
|
constructor(){ |
|
super(...arguments); |
|
this._walkStream = $798d916015b2c927$exports.walkStream; |
|
this._stat = $6c0caade5edaab5b$exports.stat; |
|
} |
|
dynamic(root, options) { |
|
return this._walkStream(root, options); |
|
} |
|
static(patterns, options) { |
|
const filepaths = patterns.map(this._getFullEntryPath, this); |
|
const stream = new $8C1kk$stream.PassThrough({ |
|
objectMode: true |
|
}); |
|
stream._write = (index, _enc, done)=>{ |
|
return this._getEntry(filepaths[index], patterns[index], options).then((entry)=>{ |
|
if (entry !== null && options.entryFilter(entry)) stream.push(entry); |
|
if (index === filepaths.length - 1) stream.end(); |
|
done(); |
|
}).catch(done); |
|
}; |
|
for(let i = 0; i < filepaths.length; i++)stream.write(i); |
|
return stream; |
|
} |
|
_getEntry(filepath, pattern, options) { |
|
return this._getStat(filepath).then((stats)=>this._makeEntry(stats, pattern) |
|
).catch((error)=>{ |
|
if (options.errorFilter(error)) return null; |
|
throw error; |
|
}); |
|
} |
|
_getStat(filepath) { |
|
return new Promise((resolve, reject)=>{ |
|
this._stat(filepath, this._fsStatSettings, (error, stats)=>{ |
|
return error === null ? resolve(stats) : reject(error); |
|
}); |
|
}); |
|
} |
|
} |
|
$f93330d45af3b4cf$exports.default = $f93330d45af3b4cf$var$ReaderStream; |
|
|
|
|
|
var $b2104eae05a96326$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($b2104eae05a96326$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
var $158f1e2e83bb81fa$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($158f1e2e83bb81fa$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
class $158f1e2e83bb81fa$var$DeepFilter { |
|
constructor(_settings, _micromatchOptions){ |
|
this._settings = _settings; |
|
this._micromatchOptions = _micromatchOptions; |
|
} |
|
getFilter(basePath, positive, negative) { |
|
const maxPatternDepth = this._getMaxPatternDepth(positive); |
|
const negativeRe = this._getNegativePatternsRe(negative); |
|
return (entry)=>this._filter(basePath, entry, negativeRe, maxPatternDepth) |
|
; |
|
} |
|
_getMaxPatternDepth(patterns) { |
|
const globstar = patterns.some($1b5b082adfcf5f99$exports.pattern.hasGlobStar); |
|
return globstar ? Infinity : $1b5b082adfcf5f99$exports.pattern.getMaxNaivePatternsDepth(patterns); |
|
} |
|
_getNegativePatternsRe(patterns) { |
|
const affectDepthOfReadingPatterns = patterns.filter($1b5b082adfcf5f99$exports.pattern.isAffectDepthOfReadingPattern); |
|
return $1b5b082adfcf5f99$exports.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this._micromatchOptions); |
|
} |
|
_filter(basePath, entry, negativeRe, maxPatternDepth) { |
|
const depth = this._getEntryDepth(basePath, entry.path); |
|
if (this._isSkippedByDeep(depth)) return false; |
|
if (this._isSkippedByMaxPatternDepth(depth, maxPatternDepth)) return false; |
|
if (this._isSkippedSymbolicLink(entry)) return false; |
|
return this._isSkippedByNegativePatterns(entry, negativeRe); |
|
} |
|
_getEntryDepth(basePath, entryPath) { |
|
const basePathDepth = basePath.split('/').length; |
|
const entryPathDepth = entryPath.split('/').length; |
|
return entryPathDepth - (basePath === '' ? 0 : basePathDepth); |
|
} |
|
_isSkippedByDeep(entryDepth) { |
|
return entryDepth >= this._settings.deep; |
|
} |
|
_isSkippedByMaxPatternDepth(entryDepth, maxPatternDepth) { |
|
return !this._settings.baseNameMatch && maxPatternDepth !== Infinity && entryDepth > maxPatternDepth; |
|
} |
|
_isSkippedSymbolicLink(entry) { |
|
return !this._settings.followSymbolicLinks && entry.dirent.isSymbolicLink(); |
|
} |
|
_isSkippedByNegativePatterns(entry, negativeRe) { |
|
return !$1b5b082adfcf5f99$exports.pattern.matchAny(entry.path, negativeRe); |
|
} |
|
} |
|
$158f1e2e83bb81fa$exports.default = $158f1e2e83bb81fa$var$DeepFilter; |
|
|
|
|
|
var $f26cad5ed17500b0$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($f26cad5ed17500b0$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
class $f26cad5ed17500b0$var$EntryFilter { |
|
constructor(_settings, _micromatchOptions){ |
|
this._settings = _settings; |
|
this._micromatchOptions = _micromatchOptions; |
|
this.index = new Map(); |
|
} |
|
getFilter(positive, negative) { |
|
const positiveRe = $1b5b082adfcf5f99$exports.pattern.convertPatternsToRe(positive, this._micromatchOptions); |
|
const negativeRe = $1b5b082adfcf5f99$exports.pattern.convertPatternsToRe(negative, this._micromatchOptions); |
|
return (entry)=>this._filter(entry, positiveRe, negativeRe) |
|
; |
|
} |
|
_filter(entry, positiveRe, negativeRe) { |
|
if (this._settings.unique) { |
|
if (this._isDuplicateEntry(entry)) return false; |
|
this._createIndexRecord(entry); |
|
} |
|
if (this._onlyFileFilter(entry) || this._onlyDirectoryFilter(entry)) return false; |
|
if (this._isSkippedByAbsoluteNegativePatterns(entry, negativeRe)) return false; |
|
const filepath = this._settings.baseNameMatch ? entry.name : entry.path; |
|
return this._isMatchToPatterns(filepath, positiveRe) && !this._isMatchToPatterns(entry.path, negativeRe); |
|
} |
|
_isDuplicateEntry(entry) { |
|
return this.index.has(entry.path); |
|
} |
|
_createIndexRecord(entry) { |
|
this.index.set(entry.path, undefined); |
|
} |
|
_onlyFileFilter(entry) { |
|
return this._settings.onlyFiles && !entry.dirent.isFile(); |
|
} |
|
_onlyDirectoryFilter(entry) { |
|
return this._settings.onlyDirectories && !entry.dirent.isDirectory(); |
|
} |
|
_isSkippedByAbsoluteNegativePatterns(entry, negativeRe) { |
|
if (!this._settings.absolute) return false; |
|
const fullpath = $1b5b082adfcf5f99$exports.path.makeAbsolute(this._settings.cwd, entry.path); |
|
return this._isMatchToPatterns(fullpath, negativeRe); |
|
} |
|
_isMatchToPatterns(filepath, patternsRe) { |
|
return $1b5b082adfcf5f99$exports.pattern.matchAny(filepath, patternsRe); |
|
} |
|
} |
|
$f26cad5ed17500b0$exports.default = $f26cad5ed17500b0$var$EntryFilter; |
|
|
|
|
|
var $4f982576078a7524$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($4f982576078a7524$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
class $4f982576078a7524$var$ErrorFilter { |
|
constructor(_settings){ |
|
this._settings = _settings; |
|
} |
|
getFilter() { |
|
return (error)=>this._isNonFatalError(error) |
|
; |
|
} |
|
_isNonFatalError(error) { |
|
return $1b5b082adfcf5f99$exports.errno.isEnoentCodeError(error) || this._settings.suppressErrors; |
|
} |
|
} |
|
$4f982576078a7524$exports.default = $4f982576078a7524$var$ErrorFilter; |
|
|
|
|
|
var $4583c239a6a31b31$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($4583c239a6a31b31$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
class $4583c239a6a31b31$var$EntryTransformer { |
|
constructor(_settings){ |
|
this._settings = _settings; |
|
} |
|
getTransformer() { |
|
return (entry)=>this._transform(entry) |
|
; |
|
} |
|
_transform(entry) { |
|
let filepath = entry.path; |
|
if (this._settings.absolute) { |
|
filepath = $1b5b082adfcf5f99$exports.path.makeAbsolute(this._settings.cwd, filepath); |
|
filepath = $1b5b082adfcf5f99$exports.path.unixify(filepath); |
|
} |
|
if (this._settings.markDirectories && entry.dirent.isDirectory()) filepath += '/'; |
|
if (!this._settings.objectMode) return filepath; |
|
return Object.assign(Object.assign({ |
|
}, entry), { |
|
path: filepath |
|
}); |
|
} |
|
} |
|
$4583c239a6a31b31$exports.default = $4583c239a6a31b31$var$EntryTransformer; |
|
|
|
|
|
class $b2104eae05a96326$var$Provider { |
|
constructor(_settings){ |
|
this._settings = _settings; |
|
this.errorFilter = new $4f982576078a7524$exports.default(this._settings); |
|
this.entryFilter = new $f26cad5ed17500b0$exports.default(this._settings, this._getMicromatchOptions()); |
|
this.deepFilter = new $158f1e2e83bb81fa$exports.default(this._settings, this._getMicromatchOptions()); |
|
this.entryTransformer = new $4583c239a6a31b31$exports.default(this._settings); |
|
} |
|
_getRootDirectory(task) { |
|
return $8C1kk$path.resolve(this._settings.cwd, task.base); |
|
} |
|
_getReaderOptions(task) { |
|
const basePath = task.base === '.' ? '' : task.base; |
|
return { |
|
basePath: basePath, |
|
pathSegmentSeparator: '/', |
|
concurrency: this._settings.concurrency, |
|
deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative), |
|
entryFilter: this.entryFilter.getFilter(task.positive, task.negative), |
|
errorFilter: this.errorFilter.getFilter(), |
|
followSymbolicLinks: this._settings.followSymbolicLinks, |
|
fs: this._settings.fs, |
|
stats: this._settings.stats, |
|
throwErrorOnBrokenSymbolicLink: this._settings.throwErrorOnBrokenSymbolicLink, |
|
transform: this.entryTransformer.getTransformer() |
|
}; |
|
} |
|
_getMicromatchOptions() { |
|
return { |
|
dot: this._settings.dot, |
|
matchBase: this._settings.baseNameMatch, |
|
nobrace: !this._settings.braceExpansion, |
|
nocase: !this._settings.caseSensitiveMatch, |
|
noext: !this._settings.extglob, |
|
noglobstar: !this._settings.globstar, |
|
posix: true, |
|
strictSlashes: false |
|
}; |
|
} |
|
} |
|
$b2104eae05a96326$exports.default = $b2104eae05a96326$var$Provider; |
|
|
|
|
|
class $5e8aeb81d3971f46$var$ProviderAsync extends $b2104eae05a96326$exports.default { |
|
constructor(){ |
|
super(...arguments); |
|
this._reader = new $f93330d45af3b4cf$exports.default(this._settings); |
|
} |
|
read(task) { |
|
const root = this._getRootDirectory(task); |
|
const options = this._getReaderOptions(task); |
|
const entries = []; |
|
return new Promise((resolve, reject)=>{ |
|
const stream = this.api(root, task, options); |
|
stream.once('error', reject); |
|
stream.on('data', (entry)=>entries.push(options.transform(entry)) |
|
); |
|
stream.once('end', ()=>resolve(entries) |
|
); |
|
}); |
|
} |
|
api(root, task, options) { |
|
if (task.dynamic) return this._reader.dynamic(root, options); |
|
return this._reader.static(task.patterns, options); |
|
} |
|
} |
|
$5e8aeb81d3971f46$exports.default = $5e8aeb81d3971f46$var$ProviderAsync; |
|
|
|
|
|
var $434410c8b70ca432$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($434410c8b70ca432$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
|
|
|
|
class $434410c8b70ca432$var$ProviderStream extends $b2104eae05a96326$exports.default { |
|
constructor(){ |
|
super(...arguments); |
|
this._reader = new $f93330d45af3b4cf$exports.default(this._settings); |
|
} |
|
read(task) { |
|
const root = this._getRootDirectory(task); |
|
const options = this._getReaderOptions(task); |
|
const source = this.api(root, task, options); |
|
const destination = new $8C1kk$stream.Readable({ |
|
objectMode: true, |
|
read: ()=>{ |
|
} |
|
}); |
|
source.once('error', (error)=>destination.emit('error', error) |
|
).on('data', (entry)=>destination.emit('data', options.transform(entry)) |
|
).once('end', ()=>destination.emit('end') |
|
); |
|
destination.once('close', ()=>source.destroy() |
|
); |
|
return destination; |
|
} |
|
api(root, task, options) { |
|
if (task.dynamic) return this._reader.dynamic(root, options); |
|
return this._reader.static(task.patterns, options); |
|
} |
|
} |
|
$434410c8b70ca432$exports.default = $434410c8b70ca432$var$ProviderStream; |
|
|
|
|
|
var $449ae2813b11b2d5$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($449ae2813b11b2d5$exports, "__esModule", { |
|
value: true |
|
}); |
|
var $91612adb731b8334$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($91612adb731b8334$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
|
|
|
|
class $91612adb731b8334$var$ReaderSync extends $595889d33eb55b58$exports.default { |
|
constructor(){ |
|
super(...arguments); |
|
this._walkSync = $798d916015b2c927$exports.walkSync; |
|
this._statSync = $6c0caade5edaab5b$exports.statSync; |
|
} |
|
dynamic(root, options) { |
|
return this._walkSync(root, options); |
|
} |
|
static(patterns, options) { |
|
const entries = []; |
|
for (const pattern of patterns){ |
|
const filepath = this._getFullEntryPath(pattern); |
|
const entry = this._getEntry(filepath, pattern, options); |
|
if (entry === null || !options.entryFilter(entry)) continue; |
|
entries.push(entry); |
|
} |
|
return entries; |
|
} |
|
_getEntry(filepath, pattern, options) { |
|
try { |
|
const stats = this._getStat(filepath); |
|
return this._makeEntry(stats, pattern); |
|
} catch (error) { |
|
if (options.errorFilter(error)) return null; |
|
throw error; |
|
} |
|
} |
|
_getStat(filepath) { |
|
return this._statSync(filepath, this._fsStatSettings); |
|
} |
|
} |
|
$91612adb731b8334$exports.default = $91612adb731b8334$var$ReaderSync; |
|
|
|
|
|
|
|
class $449ae2813b11b2d5$var$ProviderSync extends $b2104eae05a96326$exports.default { |
|
constructor(){ |
|
super(...arguments); |
|
this._reader = new $91612adb731b8334$exports.default(this._settings); |
|
} |
|
read(task) { |
|
const root = this._getRootDirectory(task); |
|
const options = this._getReaderOptions(task); |
|
const entries = this.api(root, task, options); |
|
return entries.map(options.transform); |
|
} |
|
api(root, task, options) { |
|
if (task.dynamic) return this._reader.dynamic(root, options); |
|
return this._reader.static(task.patterns, options); |
|
} |
|
} |
|
$449ae2813b11b2d5$exports.default = $449ae2813b11b2d5$var$ProviderSync; |
|
|
|
|
|
var $1d7e3dfd05c8321e$exports = {}; |
|
"use strict"; |
|
Object.defineProperty($1d7e3dfd05c8321e$exports, "__esModule", { |
|
value: true |
|
}); |
|
|
|
|
|
const $1d7e3dfd05c8321e$var$CPU_COUNT = $8C1kk$os.cpus().length; |
|
$1d7e3dfd05c8321e$exports.DEFAULT_FILE_SYSTEM_ADAPTER = { |
|
lstat: $8C1kk$fs.lstat, |
|
lstatSync: $8C1kk$fs.lstatSync, |
|
stat: $8C1kk$fs.stat, |
|
statSync: $8C1kk$fs.statSync, |
|
readdir: $8C1kk$fs.readdir, |
|
readdirSync: $8C1kk$fs.readdirSync |
|
}; |
|
class $1d7e3dfd05c8321e$var$Settings { |
|
constructor(_options = { |
|
}){ |
|
this._options = _options; |
|
this.absolute = this._getValue(this._options.absolute, false); |
|
this.baseNameMatch = this._getValue(this._options.baseNameMatch, false); |
|
this.braceExpansion = this._getValue(this._options.braceExpansion, true); |
|
this.caseSensitiveMatch = this._getValue(this._options.caseSensitiveMatch, true); |
|
this.concurrency = this._getValue(this._options.concurrency, $1d7e3dfd05c8321e$var$CPU_COUNT); |
|
this.cwd = this._getValue(this._options.cwd, process.cwd()); |
|
this.deep = this._getValue(this._options.deep, Infinity); |
|
this.dot = this._getValue(this._options.dot, false); |
|
this.extglob = this._getValue(this._options.extglob, true); |
|
this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, true); |
|
this.fs = this._getFileSystemMethods(this._options.fs); |
|
this.globstar = this._getValue(this._options.globstar, true); |
|
this.ignore = this._getValue(this._options.ignore, []); |
|
this.markDirectories = this._getValue(this._options.markDirectories, false); |
|
this.objectMode = this._getValue(this._options.objectMode, false); |
|
this.onlyDirectories = this._getValue(this._options.onlyDirectories, false); |
|
this.onlyFiles = this._getValue(this._options.onlyFiles, true); |
|
this.stats = this._getValue(this._options.stats, false); |
|
this.suppressErrors = this._getValue(this._options.suppressErrors, false); |
|
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, false); |
|
this.unique = this._getValue(this._options.unique, true); |
|
if (this.onlyDirectories) this.onlyFiles = false; |
|
if (this.stats) this.objectMode = true; |
|
} |
|
_getValue(option, value) { |
|
return option === undefined ? value : option; |
|
} |
|
_getFileSystemMethods(methods = { |
|
}) { |
|
return Object.assign(Object.assign({ |
|
}, $1d7e3dfd05c8321e$exports.DEFAULT_FILE_SYSTEM_ADAPTER), methods); |
|
} |
|
} |
|
$1d7e3dfd05c8321e$exports.default = $1d7e3dfd05c8321e$var$Settings; |
|
|
|
|
|
|
|
function $b57e78be4f7a2622$var$FastGlob(source, options) { |
|
try { |
|
$b57e78be4f7a2622$var$assertPatternsInput(source); |
|
} catch (error) { |
|
return Promise.reject(error); |
|
} |
|
const works = $b57e78be4f7a2622$var$getWorks(source, $5e8aeb81d3971f46$exports.default, options); |
|
return Promise.all(works).then($1b5b082adfcf5f99$exports.array.flatten); |
|
} |
|
// https://github.com/typescript-eslint/typescript-eslint/issues/60 |
|
// eslint-disable-next-line no-redeclare |
|
(function(FastGlob) { |
|
function sync(source, options) { |
|
$b57e78be4f7a2622$var$assertPatternsInput(source); |
|
const works = $b57e78be4f7a2622$var$getWorks(source, $449ae2813b11b2d5$exports.default, options); |
|
return $1b5b082adfcf5f99$exports.array.flatten(works); |
|
} |
|
FastGlob.sync = sync; |
|
function stream(source, options) { |
|
$b57e78be4f7a2622$var$assertPatternsInput(source); |
|
const works = $b57e78be4f7a2622$var$getWorks(source, $434410c8b70ca432$exports.default, options); |
|
/**
|
|
* The stream returned by the provider cannot work with an asynchronous iterator.
|
|
* To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams.
|
|
* This affects performance (+25%). I don't see best solution right now.
|
|
*/ return $1b5b082adfcf5f99$exports.stream.merge(works); |
|
} |
|
FastGlob.stream = stream; |
|
function generateTasks(source, options) { |
|
$b57e78be4f7a2622$var$assertPatternsInput(source); |
|
const patterns = [].concat(source); |
|
const settings = new $1d7e3dfd05c8321e$exports.default(options); |
|
return $d436392a45e5b9b4$exports.generate(patterns, settings); |
|
} |
|
FastGlob.generateTasks = generateTasks; |
|
function isDynamicPattern(source, options) { |
|
$b57e78be4f7a2622$var$assertPatternsInput(source); |
|
const settings = new $1d7e3dfd05c8321e$exports.default(options); |
|
return $1b5b082adfcf5f99$exports.pattern.isDynamicPattern(source, settings); |
|
} |
|
FastGlob.isDynamicPattern = isDynamicPattern; |
|
function escapePath(source) { |
|
$b57e78be4f7a2622$var$assertPatternsInput(source); |
|
return $1b5b082adfcf5f99$exports.path.escape(source); |
|
} |
|
FastGlob.escapePath = escapePath; |
|
})($b57e78be4f7a2622$var$FastGlob || ($b57e78be4f7a2622$var$FastGlob = { |
|
})); |
|
function $b57e78be4f7a2622$var$getWorks(source, _Provider, options) { |
|
const patterns = [].concat(source); |
|
const settings = new $1d7e3dfd05c8321e$exports.default(options); |
|
const tasks = $d436392a45e5b9b4$exports.generate(patterns, settings); |
|
const provider = new _Provider(settings); |
|
return tasks.map(provider.read, provider); |
|
} |
|
function $b57e78be4f7a2622$var$assertPatternsInput(source) { |
|
if ([].concat(source).every($b57e78be4f7a2622$var$isString)) return; |
|
throw new TypeError('Patterns must be a string or an array of strings'); |
|
} |
|
function $b57e78be4f7a2622$var$isString(source) { |
|
return typeof source === 'string'; |
|
} |
|
$b57e78be4f7a2622$exports = $b57e78be4f7a2622$var$FastGlob; |
|
|
|
|
|
|
|
|
|
const $3dff16cfd200ff25$var$ABSOLUTE_PATH_REGEX = /^([a-zA-Z]:){0,1}[\\/]+/; |
|
const $3dff16cfd200ff25$var$SEPARATOR_REGEX = /[\\]+/g; |
|
function $3dff16cfd200ff25$export$e434c7255acda994(filepath) { |
|
return $3dff16cfd200ff25$var$ABSOLUTE_PATH_REGEX.test(filepath); |
|
} |
|
function $3dff16cfd200ff25$export$16778b798ae8e49d(filePath) { |
|
return filePath.replace($3dff16cfd200ff25$var$SEPARATOR_REGEX, '/'); |
|
} |
|
function $3dff16cfd200ff25$export$6af368f973c74c5(filePath, leadingDotSlash = true) { |
|
if (leadingDotSlash && (filePath[0] !== '.' || filePath[1] !== '.' && filePath[1] !== '/' && filePath[1] !== '\\') && !($parcel$interopDefault($8C1kk$path)).isAbsolute(filePath)) return $3dff16cfd200ff25$export$16778b798ae8e49d('./' + filePath); |
|
else return $3dff16cfd200ff25$export$16778b798ae8e49d(filePath); |
|
} |
|
function $3dff16cfd200ff25$export$7413eea5ad243d4(from, to, leadingDotSlash = true) { |
|
// Fast path |
|
if (to.startsWith(from + '/')) return (leadingDotSlash ? './' : '') + to.slice(from.length + 1); |
|
return $3dff16cfd200ff25$export$6af368f973c74c5(($parcel$interopDefault($8C1kk$path)).relative(from, to), leadingDotSlash); |
|
} |
|
|
|
|
|
function $e8d0e504a4244d84$export$f3a2344a73dbdd42(p) { |
|
return (/*@__PURE__*/$parcel$interopDefault($5aee5a8e09e874bf$exports))($3dff16cfd200ff25$export$16778b798ae8e49d(p)); |
|
} |
|
function $e8d0e504a4244d84$export$16e6d319a883f04e(filePath, $e8d0e504a4244d84$export$442f1a04865e4790, opts) { |
|
$e8d0e504a4244d84$export$442f1a04865e4790 = Array.isArray($e8d0e504a4244d84$export$442f1a04865e4790) ? $e8d0e504a4244d84$export$442f1a04865e4790.map($3dff16cfd200ff25$export$16778b798ae8e49d) : $3dff16cfd200ff25$export$16778b798ae8e49d($e8d0e504a4244d84$export$442f1a04865e4790); |
|
return $fec3b4fc54d3756a$exports.isMatch(filePath, $e8d0e504a4244d84$export$442f1a04865e4790, opts); |
|
} |
|
function $e8d0e504a4244d84$export$c0436a5422df81e4($e8d0e504a4244d84$export$442f1a04865e4790, opts) { |
|
return $fec3b4fc54d3756a$exports.makeRe($e8d0e504a4244d84$export$442f1a04865e4790, opts); |
|
} |
|
function $e8d0e504a4244d84$export$42275ba87174c828(p1, fs, options) { |
|
// $FlowFixMe |
|
options = { |
|
...options, |
|
fs: { |
|
statSync: (p)=>{ |
|
return fs.statSync(p); |
|
}, |
|
lstatSync: (p)=>{ |
|
// Our FileSystem interface doesn't have lstat support at the moment, |
|
// but this is fine for our purposes since we follow symlinks by default. |
|
return fs.statSync(p); |
|
}, |
|
readdirSync: (p, opts)=>{ |
|
return fs.readdirSync(p, opts); |
|
} |
|
} |
|
}; // $FlowFixMe |
|
return (/*@__PURE__*/$parcel$interopDefault($b57e78be4f7a2622$exports)).sync($3dff16cfd200ff25$export$16778b798ae8e49d(p1), options); |
|
} |
|
function $e8d0e504a4244d84$export$442f1a04865e4790(p2, fs, options) { |
|
// $FlowFixMe |
|
options = { |
|
...options, |
|
fs: { |
|
stat: async (p, cb)=>{ |
|
try { |
|
cb(null, await fs.stat(p)); |
|
} catch (err) { |
|
cb(err); |
|
} |
|
}, |
|
lstat: async (p, cb)=>{ |
|
// Our FileSystem interface doesn't have lstat support at the moment, |
|
// but this is fine for our purposes since we follow symlinks by default. |
|
try { |
|
cb(null, await fs.stat(p)); |
|
} catch (err) { |
|
cb(err); |
|
} |
|
}, |
|
readdir: async (p, opts, cb)=>{ |
|
if (typeof opts === 'function') { |
|
cb = opts; |
|
opts = null; |
|
} |
|
try { |
|
cb(null, await fs.readdir(p, opts)); |
|
} catch (err) { |
|
cb(err); |
|
} |
|
} |
|
} |
|
}; // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 |
|
return (/*@__PURE__*/$parcel$interopDefault($b57e78be4f7a2622$exports))($3dff16cfd200ff25$export$16778b798ae8e49d(p2), options); |
|
} |
|
|
|
|
|
|
|
function $275c1a71c92a4142$export$2e2bcd8739ae039(files) { |
|
let cur = null; |
|
for (let file of files){ |
|
let parsed = ($parcel$interopDefault($8C1kk$path)).parse(file); |
|
parsed.dir = $275c1a71c92a4142$var$findGlobRoot(parsed.dir); |
|
if (!cur) cur = parsed; |
|
else if (parsed.root !== cur.root) // bail out. there is no common root. |
|
// this can happen on windows, e.g. C:\foo\bar vs. D:\foo\bar |
|
return process.cwd(); |
|
else { |
|
// find the common path parts. |
|
let curParts = cur.dir.split(($parcel$interopDefault($8C1kk$path)).sep); |
|
let newParts = parsed.dir.split(($parcel$interopDefault($8C1kk$path)).sep); |
|
let len = Math.min(curParts.length, newParts.length); |
|
let i = 0; |
|
while(i < len && curParts[i] === newParts[i])i++; |
|
cur.dir = i > 1 ? curParts.slice(0, i).join(($parcel$interopDefault($8C1kk$path)).sep) : cur.root; |
|
} |
|
} |
|
return cur ? cur.dir : process.cwd(); |
|
} // Transforms a path like `packages/*/src/index.js` to the root of the glob, `packages/` |
|
function $275c1a71c92a4142$var$findGlobRoot(dir) { |
|
let parts = dir.split(($parcel$interopDefault($8C1kk$path)).sep); |
|
let last = parts.length; |
|
for(let i = parts.length - 1; i >= 0; i--)if ($e8d0e504a4244d84$export$f3a2344a73dbdd42(parts[i])) last = i; |
|
return parts.slice(0, last).join(($parcel$interopDefault($8C1kk$path)).sep); |
|
} |
|
|
|
|
|
|
|
function $ea105385370dfccd$export$2e2bcd8739ae039(child, parent) { |
|
const relative = ($parcel$interopDefault($8C1kk$path)).relative(parent, child); |
|
return !relative.startsWith('..') && !($parcel$interopDefault($8C1kk$path)).isAbsolute(relative); |
|
} |
|
|
|
|
|
var $7cae98672dfb03cc$exports = {}; |
|
/** |
|
* Expose `isUrl`. |
|
*/ $7cae98672dfb03cc$exports = $7cae98672dfb03cc$var$isUrl; |
|
/** |
|
* RegExps. |
|
* A URL must match #1 and then at least one of #2/#3. |
|
* Use two levels of REs to avoid REDOS. |
|
*/ var $7cae98672dfb03cc$var$protocolAndDomainRE = /^(?:\w+:)?\/\/(\S+)$/; |
|
var $7cae98672dfb03cc$var$localhostDomainRE = /^localhost[\:?\d]*(?:[^\:?\d]\S*)?$/; |
|
var $7cae98672dfb03cc$var$nonLocalhostDomainRE = /^[^\s\.]+\.\S{2,}$/; |
|
/** |
|
* Loosely validate a URL `string`. |
|
* |
|
* @param {String} string |
|
* @return {Boolean} |
|
*/ function $7cae98672dfb03cc$var$isUrl(string) { |
|
if (typeof string !== 'string') return false; |
|
var match = string.match($7cae98672dfb03cc$var$protocolAndDomainRE); |
|
if (!match) return false; |
|
var everythingAfterProtocol = match[1]; |
|
if (!everythingAfterProtocol) return false; |
|
if ($7cae98672dfb03cc$var$localhostDomainRE.test(everythingAfterProtocol) || $7cae98672dfb03cc$var$nonLocalhostDomainRE.test(everythingAfterProtocol)) return true; |
|
return false; |
|
} |
|
|
|
|
|
const $f7d48e99e9c9e3b2$var$ANCHOR_REGEXP = /^#/; // Matches scheme (ie: tel:, mailto:, data:, itms-apps:) |
|
const $f7d48e99e9c9e3b2$var$SCHEME_REGEXP = /^[a-z][a-z0-9\-+.]*:/i; |
|
function $f7d48e99e9c9e3b2$export$2e2bcd8739ae039(url) { |
|
return (/*@__PURE__*/$parcel$interopDefault($7cae98672dfb03cc$exports))(url) || $f7d48e99e9c9e3b2$var$ANCHOR_REGEXP.test(url) || $f7d48e99e9c9e3b2$var$SCHEME_REGEXP.test(url); |
|
} |
|
|
|
|
|
|
|
function $295998acc3b31ee9$export$2e2bcd8739ae039(object) { |
|
let hash = ($parcel$interopDefault($8C1kk$crypto)).createHash('md5'); |
|
for (let key of Object.keys(object).sort()){ |
|
let val = object[key]; |
|
if (typeof val === 'object' && val) hash.update(key + $295998acc3b31ee9$export$2e2bcd8739ae039(val)); |
|
else hash.update(key + val); |
|
} |
|
return hash.digest('hex'); |
|
} |
|
|
|
|
|
function $ec068ba9e84f8eea$export$2e2bcd8739ae039(timeInMs) { |
|
return timeInMs < 1000 ? `${timeInMs}ms` : `${(timeInMs / 1000).toFixed(2)}s`; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var $77226306a1863103$exports = {}; |
|
'use strict'; |
|
var $3124255f7fbe16f0$exports = {}; |
|
'use strict'; |
|
const $3124255f7fbe16f0$var$ansiEscapes = $3124255f7fbe16f0$exports; |
|
// TODO: remove this in the next major version |
|
$3124255f7fbe16f0$exports.default = $3124255f7fbe16f0$var$ansiEscapes; |
|
const $3124255f7fbe16f0$var$ESC = '\u001B['; |
|
const $3124255f7fbe16f0$var$OSC = '\u001B]'; |
|
const $3124255f7fbe16f0$var$BEL = '\u0007'; |
|
const $3124255f7fbe16f0$var$SEP = ';'; |
|
const $3124255f7fbe16f0$var$isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal'; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorTo = (x, y)=>{ |
|
if (typeof x !== 'number') throw new TypeError('The `x` argument is required'); |
|
if (typeof y !== 'number') return $3124255f7fbe16f0$var$ESC + (x + 1) + 'G'; |
|
return $3124255f7fbe16f0$var$ESC + (y + 1) + ';' + (x + 1) + 'H'; |
|
}; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorMove = (x, y)=>{ |
|
if (typeof x !== 'number') throw new TypeError('The `x` argument is required'); |
|
let ret = ''; |
|
if (x < 0) ret += $3124255f7fbe16f0$var$ESC + -x + 'D'; |
|
else if (x > 0) ret += $3124255f7fbe16f0$var$ESC + x + 'C'; |
|
if (y < 0) ret += $3124255f7fbe16f0$var$ESC + -y + 'A'; |
|
else if (y > 0) ret += $3124255f7fbe16f0$var$ESC + y + 'B'; |
|
return ret; |
|
}; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorUp = (count = 1)=>$3124255f7fbe16f0$var$ESC + count + 'A' |
|
; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorDown = (count = 1)=>$3124255f7fbe16f0$var$ESC + count + 'B' |
|
; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorForward = (count = 1)=>$3124255f7fbe16f0$var$ESC + count + 'C' |
|
; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorBackward = (count = 1)=>$3124255f7fbe16f0$var$ESC + count + 'D' |
|
; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorLeft = $3124255f7fbe16f0$var$ESC + 'G'; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorSavePosition = $3124255f7fbe16f0$var$isTerminalApp ? '\u001B7' : $3124255f7fbe16f0$var$ESC + 's'; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorRestorePosition = $3124255f7fbe16f0$var$isTerminalApp ? '\u001B8' : $3124255f7fbe16f0$var$ESC + 'u'; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorGetPosition = $3124255f7fbe16f0$var$ESC + '6n'; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorNextLine = $3124255f7fbe16f0$var$ESC + 'E'; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorPrevLine = $3124255f7fbe16f0$var$ESC + 'F'; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorHide = $3124255f7fbe16f0$var$ESC + '?25l'; |
|
$3124255f7fbe16f0$var$ansiEscapes.cursorShow = $3124255f7fbe16f0$var$ESC + '?25h'; |
|
$3124255f7fbe16f0$var$ansiEscapes.eraseLines = (count)=>{ |
|
let clear = ''; |
|
for(let i = 0; i < count; i++)clear += $3124255f7fbe16f0$var$ansiEscapes.eraseLine + (i < count - 1 ? $3124255f7fbe16f0$var$ansiEscapes.cursorUp() : ''); |
|
if (count) clear += $3124255f7fbe16f0$var$ansiEscapes.cursorLeft; |
|
return clear; |
|
}; |
|
$3124255f7fbe16f0$var$ansiEscapes.eraseEndLine = $3124255f7fbe16f0$var$ESC + 'K'; |
|
$3124255f7fbe16f0$var$ansiEscapes.eraseStartLine = $3124255f7fbe16f0$var$ESC + '1K'; |
|
$3124255f7fbe16f0$var$ansiEscapes.eraseLine = $3124255f7fbe16f0$var$ESC + '2K'; |
|
$3124255f7fbe16f0$var$ansiEscapes.eraseDown = $3124255f7fbe16f0$var$ESC + 'J'; |
|
$3124255f7fbe16f0$var$ansiEscapes.eraseUp = $3124255f7fbe16f0$var$ESC + '1J'; |
|
$3124255f7fbe16f0$var$ansiEscapes.eraseScreen = $3124255f7fbe16f0$var$ESC + '2J'; |
|
$3124255f7fbe16f0$var$ansiEscapes.scrollUp = $3124255f7fbe16f0$var$ESC + 'S'; |
|
$3124255f7fbe16f0$var$ansiEscapes.scrollDown = $3124255f7fbe16f0$var$ESC + 'T'; |
|
$3124255f7fbe16f0$var$ansiEscapes.clearScreen = '\u001Bc'; |
|
$3124255f7fbe16f0$var$ansiEscapes.clearTerminal = process.platform === 'win32' ? `${$3124255f7fbe16f0$var$ansiEscapes.eraseScreen}${$3124255f7fbe16f0$var$ESC}0f` : // 1. Erases the screen (Only done in case `2` is not supported) |
|
// 2. Erases the whole screen including scrollback buffer |
|
// 3. Moves cursor to the top-left position |
|
// More info: https://www.real-world-systems.com/docs/ANSIcode.html |
|
`${$3124255f7fbe16f0$var$ansiEscapes.eraseScreen}${$3124255f7fbe16f0$var$ESC}3J${$3124255f7fbe16f0$var$ESC}H`; |
|
$3124255f7fbe16f0$var$ansiEscapes.beep = $3124255f7fbe16f0$var$BEL; |
|
$3124255f7fbe16f0$var$ansiEscapes.link = (text, url)=>{ |
|
return [ |
|
$3124255f7fbe16f0$var$OSC, |
|
'8', |
|
$3124255f7fbe16f0$var$SEP, |
|
$3124255f7fbe16f0$var$SEP, |
|
url, |
|
$3124255f7fbe16f0$var$BEL, |
|
text, |
|
$3124255f7fbe16f0$var$OSC, |
|
'8', |
|
$3124255f7fbe16f0$var$SEP, |
|
$3124255f7fbe16f0$var$SEP, |
|
$3124255f7fbe16f0$var$BEL |
|
].join(''); |
|
}; |
|
$3124255f7fbe16f0$var$ansiEscapes.image = (buffer, options = { |
|
})=>{ |
|
let ret = `${$3124255f7fbe16f0$var$OSC}1337;File=inline=1`; |
|
if (options.width) ret += `;width=${options.width}`; |
|
if (options.height) ret += `;height=${options.height}`; |
|
if (options.preserveAspectRatio === false) ret += ';preserveAspectRatio=0'; |
|
return ret + ':' + buffer.toString('base64') + $3124255f7fbe16f0$var$BEL; |
|
}; |
|
$3124255f7fbe16f0$var$ansiEscapes.iTerm = { |
|
setCwd: (cwd = process.cwd())=>`${$3124255f7fbe16f0$var$OSC}50;CurrentDir=${cwd}${$3124255f7fbe16f0$var$BEL}` |
|
, |
|
annotation: (message, options = { |
|
})=>{ |
|
let ret = `${$3124255f7fbe16f0$var$OSC}1337;`; |
|
const hasX = typeof options.x !== 'undefined'; |
|
const hasY = typeof options.y !== 'undefined'; |
|
if ((hasX || hasY) && !(hasX && hasY && typeof options.length !== 'undefined')) throw new Error('`x`, `y` and `length` must be defined when `x` or `y` is defined'); |
|
message = message.replace(/\|/g, ''); |
|
ret += options.isHidden ? 'AddHiddenAnnotation=' : 'AddAnnotation='; |
|
if (options.length > 0) ret += (hasX ? [ |
|
message, |
|
options.length, |
|
options.x, |
|
options.y |
|
] : [ |
|
options.length, |
|
message |
|
]).join('|'); |
|
else ret += message; |
|
return ret + $3124255f7fbe16f0$var$BEL; |
|
} |
|
}; |
|
|
|
|
|
var $007fe08032bb1964$exports = {}; |
|
'use strict'; |
|
var $66d9750644ce4a3a$exports = {}; |
|
'use strict'; |
|
|
|
|
|
var $199fa68899b4a814$exports = {}; |
|
'use strict'; |
|
$199fa68899b4a814$exports = (flag, argv = process.argv)=>{ |
|
const prefix = flag.startsWith('-') ? '' : flag.length === 1 ? '-' : '--'; |
|
const position = argv.indexOf(prefix + flag); |
|
const terminatorPosition = argv.indexOf('--'); |
|
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); |
|
}; |
|
|
|
|
|
const { env: $66d9750644ce4a3a$var$env } = process; |
|
let $66d9750644ce4a3a$var$forceColor; |
|
if ($199fa68899b4a814$exports('no-color') || $199fa68899b4a814$exports('no-colors') || $199fa68899b4a814$exports('color=false') || $199fa68899b4a814$exports('color=never')) $66d9750644ce4a3a$var$forceColor = 0; |
|
else if ($199fa68899b4a814$exports('color') || $199fa68899b4a814$exports('colors') || $199fa68899b4a814$exports('color=true') || $199fa68899b4a814$exports('color=always')) $66d9750644ce4a3a$var$forceColor = 1; |
|
if ('FORCE_COLOR' in $66d9750644ce4a3a$var$env) { |
|
if ($66d9750644ce4a3a$var$env.FORCE_COLOR === 'true') $66d9750644ce4a3a$var$forceColor = 1; |
|
else if ($66d9750644ce4a3a$var$env.FORCE_COLOR === 'false') $66d9750644ce4a3a$var$forceColor = 0; |
|
else $66d9750644ce4a3a$var$forceColor = $66d9750644ce4a3a$var$env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt($66d9750644ce4a3a$var$env.FORCE_COLOR, 10), 3); |
|
} |
|
function $66d9750644ce4a3a$var$translateLevel(level) { |
|
if (level === 0) return false; |
|
return { |
|
level: level, |
|
hasBasic: true, |
|
has256: level >= 2, |
|
has16m: level >= 3 |
|
}; |
|
} |
|
function $66d9750644ce4a3a$var$supportsColor(haveStream, streamIsTTY) { |
|
if ($66d9750644ce4a3a$var$forceColor === 0) return 0; |
|
if ($199fa68899b4a814$exports('color=16m') || $199fa68899b4a814$exports('color=full') || $199fa68899b4a814$exports('color=truecolor')) return 3; |
|
if ($199fa68899b4a814$exports('color=256')) return 2; |
|
if (haveStream && !streamIsTTY && $66d9750644ce4a3a$var$forceColor === undefined) return 0; |
|
const min = $66d9750644ce4a3a$var$forceColor || 0; |
|
if ($66d9750644ce4a3a$var$env.TERM === 'dumb') return min; |
|
if (process.platform === 'win32') { |
|
// Windows 10 build 10586 is the first Windows release that supports 256 colors. |
|
// Windows 10 build 14931 is the first release that supports 16m/TrueColor. |
|
const osRelease = $8C1kk$os.release().split('.'); |
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2; |
|
return 1; |
|
} |
|
if ('CI' in $66d9750644ce4a3a$var$env) { |
|
if ([ |
|
'TRAVIS', |
|
'CIRCLECI', |
|
'APPVEYOR', |
|
'GITLAB_CI', |
|
'GITHUB_ACTIONS', |
|
'BUILDKITE' |
|
].some((sign)=>sign in $66d9750644ce4a3a$var$env |
|
) || $66d9750644ce4a3a$var$env.CI_NAME === 'codeship') return 1; |
|
return min; |
|
} |
|
if ('TEAMCITY_VERSION' in $66d9750644ce4a3a$var$env) return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test($66d9750644ce4a3a$var$env.TEAMCITY_VERSION) ? 1 : 0; |
|
if ($66d9750644ce4a3a$var$env.COLORTERM === 'truecolor') return 3; |
|
if ('TERM_PROGRAM' in $66d9750644ce4a3a$var$env) { |
|
const version = parseInt(($66d9750644ce4a3a$var$env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); |
|
switch($66d9750644ce4a3a$var$env.TERM_PROGRAM){ |
|
case 'iTerm.app': |
|
return version >= 3 ? 3 : 2; |
|
case 'Apple_Terminal': |
|
return 2; |
|
} |
|
} |
|
if (/-256(color)?$/i.test($66d9750644ce4a3a$var$env.TERM)) return 2; |
|
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test($66d9750644ce4a3a$var$env.TERM)) return 1; |
|
if ('COLORTERM' in $66d9750644ce4a3a$var$env) return 1; |
|
return min; |
|
} |
|
function $66d9750644ce4a3a$var$getSupportLevel(stream) { |
|
const level = $66d9750644ce4a3a$var$supportsColor(stream, stream && stream.isTTY); |
|
return $66d9750644ce4a3a$var$translateLevel(level); |
|
} |
|
$66d9750644ce4a3a$exports = { |
|
supportsColor: $66d9750644ce4a3a$var$getSupportLevel, |
|
stdout: $66d9750644ce4a3a$var$translateLevel($66d9750644ce4a3a$var$supportsColor(true, $8C1kk$tty.isatty(1))), |
|
stderr: $66d9750644ce4a3a$var$translateLevel($66d9750644ce4a3a$var$supportsColor(true, $8C1kk$tty.isatty(2))) |
|
}; |
|
|
|
|
|
|
|
function $007fe08032bb1964$var$parseVersion(versionString) { |
|
if (/^\d{3,4}$/.test(versionString)) { |
|
// Env var doesn't always use dots. example: 4601 => 46.1.0 |
|
const m = /(\d{1,2})(\d{2})/.exec(versionString); |
|
return { |
|
major: 0, |
|
minor: parseInt(m[1], 10), |
|
patch: parseInt(m[2], 10) |
|
}; |
|
} |
|
const versions = (versionString || '').split('.').map((n)=>parseInt(n, 10) |
|
); |
|
return { |
|
major: versions[0], |
|
minor: versions[1], |
|
patch: versions[2] |
|
}; |
|
} |
|
function $007fe08032bb1964$var$supportsHyperlink(stream) { |
|
const { env: env } = process; |
|
if ('FORCE_HYPERLINK' in env) return !(env.FORCE_HYPERLINK.length > 0 && parseInt(env.FORCE_HYPERLINK, 10) === 0); |
|
if ($199fa68899b4a814$exports('no-hyperlink') || $199fa68899b4a814$exports('no-hyperlinks') || $199fa68899b4a814$exports('hyperlink=false') || $199fa68899b4a814$exports('hyperlink=never')) return false; |
|
if ($199fa68899b4a814$exports('hyperlink=true') || $199fa68899b4a814$exports('hyperlink=always')) return true; |
|
// If they specify no colors, they probably don't want hyperlinks. |
|
if (!$66d9750644ce4a3a$exports.supportsColor(stream)) return false; |
|
if (stream && !stream.isTTY) return false; |
|
if (process.platform === 'win32') return false; |
|
if ('NETLIFY' in env) return true; |
|
if ('CI' in env) return false; |
|
if ('TEAMCITY_VERSION' in env) return false; |
|
if ('TERM_PROGRAM' in env) { |
|
const version = $007fe08032bb1964$var$parseVersion(env.TERM_PROGRAM_VERSION); |
|
switch(env.TERM_PROGRAM){ |
|
case 'iTerm.app': |
|
if (version.major === 3) return version.minor >= 1; |
|
return version.major > 3; |
|
} |
|
} |
|
if ('VTE_VERSION' in env) { |
|
// 0.50.0 was supposed to support hyperlinks, but throws a segfault |
|
if (env.VTE_VERSION === '0.50.0') return false; |
|
const version = $007fe08032bb1964$var$parseVersion(env.VTE_VERSION); |
|
return version.major > 0 || version.minor >= 50; |
|
} |
|
return false; |
|
} |
|
$007fe08032bb1964$exports = { |
|
supportsHyperlink: $007fe08032bb1964$var$supportsHyperlink, |
|
stdout: $007fe08032bb1964$var$supportsHyperlink(process.stdout), |
|
stderr: $007fe08032bb1964$var$supportsHyperlink(process.stderr) |
|
}; |
|
|
|
|
|
const $77226306a1863103$var$terminalLink = (text, url, { target: target = 'stdout' , ...options } = { |
|
})=>{ |
|
if (!$007fe08032bb1964$exports[target]) { |
|
// If the fallback has been explicitly disabled, don't modify the text itself. |
|
if (options.fallback === false) return text; |
|
return typeof options.fallback === 'function' ? options.fallback(text, url) : `${text} (\u200B${url}\u200B)`; |
|
} |
|
return $3124255f7fbe16f0$exports.link(text, url); |
|
}; |
|
$77226306a1863103$exports = (text, url, options = { |
|
})=>$77226306a1863103$var$terminalLink(text, url, options) |
|
; |
|
$77226306a1863103$exports.stderr = (text, url, options = { |
|
})=>$77226306a1863103$var$terminalLink(text, url, { |
|
target: 'stderr', |
|
...options |
|
}) |
|
; |
|
$77226306a1863103$exports.isSupported = $007fe08032bb1964$exports.stdout; |
|
$77226306a1863103$exports.stderr.isSupported = $007fe08032bb1964$exports.stderr; |
|
|
|
|
|
async function $f02d6a9d30f55938$export$2e2bcd8739ae039(diagnostic, options, terminalWidth) { |
|
let { origin: origin , message: message , stack: stack , codeFrames: codeFrames , hints: hints , skipFormatting: skipFormatting , documentationURL: documentationURL } = diagnostic; |
|
let result = { |
|
message: ($parcel$interopDefault($8C1kk$parcelmarkdownansi))(`**${origin !== null && origin !== void 0 ? origin : 'unknown'}**: `) + (skipFormatting ? message : ($parcel$interopDefault($8C1kk$parcelmarkdownansi))(message)), |
|
stack: '', |
|
codeframe: '', |
|
hints: [], |
|
documentation: '' |
|
}; |
|
if (codeFrames != null) for (let codeFrame of codeFrames){ |
|
let filePath = codeFrame.filePath; |
|
if (filePath != null && options && !($parcel$interopDefault($8C1kk$path)).isAbsolute(filePath)) filePath = ($parcel$interopDefault($8C1kk$path)).join(options.projectRoot, filePath); |
|
let highlights = codeFrame.codeHighlights; |
|
var _code; |
|
let code = (_code = codeFrame.code) !== null && _code !== void 0 ? _code : options && await options.inputFS.readFile((/*@__PURE__*/$parcel$interopDefault($812806c6461f2963$exports))(filePath), 'utf8'); |
|
let formattedCodeFrame = ''; |
|
if (code != null) formattedCodeFrame = ($parcel$interopDefault($8C1kk$parcelcodeframe))(code, highlights, { |
|
useColor: true, |
|
syntaxHighlighting: true, |
|
language: codeFrame.language || (filePath != null ? ($parcel$interopDefault($8C1kk$path)).extname(filePath).substr(1) : undefined), |
|
terminalWidth: terminalWidth |
|
}); |
|
result.codeframe += typeof filePath !== 'string' ? '' : ($parcel$interopDefault($8C1kk$chalk)).gray.underline(`${filePath}:${highlights[0].start.line}:${highlights[0].start.column}\n`); |
|
result.codeframe += formattedCodeFrame; |
|
if (codeFrame !== codeFrames[codeFrames.length - 1]) result.codeframe += '\n\n'; |
|
} |
|
if (stack != null) result.stack = stack; |
|
if (Array.isArray(hints) && hints.length) result.hints = hints.map((h)=>{ |
|
return ($parcel$interopDefault($8C1kk$parcelmarkdownansi))(h); |
|
}); |
|
if (documentationURL != null) result.documentation = (/*@__PURE__*/$parcel$interopDefault($77226306a1863103$exports))('Learn more', documentationURL, { |
|
fallback: (text, url)=>`${text}: ${url}` |
|
}); |
|
return result; |
|
} |
|
|
|
|
|
|
|
function $75952a43539cb60f$export$93f345b3f0dd27e7() { |
|
let deferred; |
|
let promise = new Promise((resolve, reject)=>{ |
|
deferred = { |
|
resolve: resolve, |
|
reject: reject |
|
}; |
|
}); // Promise constructor callback executes synchronously, so this is defined |
|
($parcel$interopDefault($8C1kk$assert))(deferred != null); |
|
return { |
|
deferred: deferred, |
|
promise: promise |
|
}; |
|
} |
|
|
|
|
|
class $b0fd219fea43bcac$export$2e2bcd8739ae039 { |
|
_numRunning = 0; |
|
_queue = []; |
|
_runPromise = null; |
|
_count = 0; |
|
_results = []; |
|
constructor(opts = { |
|
maxConcurrent: Infinity |
|
}){ |
|
if (opts.maxConcurrent <= 0) throw new TypeError('maxConcurrent must be a positive, non-zero value'); |
|
this._maxConcurrent = opts.maxConcurrent; |
|
} |
|
getNumWaiting() { |
|
return this._queue.length; |
|
} |
|
add(fn) { |
|
return new Promise((resolve, reject)=>{ |
|
let i = this._count++; |
|
this._queue.push(()=>fn().then((result)=>{ |
|
this._results[i] = result; |
|
resolve(result); |
|
}, (err)=>{ |
|
reject(err); |
|
throw err; |
|
}) |
|
); |
|
if (this._numRunning > 0 && this._numRunning < this._maxConcurrent) this._next(); |
|
}); |
|
} |
|
run() { |
|
if (this._runPromise != null) return this._runPromise; |
|
if (this._queue.length === 0) return Promise.resolve([]); |
|
let { deferred: deferred , promise: promise } = $75952a43539cb60f$export$93f345b3f0dd27e7(); |
|
this._deferred = deferred; |
|
this._runPromise = promise; |
|
while(this._queue.length && this._numRunning < this._maxConcurrent)this._next(); |
|
return promise; |
|
} |
|
async _next() { |
|
let fn = this._queue.shift(); |
|
await this._runFn(fn); |
|
if (this._queue.length) this._next(); |
|
else if (this._numRunning === 0) this._done(); |
|
} |
|
async _runFn(fn) { |
|
this._numRunning++; |
|
try { |
|
await fn(); |
|
} catch (e) { |
|
// Only store the first error that occurs. |
|
// We don't reject immediately so that any other concurrent |
|
// requests have time to complete. |
|
if (this._error == null) this._error = e; |
|
} finally{ |
|
this._numRunning--; |
|
} |
|
} |
|
_resetState() { |
|
this._queue = []; |
|
this._count = 0; |
|
this._results = []; |
|
this._runPromise = null; |
|
this._numRunning = 0; |
|
this._deferred = null; |
|
} |
|
_done() { |
|
if (this._deferred != null) { |
|
if (this._error != null) this._deferred.reject(this._error); |
|
else this._deferred.resolve(this._results); |
|
} |
|
this._resetState(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
var $f48e6c7a66080865$exports = {}; |
|
|
|
$parcel$export($f48e6c7a66080865$exports, "distance", () => $f48e6c7a66080865$export$9f17032d917177de, (v) => $f48e6c7a66080865$export$9f17032d917177de = v); |
|
$parcel$export($f48e6c7a66080865$exports, "closest", () => $f48e6c7a66080865$export$ff7f7c97cdce86e, (v) => $f48e6c7a66080865$export$ff7f7c97cdce86e = v); |
|
var $f48e6c7a66080865$export$9f17032d917177de; |
|
var $f48e6c7a66080865$export$ff7f7c97cdce86e; |
|
const $f48e6c7a66080865$var$peq = new Uint32Array(65536); |
|
const $f48e6c7a66080865$var$myers_32 = (a, b)=>{ |
|
const n = a.length; |
|
const m = b.length; |
|
const lst = 1 << n - 1; |
|
let pv = -1; |
|
let mv = 0; |
|
let sc = n; |
|
let i = m; |
|
while(i--)$f48e6c7a66080865$var$peq[b.charCodeAt(i)] = 0; |
|
i = n; |
|
while(i--)$f48e6c7a66080865$var$peq[a.charCodeAt(i)] |= 1 << i; |
|
for(i = 0; i < m; i++){ |
|
let eq = $f48e6c7a66080865$var$peq[b.charCodeAt(i)]; |
|
const xv = eq | mv; |
|
eq |= (eq & pv) + pv ^ pv; |
|
mv |= ~(eq | pv); |
|
pv &= eq; |
|
if (mv & lst) sc++; |
|
if (pv & lst) sc--; |
|
mv = mv << 1 | 1; |
|
pv = pv << 1 | ~(xv | mv); |
|
mv &= xv; |
|
} |
|
return sc; |
|
}; |
|
const $f48e6c7a66080865$var$myers_x = (b, a)=>{ |
|
const n = a.length; |
|
const m = b.length; |
|
const mhc = []; |
|
const phc = []; |
|
const hsize = Math.ceil(n / 32); |
|
const vsize = Math.ceil(m / 32); |
|
let score = m; |
|
for(let i = 0; i < hsize; i++){ |
|
phc[i] = -1; |
|
mhc[i] = 0; |
|
} |
|
let j = 0; |
|
for(; j < vsize - 1; j++){ |
|
let mv = 0; |
|
let pv = -1; |
|
const start = j * 32; |
|
const vlen = Math.min(32, m - start); |
|
let k = n; |
|
while(k--)$f48e6c7a66080865$var$peq[a.charCodeAt(k)] = 0; |
|
for(k = start; k < start + vlen; k++)$f48e6c7a66080865$var$peq[b.charCodeAt(k)] |= 1 << k; |
|
score = m; |
|
for(let i = 0; i < n; i++){ |
|
const eq = $f48e6c7a66080865$var$peq[a.charCodeAt(i)]; |
|
const pb = phc[i / 32 | 0] >>> i % 32 & 1; |
|
const mb = mhc[i / 32 | 0] >>> i % 32 & 1; |
|
const xv = eq | mv; |
|
const xh = ((eq | mb) & pv) + pv ^ pv | eq | mb; |
|
let ph = mv | ~(xh | pv); |
|
let mh = pv & xh; |
|
if (ph >>> 31 ^ pb) phc[i / 32 | 0] ^= 1 << i % 32; |
|
if (mh >>> 31 ^ mb) mhc[i / 32 | 0] ^= 1 << i % 32; |
|
ph = ph << 1 | pb; |
|
mh = mh << 1 | mb; |
|
pv = mh | ~(xv | ph); |
|
mv = ph & xv; |
|
} |
|
} |
|
let mv = 0; |
|
let pv = -1; |
|
const start = j * 32; |
|
const vlen = Math.min(32, m - start); |
|
let k = n; |
|
while(k--)$f48e6c7a66080865$var$peq[a.charCodeAt(k)] = 0; |
|
for(k = start; k < start + vlen; k++)$f48e6c7a66080865$var$peq[b.charCodeAt(k)] |= 1 << k; |
|
score = m; |
|
for(let i1 = 0; i1 < n; i1++){ |
|
const eq = $f48e6c7a66080865$var$peq[a.charCodeAt(i1)]; |
|
const pb = phc[i1 / 32 | 0] >>> i1 % 32 & 1; |
|
const mb = mhc[i1 / 32 | 0] >>> i1 % 32 & 1; |
|
const xv = eq | mv; |
|
const xh = ((eq | mb) & pv) + pv ^ pv | eq | mb; |
|
let ph = mv | ~(xh | pv); |
|
let mh = pv & xh; |
|
score += ph >>> m % 32 - 1 & 1; |
|
score -= mh >>> m % 32 - 1 & 1; |
|
if (ph >>> 31 ^ pb) phc[i1 / 32 | 0] ^= 1 << i1 % 32; |
|
if (mh >>> 31 ^ mb) mhc[i1 / 32 | 0] ^= 1 << i1 % 32; |
|
ph = ph << 1 | pb; |
|
mh = mh << 1 | mb; |
|
pv = mh | ~(xv | ph); |
|
mv = ph & xv; |
|
} |
|
return score; |
|
}; |
|
$f48e6c7a66080865$export$9f17032d917177de = (a, b)=>{ |
|
if (a.length < b.length) { |
|
const tmp = b; |
|
b = a; |
|
a = tmp; |
|
} |
|
if (b.length === 0) return a.length; |
|
if (a.length <= 32) return $f48e6c7a66080865$var$myers_32(a, b); |
|
return $f48e6c7a66080865$var$myers_x(a, b); |
|
}; |
|
$f48e6c7a66080865$export$ff7f7c97cdce86e = (str, arr)=>{ |
|
let min_distance = Infinity; |
|
let min_index = 0; |
|
for(let i = 0; i < arr.length; i++){ |
|
const distance = $f48e6c7a66080865$export$9f17032d917177de(str, arr[i]); |
|
if (distance < min_distance) { |
|
min_distance = distance; |
|
min_index = i; |
|
} |
|
} |
|
return arr[min_index]; |
|
}; |
|
|
|
|
|
function $4ca1027d34905147$var$validateSchema(schema, data) { |
|
function walk(schemaAncestors, dataNode, dataPath) { |
|
let [schemaNode] = schemaAncestors; |
|
if (schemaNode.type) { |
|
let type = Array.isArray(dataNode) ? 'array' : typeof dataNode; |
|
if (schemaNode.type !== type) return { |
|
type: 'type', |
|
dataType: 'value', |
|
dataPath: dataPath, |
|
expectedTypes: [ |
|
schemaNode.type |
|
], |
|
ancestors: schemaAncestors, |
|
prettyType: schemaNode.__type |
|
}; |
|
else switch(schemaNode.type){ |
|
case 'array': |
|
if (schemaNode.items) { |
|
let results = []; // $FlowFixMe type was already checked |
|
for(let i = 0; i < dataNode.length; i++){ |
|
let result = walk([ |
|
schemaNode.items |
|
].concat(schemaAncestors), dataNode[i], dataPath + '/' + i); |
|
if (result) results.push(result); |
|
} |
|
if (results.length) return results.reduce((acc, v)=>acc.concat(v) |
|
, []); |
|
} |
|
break; |
|
case 'string': |
|
{ |
|
// $FlowFixMe type was already checked |
|
let value = dataNode; |
|
if (schemaNode.enum) { |
|
if (!schemaNode.enum.includes(value)) return { |
|
type: 'enum', |
|
dataType: 'value', |
|
dataPath: dataPath, |
|
expectedValues: schemaNode.enum, |
|
actualValue: value, |
|
ancestors: schemaAncestors |
|
}; |
|
} else if (schemaNode.__validate) { |
|
let validationError = schemaNode.__validate(value); |
|
if (typeof validationError == 'string') return { |
|
type: 'other', |
|
dataType: 'value', |
|
dataPath: dataPath, |
|
message: validationError, |
|
actualValue: value, |
|
ancestors: schemaAncestors |
|
}; |
|
} |
|
break; |
|
} |
|
case 'number': |
|
{ |
|
// $FlowFixMe type was already checked |
|
let value = dataNode; |
|
if (schemaNode.enum) { |
|
if (!schemaNode.enum.includes(value)) return { |
|
type: 'enum', |
|
dataType: 'value', |
|
dataPath: dataPath, |
|
expectedValues: schemaNode.enum, |
|
actualValue: value, |
|
ancestors: schemaAncestors |
|
}; |
|
} |
|
break; |
|
} |
|
case 'object': |
|
{ |
|
let results = []; |
|
let invalidProps; |
|
if (schemaNode.__forbiddenProperties) { |
|
// $FlowFixMe type was already checked |
|
let keys = Object.keys(dataNode); |
|
invalidProps = schemaNode.__forbiddenProperties.filter((val)=>keys.includes(val) |
|
); |
|
results.push(...invalidProps.map((k)=>({ |
|
type: 'forbidden-prop', |
|
dataPath: dataPath + '/' + $8C1kk$parceldiagnostic.encodeJSONKeyComponent(k), |
|
dataType: 'key', |
|
prop: k, |
|
expectedProps: Object.keys(schemaNode.properties), |
|
actualProps: keys, |
|
ancestors: schemaAncestors |
|
}) |
|
)); |
|
} |
|
if (schemaNode.required) { |
|
// $FlowFixMe type was already checked |
|
let keys = Object.keys(dataNode); |
|
let missingKeys = schemaNode.required.filter((val)=>!keys.includes(val) |
|
); |
|
results.push(...missingKeys.map((k)=>({ |
|
type: 'missing-prop', |
|
dataPath: dataPath, |
|
dataType: 'value', |
|
prop: k, |
|
expectedProps: schemaNode.required, |
|
actualProps: keys, |
|
ancestors: schemaAncestors |
|
}) |
|
)); |
|
} |
|
if (schemaNode.properties) { |
|
let { additionalProperties: additionalProperties = true } = schemaNode; // $FlowFixMe type was already checked |
|
for(let k in dataNode){ |
|
if (invalidProps && invalidProps.includes(k)) continue; |
|
else if (k in schemaNode.properties) { |
|
let result = walk([ |
|
schemaNode.properties[k] |
|
].concat(schemaAncestors), dataNode[k], dataPath + '/' + $8C1kk$parceldiagnostic.encodeJSONKeyComponent(k)); |
|
if (result) results.push(result); |
|
} else { |
|
if (typeof additionalProperties === 'boolean') { |
|
if (!additionalProperties) results.push({ |
|
type: 'enum', |
|
dataType: 'key', |
|
dataPath: dataPath + '/' + $8C1kk$parceldiagnostic.encodeJSONKeyComponent(k), |
|
expectedValues: Object.keys(schemaNode.properties).filter((p)=>!(p in dataNode) |
|
), |
|
actualValue: k, |
|
ancestors: schemaAncestors, |
|
prettyType: schemaNode.__type |
|
}); |
|
} else { |
|
let result = walk([ |
|
additionalProperties |
|
].concat(schemaAncestors), dataNode[k], dataPath + '/' + $8C1kk$parceldiagnostic.encodeJSONKeyComponent(k)); |
|
if (result) results.push(result); |
|
} |
|
} |
|
} |
|
} |
|
if (results.length) return results.reduce((acc, v)=>acc.concat(v) |
|
, []); |
|
break; |
|
} |
|
case 'boolean': |
|
break; |
|
default: |
|
throw new Error(`Unimplemented schema type ${type}?`); |
|
} |
|
} else { |
|
if (schemaNode.enum && !schemaNode.enum.includes(dataNode)) return { |
|
type: 'enum', |
|
dataType: 'value', |
|
dataPath: dataPath, |
|
expectedValues: schemaNode.enum, |
|
actualValue: schemaNode, |
|
ancestors: schemaAncestors |
|
}; |
|
if (schemaNode.oneOf || schemaNode.allOf) { |
|
let list = schemaNode.oneOf || schemaNode.allOf; |
|
let results = []; |
|
for (let f of list){ |
|
let result = walk([ |
|
f |
|
].concat(schemaAncestors), dataNode, dataPath); |
|
if (result) results.push(result); |
|
} |
|
if (schemaNode.oneOf ? results.length == schemaNode.oneOf.length : results.length > 0) { |
|
// return the result with more values / longer key |
|
results.sort((a, b)=>Array.isArray(a) || Array.isArray(b) ? Array.isArray(a) && !Array.isArray(b) ? -1 : !Array.isArray(a) && Array.isArray(b) ? 1 : Array.isArray(a) && Array.isArray(b) ? b.length - a.length : 0 : b.dataPath.length - a.dataPath.length |
|
); |
|
return results[0]; |
|
} |
|
} else if (schemaNode.not) { |
|
let result = walk([ |
|
schemaNode.not |
|
].concat(schemaAncestors), dataNode, dataPath); |
|
if (!result || result.length == 0) return { |
|
type: 'other', |
|
dataPath: dataPath, |
|
dataType: null, |
|
message: schemaNode.__message, |
|
actualValue: dataNode, |
|
ancestors: schemaAncestors |
|
}; |
|
} |
|
} |
|
return undefined; |
|
} |
|
let result1 = walk([ |
|
schema |
|
], data, ''); |
|
return Array.isArray(result1) ? result1 : result1 ? [ |
|
result1 |
|
] : []; |
|
} |
|
var $4ca1027d34905147$export$2e2bcd8739ae039 = $4ca1027d34905147$var$validateSchema; |
|
function $4ca1027d34905147$export$2115c2c0a84eef61(expectedValues, actualValue) { |
|
let result = expectedValues.map((exp)=>[ |
|
exp, |
|
(/*@__PURE__*/$parcel$interopDefault($f48e6c7a66080865$exports)).distance(exp, actualValue) |
|
] |
|
).filter(([, d])=>d * 2 < actualValue.length |
|
); |
|
result.sort(([, a], [, b])=>a - b |
|
); |
|
return result.map(([v])=>v |
|
); |
|
} |
|
$4ca1027d34905147$var$validateSchema.diagnostic = function(schema, data, origin, message1) { |
|
if ('source' in data && 'data' in data && typeof data.source !== 'string' && !data) throw new Error('At least one of data.source and data.source must be defined!'); |
|
var _data; |
|
let object = data.map ? data.map.data : (_data = data.data) !== null && _data !== void 0 ? _data : JSON.parse(data.source); |
|
let errors = $4ca1027d34905147$var$validateSchema(schema, object); |
|
if (errors.length) { |
|
let keys = errors.map((e)=>{ |
|
let message; |
|
if (e.type === 'enum') { |
|
let { actualValue: actualValue } = e; |
|
let expectedValues = e.expectedValues.map(String); |
|
let likely = actualValue != null ? $4ca1027d34905147$export$2115c2c0a84eef61(expectedValues, String(actualValue)) : []; |
|
if (likely.length > 0) message = `Did you mean ${likely.map((v)=>JSON.stringify(v) |
|
).join(', ')}?`; |
|
else if (expectedValues.length > 0) message = `Possible values: ${expectedValues.map((v)=>JSON.stringify(v) |
|
).join(', ')}`; |
|
else message = 'Unexpected value'; |
|
} else if (e.type === 'forbidden-prop') { |
|
let { prop: prop , expectedProps: expectedProps , actualProps: actualProps } = e; |
|
let likely = $4ca1027d34905147$export$2115c2c0a84eef61(expectedProps, prop).filter((v)=>!actualProps.includes(v) |
|
); |
|
if (likely.length > 0) message = `Did you mean ${likely.map((v)=>JSON.stringify(v) |
|
).join(', ')}?`; |
|
else message = 'Unexpected property'; |
|
} else if (e.type === 'missing-prop') { |
|
let { prop: prop , actualProps: actualProps } = e; |
|
let likely = $4ca1027d34905147$export$2115c2c0a84eef61(actualProps, prop); |
|
if (likely.length > 0) { |
|
message = `Did you mean ${JSON.stringify(prop)}?`; |
|
e.dataPath += '/' + likely[0]; |
|
e.dataType = 'key'; |
|
} else message = `Missing property ${prop}`; |
|
} else if (e.type === 'type') { |
|
if (e.prettyType != null) message = `Expected ${e.prettyType}`; |
|
else message = `Expected type ${e.expectedTypes.join(', ')}`; |
|
} else message = e.message; |
|
return { |
|
key: e.dataPath, |
|
type: e.dataType, |
|
message: message |
|
}; |
|
}); |
|
let map, code; |
|
if (data.map) { |
|
map = data.map; |
|
code = data.source; |
|
} else { |
|
var _source; |
|
// $FlowFixMe we can assume that data is valid JSON |
|
map = (_source = data.source) !== null && _source !== void 0 ? _source : JSON.stringify((/*@__PURE__*/$parcel$interopDefault($812806c6461f2963$exports))(data.data), 0, '\t'); |
|
code = map; |
|
} |
|
var _filePath, _prependKey; |
|
let codeFrames = [ |
|
{ |
|
filePath: (_filePath = data.filePath) !== null && _filePath !== void 0 ? _filePath : undefined, |
|
language: 'json', |
|
code: code, |
|
codeHighlights: $8C1kk$parceldiagnostic.generateJSONCodeHighlights(map, keys.map(({ key: key , type: type , message: message })=>({ |
|
key: ((_prependKey = data.prependKey) !== null && _prependKey !== void 0 ? _prependKey : '') + key, |
|
type: type, |
|
message: message != null ? $8C1kk$parceldiagnostic.escapeMarkdown(message) : message |
|
}) |
|
)) |
|
} |
|
]; |
|
throw new ($parcel$interopDefault($8C1kk$parceldiagnostic))({ |
|
diagnostic: { |
|
message: message1, |
|
origin: origin, |
|
codeFrames: codeFrames |
|
} |
|
}); |
|
} |
|
}; |
|
|
|
|
|
|
|
class $3f2d35ad38f40faa$export$2e2bcd8739ae039 extends $8C1kk$stream.Transform { |
|
constructor(tap, options){ |
|
super({ |
|
...options |
|
}); |
|
this._tap = tap; |
|
} |
|
_transform(chunk, encoding, callback) { |
|
try { |
|
this._tap(Buffer.from(chunk)); |
|
callback(null, chunk); |
|
} catch (err) { |
|
callback(err); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
function $dfabc3743c08d51c$export$2e2bcd8739ae039(publicURL, assetPath) { |
|
const url = ($parcel$interopDefault($8C1kk$url)).parse(publicURL, false, true); // Leading / ensures that paths with colons are not parsed as a protocol. |
|
let p = assetPath.startsWith('/') ? assetPath : '/' + assetPath; |
|
const assetUrl = ($parcel$interopDefault($8C1kk$url)).parse(p); |
|
url.pathname = ($parcel$interopDefault($8C1kk$path)).posix.join(url.pathname, assetUrl.pathname); |
|
url.search = assetUrl.search; |
|
url.hash = assetUrl.hash; |
|
return ($parcel$interopDefault($8C1kk$url)).format(url); |
|
} |
|
|
|
|
|
|
|
|
|
function $b18990c6c3ea36b3$export$2e2bcd8739ae039(from, to) { |
|
return ($parcel$interopDefault($8C1kk$url)).format(($parcel$interopDefault($8C1kk$url)).parse(($parcel$interopDefault($8C1kk$path)).relative(from, to))); |
|
} |
|
|
|
|
|
function $43b0dce5dd282650$export$2e2bcd8739ae039(start, specifier, lineOffset = 0, columnOffset = 0, importWrapperLength = 2) { |
|
return { |
|
filePath: specifier, |
|
start: { |
|
line: start.line + lineOffset, |
|
column: start.column + columnOffset |
|
}, |
|
end: { |
|
line: start.line + lineOffset, |
|
column: start.column + specifier.length - 1 + importWrapperLength + columnOffset |
|
} |
|
}; |
|
} |
|
|
|
|
|
function $1ba22b2a95920d8e$export$2e2bcd8739ae039(fn, delay) { |
|
let timeout; |
|
return function(...args) { |
|
if (timeout) clearTimeout(timeout); |
|
timeout = setTimeout(()=>{ |
|
timeout = null; |
|
fn(...args); |
|
}, delay); |
|
}; |
|
} |
|
|
|
|
|
function $e499d3e618e93ebd$export$2e2bcd8739ae039(fn, delay) { |
|
let lastCalled; |
|
return function(...args) { |
|
if (lastCalled == null || lastCalled + delay <= Date.now()) { |
|
fn.call(this, ...args); |
|
lastCalled = Date.now(); |
|
} |
|
}; |
|
} |
|
|
|
|
|
var $618f8c1de80a427f$exports = {}; |
|
'use strict'; |
|
|
|
var $618f8c1de80a427f$require$promisify = $8C1kk$util.promisify; |
|
|
|
|
|
|
|
var $544c5203b18a57d8$exports = {}; |
|
'use strict'; |
|
|
|
|
|
var $bd6a007ad9027619$exports = {}; |
|
'use strict'; |
|
|
|
let $bd6a007ad9027619$var$isDocker; |
|
function $bd6a007ad9027619$var$hasDockerEnv() { |
|
try { |
|
$8C1kk$fs.statSync('/.dockerenv'); |
|
return true; |
|
} catch (_) { |
|
return false; |
|
} |
|
} |
|
function $bd6a007ad9027619$var$hasDockerCGroup() { |
|
try { |
|
return $8C1kk$fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker'); |
|
} catch (_) { |
|
return false; |
|
} |
|
} |
|
$bd6a007ad9027619$exports = ()=>{ |
|
if ($bd6a007ad9027619$var$isDocker === undefined) $bd6a007ad9027619$var$isDocker = $bd6a007ad9027619$var$hasDockerEnv() || $bd6a007ad9027619$var$hasDockerCGroup(); |
|
return $bd6a007ad9027619$var$isDocker; |
|
}; |
|
|
|
|
|
const $544c5203b18a57d8$var$isWsl = ()=>{ |
|
if (process.platform !== 'linux') return false; |
|
if ($8C1kk$os.release().toLowerCase().includes('microsoft')) { |
|
if ($bd6a007ad9027619$exports()) return false; |
|
return true; |
|
} |
|
try { |
|
return $8C1kk$fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft') ? !$bd6a007ad9027619$exports() : false; |
|
} catch (_) { |
|
return false; |
|
} |
|
}; |
|
if (process.env.__IS_WSL_TEST__) $544c5203b18a57d8$exports = $544c5203b18a57d8$var$isWsl; |
|
else $544c5203b18a57d8$exports = $544c5203b18a57d8$var$isWsl(); |
|
|
|
|
|
|
|
const $618f8c1de80a427f$var$pAccess = $618f8c1de80a427f$require$promisify($8C1kk$fs.access); |
|
const $618f8c1de80a427f$var$pExecFile = $618f8c1de80a427f$require$promisify($8C1kk$child_process.execFile); |
|
// Path to included `xdg-open`. |
|
const $618f8c1de80a427f$var$localXdgOpenPath = $8C1kk$path.join(__dirname, 'xdg-open'); |
|
// Convert a path from WSL format to Windows format: |
|
// `/mnt/c/Program Files/Example/MyApp.exe` → `C:\Program Files\Example\MyApp.exe` |
|
const $618f8c1de80a427f$var$wslToWindowsPath = async (path)=>{ |
|
const { stdout: stdout } = await $618f8c1de80a427f$var$pExecFile('wslpath', [ |
|
'-w', |
|
path |
|
]); |
|
return stdout.trim(); |
|
}; |
|
$618f8c1de80a427f$exports = async (target, options)=>{ |
|
if (typeof target !== 'string') throw new TypeError('Expected a `target`'); |
|
options = { |
|
wait: false, |
|
background: false, |
|
url: false, |
|
...options |
|
}; |
|
let command; |
|
let appArguments = []; |
|
const cliArguments = []; |
|
const childProcessOptions = { |
|
}; |
|
if (Array.isArray(options.app)) { |
|
appArguments = options.app.slice(1); |
|
options.app = options.app[0]; |
|
} |
|
// Encodes the target as if it were an URL. Especially useful to get |
|
// double-quotes through the “double-quotes on Windows caveat”, but it |
|
// can be used on any platform. |
|
if (options.url) { |
|
target = encodeURI(target); |
|
if ($544c5203b18a57d8$exports) target = target.replace(/&/g, '^&'); |
|
} |
|
if (process.platform === 'darwin') { |
|
command = 'open'; |
|
if (options.wait) cliArguments.push('--wait-apps'); |
|
if (options.background) cliArguments.push('--background'); |
|
if (options.app) cliArguments.push('-a', options.app); |
|
} else if (process.platform === 'win32' || $544c5203b18a57d8$exports && !$bd6a007ad9027619$exports()) { |
|
command = 'cmd' + ($544c5203b18a57d8$exports ? '.exe' : ''); |
|
cliArguments.push('/s', '/c', 'start', '""', '/b'); |
|
if (!$544c5203b18a57d8$exports) { |
|
// Always quoting target allows for URLs/paths to have spaces and unmarked characters, as `cmd.exe` will |
|
// interpret them as plain text to be forwarded as one unique argument. Enabling `windowsVerbatimArguments` |
|
// disables Node.js's default quotes and escapes handling (https://git.io/fjdem). |
|
// References: |
|
// - Issues #17, #44, #55, #77, #101, #115 |
|
// - Pull requests: #74, #98 |
|
// |
|
// As a result, all double-quotes are stripped from the `target` and do not get to your desired destination. |
|
target = `"${target}"`; |
|
childProcessOptions.windowsVerbatimArguments = true; |
|
if (options.app) options.app = `"${options.app}"`; |
|
} |
|
if (options.wait) cliArguments.push('/wait'); |
|
if (options.app) { |
|
if ($544c5203b18a57d8$exports && options.app.startsWith('/mnt/')) { |
|
const windowsPath = await $618f8c1de80a427f$var$wslToWindowsPath(options.app); |
|
options.app = windowsPath; |
|
} |
|
cliArguments.push(options.app); |
|
} |
|
if (appArguments.length > 0) cliArguments.push(...appArguments); |
|
} else { |
|
if (options.app) command = options.app; |
|
else { |
|
// When bundled by Webpack, there's no actual package file path and no local `xdg-open`. |
|
const isBundled = !__dirname || __dirname === '/'; |
|
// Check if local `xdg-open` exists and is executable. |
|
let exeLocalXdgOpen = false; |
|
try { |
|
await $618f8c1de80a427f$var$pAccess($618f8c1de80a427f$var$localXdgOpenPath, $8C1kk$fs.constants.X_OK); |
|
exeLocalXdgOpen = true; |
|
} catch (_) { |
|
} |
|
const useSystemXdgOpen = process.versions.electron || process.platform === 'android' || isBundled || !exeLocalXdgOpen; |
|
command = useSystemXdgOpen ? 'xdg-open' : $618f8c1de80a427f$var$localXdgOpenPath; |
|
} |
|
if (appArguments.length > 0) cliArguments.push(...appArguments); |
|
if (!options.wait) { |
|
// `xdg-open` will block the process unless stdio is ignored |
|
// and it's detached from the parent even if it's unref'd. |
|
childProcessOptions.stdio = 'ignore'; |
|
childProcessOptions.detached = true; |
|
} |
|
} |
|
cliArguments.push(target); |
|
if (process.platform === 'darwin' && appArguments.length > 0) cliArguments.push('--args', ...appArguments); |
|
const subprocess = $8C1kk$child_process.spawn(command, cliArguments, childProcessOptions); |
|
if (options.wait) return new Promise((resolve, reject)=>{ |
|
subprocess.once('error', reject); |
|
subprocess.once('close', (exitCode)=>{ |
|
if (exitCode > 0) { |
|
reject(new Error(`Exited with code ${exitCode}`)); |
|
return; |
|
} |
|
resolve(subprocess); |
|
}); |
|
}); |
|
subprocess.unref(); |
|
return subprocess; |
|
}; |
|
|
|
|
|
|
|
|
|
// https://github.com/react-native-community/cli/blob/e2be8a905285d9b37512fc78c9755b9635ecf805/packages/cli/src/commands/server/launchDebugger.ts#L28 |
|
function $f064b622a304e96c$var$getChromeAppName() { |
|
switch(process.platform){ |
|
case 'darwin': |
|
return 'google chrome'; |
|
case 'win32': |
|
return 'chrome'; |
|
case 'linux': |
|
if ($f064b622a304e96c$var$commandExistsUnixSync('google-chrome')) return 'google-chrome'; |
|
if ($f064b622a304e96c$var$commandExistsUnixSync('chromium-browser')) return 'chromium-browser'; |
|
return 'chromium'; |
|
default: |
|
return 'google-chrome'; |
|
} |
|
} |
|
function $f064b622a304e96c$var$commandExistsUnixSync(commandName) { |
|
try { |
|
const stdout = $8C1kk$child_process.execSync(`command -v ${commandName} 2>/dev/null` + ` && { echo >&1 '${commandName} found'; exit 0; }`); |
|
return !!stdout; |
|
} catch (error) { |
|
return false; |
|
} |
|
} |
|
function $f064b622a304e96c$var$getAppName(appName) { |
|
if ([ |
|
'google', |
|
'chrome' |
|
].includes(appName)) return $f064b622a304e96c$var$getChromeAppName(); |
|
else if ([ |
|
'brave', |
|
'Brave' |
|
].includes(appName)) return 'Brave Browser'; |
|
else return appName; |
|
} |
|
async function $f064b622a304e96c$export$2e2bcd8739ae039(url, browser) { |
|
try { |
|
const options = typeof browser === 'string' && browser.length > 0 ? { |
|
app: [ |
|
$f064b622a304e96c$var$getAppName(browser) |
|
] |
|
} : undefined; |
|
await (/*@__PURE__*/$parcel$interopDefault($618f8c1de80a427f$exports))(url, options); |
|
} catch (err) { |
|
($parcel$interopDefault($8C1kk$parcellogger)).error(`Unexpected error while opening in browser: ${browser}`, '@parcel/utils'); |
|
($parcel$interopDefault($8C1kk$parcellogger)).error(err, '@parcel/utils'); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var $284aeb9e515b63c0$exports = {}; |
|
var $284aeb9e515b63c0$var$clone = function() { |
|
function _instanceof(obj, type) { |
|
return type != null && obj instanceof type; |
|
} |
|
var nativeMap; |
|
try { |
|
nativeMap = Map; |
|
} catch (_) { |
|
// maybe a reference error because no `Map`. Give it a dummy value that no |
|
// value will ever be an instanceof. |
|
nativeMap = function() { |
|
}; |
|
} |
|
var nativeSet; |
|
try { |
|
nativeSet = Set; |
|
} catch (_1) { |
|
nativeSet = function() { |
|
}; |
|
} |
|
var nativePromise; |
|
try { |
|
nativePromise = Promise; |
|
} catch (_2) { |
|
nativePromise = function() { |
|
}; |
|
} |
|
/** |
|
* Clones (copies) an Object using deep copying. |
|
* |
|
* This function supports circular references by default, but if you are certain |
|
* there are no circular references in your object, you can save some CPU time |
|
* by calling clone(obj, false). |
|
* |
|
* Caution: if `circular` is false and `parent` contains circular references, |
|
* your program may enter an infinite loop and crash. |
|
* |
|
* @param `parent` - the object to be cloned |
|
* @param `circular` - set to true if the object to be cloned may contain |
|
* circular references. (optional - true by default) |
|
* @param `depth` - set to a number if the object is only to be cloned to |
|
* a particular depth. (optional - defaults to Infinity) |
|
* @param `prototype` - sets the prototype to be used when cloning an object. |
|
* (optional - defaults to parent prototype). |
|
* @param `includeNonEnumerable` - set to true if the non-enumerable properties |
|
* should be cloned as well. Non-enumerable properties on the prototype |
|
* chain will be ignored. (optional - false by default) |
|
*/ function clone(parent1, circular, depth1, prototype, includeNonEnumerable) { |
|
if (typeof circular === 'object') { |
|
depth1 = circular.depth; |
|
prototype = circular.prototype; |
|
includeNonEnumerable = circular.includeNonEnumerable; |
|
circular = circular.circular; |
|
} |
|
// maintain two arrays for circular references, where corresponding parents |
|
// and children have the same index |
|
var allParents = []; |
|
var allChildren = []; |
|
var useBuffer = typeof Buffer != 'undefined'; |
|
if (typeof circular == 'undefined') circular = true; |
|
if (typeof depth1 == 'undefined') depth1 = Infinity; |
|
// recurse this function so we don't reset allParents and allChildren |
|
function _clone(parent, depth) { |
|
// cloning null always returns null |
|
if (parent === null) return null; |
|
if (depth === 0) return parent; |
|
var child; |
|
var proto; |
|
if (typeof parent != 'object') return parent; |
|
if (_instanceof(parent, nativeMap)) child = new nativeMap(); |
|
else if (_instanceof(parent, nativeSet)) child = new nativeSet(); |
|
else if (_instanceof(parent, nativePromise)) child = new nativePromise(function(resolve, reject) { |
|
parent.then(function(value) { |
|
resolve(_clone(value, depth - 1)); |
|
}, function(err) { |
|
reject(_clone(err, depth - 1)); |
|
}); |
|
}); |
|
else if (clone.__isArray(parent)) child = []; |
|
else if (clone.__isRegExp(parent)) { |
|
child = new RegExp(parent.source, __getRegExpFlags(parent)); |
|
if (parent.lastIndex) child.lastIndex = parent.lastIndex; |
|
} else if (clone.__isDate(parent)) child = new Date(parent.getTime()); |
|
else if (useBuffer && Buffer.isBuffer(parent)) { |
|
if (Buffer.allocUnsafe) // Node.js >= 4.5.0 |
|
child = Buffer.allocUnsafe(parent.length); |
|
else // Older Node.js versions |
|
child = new Buffer(parent.length); |
|
parent.copy(child); |
|
return child; |
|
} else if (_instanceof(parent, Error)) child = Object.create(parent); |
|
else if (typeof prototype == 'undefined') { |
|
proto = Object.getPrototypeOf(parent); |
|
child = Object.create(proto); |
|
} else { |
|
child = Object.create(prototype); |
|
proto = prototype; |
|
} |
|
if (circular) { |
|
var index = allParents.indexOf(parent); |
|
if (index != -1) return allChildren[index]; |
|
allParents.push(parent); |
|
allChildren.push(child); |
|
} |
|
if (_instanceof(parent, nativeMap)) parent.forEach(function(value, key) { |
|
var keyChild = _clone(key, depth - 1); |
|
var valueChild = _clone(value, depth - 1); |
|
child.set(keyChild, valueChild); |
|
}); |
|
if (_instanceof(parent, nativeSet)) parent.forEach(function(value) { |
|
var entryChild = _clone(value, depth - 1); |
|
child.add(entryChild); |
|
}); |
|
for(var i in parent){ |
|
var attrs; |
|
if (proto) attrs = Object.getOwnPropertyDescriptor(proto, i); |
|
if (attrs && attrs.set == null) continue; |
|
child[i] = _clone(parent[i], depth - 1); |
|
} |
|
if (Object.getOwnPropertySymbols) { |
|
var symbols = Object.getOwnPropertySymbols(parent); |
|
for(var i = 0; i < symbols.length; i++){ |
|
// Don't need to worry about cloning a symbol because it is a primitive, |
|
// like a number or string. |
|
var symbol = symbols[i]; |
|
var descriptor = Object.getOwnPropertyDescriptor(parent, symbol); |
|
if (descriptor && !descriptor.enumerable && !includeNonEnumerable) continue; |
|
child[symbol] = _clone(parent[symbol], depth - 1); |
|
if (!descriptor.enumerable) Object.defineProperty(child, symbol, { |
|
enumerable: false |
|
}); |
|
} |
|
} |
|
if (includeNonEnumerable) { |
|
var allPropertyNames = Object.getOwnPropertyNames(parent); |
|
for(var i = 0; i < allPropertyNames.length; i++){ |
|
var propertyName = allPropertyNames[i]; |
|
var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName); |
|
if (descriptor && descriptor.enumerable) continue; |
|
child[propertyName] = _clone(parent[propertyName], depth - 1); |
|
Object.defineProperty(child, propertyName, { |
|
enumerable: false |
|
}); |
|
} |
|
} |
|
return child; |
|
} |
|
return _clone(parent1, depth1); |
|
} |
|
/** |
|
* Simple flat clone using prototype, accepts only objects, usefull for property |
|
* override on FLAT configuration object (no nested props). |
|
* |
|
* USE WITH CAUTION! This may not behave as you wish if you do not know how this |
|
* works. |
|
*/ clone.clonePrototype = function clonePrototype(parent) { |
|
if (parent === null) return null; |
|
var c = function() { |
|
}; |
|
c.prototype = parent; |
|
return new c(); |
|
}; |
|
// private utility functions |
|
function __objToStr(o) { |
|
return Object.prototype.toString.call(o); |
|
} |
|
clone.__objToStr = __objToStr; |
|
function __isDate(o) { |
|
return typeof o === 'object' && __objToStr(o) === '[object Date]'; |
|
} |
|
clone.__isDate = __isDate; |
|
function __isArray(o) { |
|
return typeof o === 'object' && __objToStr(o) === '[object Array]'; |
|
} |
|
clone.__isArray = __isArray; |
|
function __isRegExp(o) { |
|
return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; |
|
} |
|
clone.__isRegExp = __isRegExp; |
|
function __getRegExpFlags(re) { |
|
var flags = ''; |
|
if (re.global) flags += 'g'; |
|
if (re.ignoreCase) flags += 'i'; |
|
if (re.multiline) flags += 'm'; |
|
return flags; |
|
} |
|
clone.__getRegExpFlags = __getRegExpFlags; |
|
return clone; |
|
}(); |
|
if ("object" === 'object' && $284aeb9e515b63c0$exports) $284aeb9e515b63c0$exports = $284aeb9e515b63c0$var$clone; |
|
|
|
|
|
// This is a generated file. Do not edit. |
|
var $5dc3ee1f90b35876$var$Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/; |
|
var $5dc3ee1f90b35876$var$ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/; |
|
var $5dc3ee1f90b35876$var$ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/; |
|
var $5dc3ee1f90b35876$var$unicode = { |
|
Space_Separator: $5dc3ee1f90b35876$var$Space_Separator, |
|
ID_Start: $5dc3ee1f90b35876$var$ID_Start, |
|
ID_Continue: $5dc3ee1f90b35876$var$ID_Continue |
|
}; |
|
var $5dc3ee1f90b35876$var$util = { |
|
isSpaceSeparator (c) { |
|
return typeof c === 'string' && $5dc3ee1f90b35876$var$unicode.Space_Separator.test(c); |
|
}, |
|
isIdStartChar (c) { |
|
return typeof c === 'string' && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c === '$' || c === '_' || $5dc3ee1f90b35876$var$unicode.ID_Start.test(c)); |
|
}, |
|
isIdContinueChar (c) { |
|
return typeof c === 'string' && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c === '$' || c === '_' || c === '\u200C' || c === '\u200D' || $5dc3ee1f90b35876$var$unicode.ID_Continue.test(c)); |
|
}, |
|
isDigit (c) { |
|
return typeof c === 'string' && /[0-9]/.test(c); |
|
}, |
|
isHexDigit (c) { |
|
return typeof c === 'string' && /[0-9A-Fa-f]/.test(c); |
|
} |
|
}; |
|
let $5dc3ee1f90b35876$var$source; |
|
let $5dc3ee1f90b35876$var$parseState; |
|
let $5dc3ee1f90b35876$var$stack; |
|
let $5dc3ee1f90b35876$var$pos; |
|
let $5dc3ee1f90b35876$var$line; |
|
let $5dc3ee1f90b35876$var$column; |
|
let $5dc3ee1f90b35876$var$token; |
|
let $5dc3ee1f90b35876$var$key; |
|
let $5dc3ee1f90b35876$var$root; |
|
var $5dc3ee1f90b35876$var$parse = function parse(text, reviver) { |
|
$5dc3ee1f90b35876$var$source = String(text); |
|
$5dc3ee1f90b35876$var$parseState = 'start'; |
|
$5dc3ee1f90b35876$var$stack = []; |
|
$5dc3ee1f90b35876$var$pos = 0; |
|
$5dc3ee1f90b35876$var$line = 1; |
|
$5dc3ee1f90b35876$var$column = 0; |
|
$5dc3ee1f90b35876$var$token = undefined; |
|
$5dc3ee1f90b35876$var$key = undefined; |
|
$5dc3ee1f90b35876$var$root = undefined; |
|
do { |
|
$5dc3ee1f90b35876$var$token = $5dc3ee1f90b35876$var$lex(); |
|
// This code is unreachable. |
|
// if (!parseStates[parseState]) { |
|
// throw invalidParseState() |
|
// } |
|
$5dc3ee1f90b35876$var$parseStates[$5dc3ee1f90b35876$var$parseState](); |
|
}while ($5dc3ee1f90b35876$var$token.type !== 'eof') |
|
if (typeof reviver === 'function') return $5dc3ee1f90b35876$var$internalize({ |
|
'': $5dc3ee1f90b35876$var$root |
|
}, '', reviver); |
|
return $5dc3ee1f90b35876$var$root; |
|
}; |
|
function $5dc3ee1f90b35876$var$internalize(holder, name, reviver) { |
|
const value = holder[name]; |
|
if (value != null && typeof value === 'object') for(const key in value){ |
|
const replacement = $5dc3ee1f90b35876$var$internalize(value, key, reviver); |
|
if (replacement === undefined) delete value[key]; |
|
else value[key] = replacement; |
|
} |
|
return reviver.call(holder, name, value); |
|
} |
|
let $5dc3ee1f90b35876$var$lexState; |
|
let $5dc3ee1f90b35876$var$buffer; |
|
let $5dc3ee1f90b35876$var$doubleQuote; |
|
let $5dc3ee1f90b35876$var$sign; |
|
let $5dc3ee1f90b35876$var$c; |
|
function $5dc3ee1f90b35876$var$lex() { |
|
$5dc3ee1f90b35876$var$lexState = 'default'; |
|
$5dc3ee1f90b35876$var$buffer = ''; |
|
$5dc3ee1f90b35876$var$doubleQuote = false; |
|
$5dc3ee1f90b35876$var$sign = 1; |
|
for(;;){ |
|
$5dc3ee1f90b35876$var$c = $5dc3ee1f90b35876$var$peek(); |
|
// This code is unreachable. |
|
// if (!lexStates[lexState]) { |
|
// throw invalidLexState(lexState) |
|
// } |
|
const token = $5dc3ee1f90b35876$var$lexStates[$5dc3ee1f90b35876$var$lexState](); |
|
if (token) return token; |
|
} |
|
} |
|
function $5dc3ee1f90b35876$var$peek() { |
|
if ($5dc3ee1f90b35876$var$source[$5dc3ee1f90b35876$var$pos]) return String.fromCodePoint($5dc3ee1f90b35876$var$source.codePointAt($5dc3ee1f90b35876$var$pos)); |
|
} |
|
function $5dc3ee1f90b35876$var$read() { |
|
const c = $5dc3ee1f90b35876$var$peek(); |
|
if (c === '\n') { |
|
$5dc3ee1f90b35876$var$line++; |
|
$5dc3ee1f90b35876$var$column = 0; |
|
} else if (c) $5dc3ee1f90b35876$var$column += c.length; |
|
else $5dc3ee1f90b35876$var$column++; |
|
if (c) $5dc3ee1f90b35876$var$pos += c.length; |
|
return c; |
|
} |
|
const $5dc3ee1f90b35876$var$lexStates = { |
|
default () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '\t': |
|
case '\v': |
|
case '\f': |
|
case ' ': |
|
case '\u00A0': |
|
case '\uFEFF': |
|
case '\n': |
|
case '\r': |
|
case '\u2028': |
|
case '\u2029': |
|
$5dc3ee1f90b35876$var$read(); |
|
return; |
|
case '/': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'comment'; |
|
return; |
|
case undefined: |
|
$5dc3ee1f90b35876$var$read(); |
|
return $5dc3ee1f90b35876$var$newToken('eof'); |
|
} |
|
if ($5dc3ee1f90b35876$var$util.isSpaceSeparator($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$read(); |
|
return; |
|
} |
|
// This code is unreachable. |
|
// if (!lexStates[parseState]) { |
|
// throw invalidLexState(parseState) |
|
// } |
|
return $5dc3ee1f90b35876$var$lexStates[$5dc3ee1f90b35876$var$parseState](); |
|
}, |
|
comment () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '*': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'multiLineComment'; |
|
return; |
|
case '/': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'singleLineComment'; |
|
return; |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
multiLineComment () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '*': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'multiLineCommentAsterisk'; |
|
return; |
|
case undefined: |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
} |
|
$5dc3ee1f90b35876$var$read(); |
|
}, |
|
multiLineCommentAsterisk () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '*': |
|
$5dc3ee1f90b35876$var$read(); |
|
return; |
|
case '/': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'default'; |
|
return; |
|
case undefined: |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
} |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'multiLineComment'; |
|
}, |
|
singleLineComment () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '\n': |
|
case '\r': |
|
case '\u2028': |
|
case '\u2029': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'default'; |
|
return; |
|
case undefined: |
|
$5dc3ee1f90b35876$var$read(); |
|
return $5dc3ee1f90b35876$var$newToken('eof'); |
|
} |
|
$5dc3ee1f90b35876$var$read(); |
|
}, |
|
value () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '{': |
|
case '[': |
|
return $5dc3ee1f90b35876$var$newToken('punctuator', $5dc3ee1f90b35876$var$read()); |
|
case 'n': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$literal('ull'); |
|
return $5dc3ee1f90b35876$var$newToken('null', null); |
|
case 't': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$literal('rue'); |
|
return $5dc3ee1f90b35876$var$newToken('boolean', true); |
|
case 'f': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$literal('alse'); |
|
return $5dc3ee1f90b35876$var$newToken('boolean', false); |
|
case '-': |
|
case '+': |
|
if ($5dc3ee1f90b35876$var$read() === '-') $5dc3ee1f90b35876$var$sign = -1; |
|
$5dc3ee1f90b35876$var$lexState = 'sign'; |
|
return; |
|
case '.': |
|
$5dc3ee1f90b35876$var$buffer = $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalPointLeading'; |
|
return; |
|
case '0': |
|
$5dc3ee1f90b35876$var$buffer = $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'zero'; |
|
return; |
|
case '1': |
|
case '2': |
|
case '3': |
|
case '4': |
|
case '5': |
|
case '6': |
|
case '7': |
|
case '8': |
|
case '9': |
|
$5dc3ee1f90b35876$var$buffer = $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalInteger'; |
|
return; |
|
case 'I': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$literal('nfinity'); |
|
return $5dc3ee1f90b35876$var$newToken('numeric', Infinity); |
|
case 'N': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$literal('aN'); |
|
return $5dc3ee1f90b35876$var$newToken('numeric', NaN); |
|
case '"': |
|
case "'": |
|
$5dc3ee1f90b35876$var$doubleQuote = $5dc3ee1f90b35876$var$read() === '"'; |
|
$5dc3ee1f90b35876$var$buffer = ''; |
|
$5dc3ee1f90b35876$var$lexState = 'string'; |
|
return; |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
identifierNameStartEscape () { |
|
if ($5dc3ee1f90b35876$var$c !== 'u') throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
$5dc3ee1f90b35876$var$read(); |
|
const u = $5dc3ee1f90b35876$var$unicodeEscape(); |
|
switch(u){ |
|
case '$': |
|
case '_': |
|
break; |
|
default: |
|
if (!$5dc3ee1f90b35876$var$util.isIdStartChar(u)) throw $5dc3ee1f90b35876$var$invalidIdentifier(); |
|
break; |
|
} |
|
$5dc3ee1f90b35876$var$buffer += u; |
|
$5dc3ee1f90b35876$var$lexState = 'identifierName'; |
|
}, |
|
identifierName () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '$': |
|
case '_': |
|
case '\u200C': |
|
case '\u200D': |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
return; |
|
case '\\': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'identifierNameEscape'; |
|
return; |
|
} |
|
if ($5dc3ee1f90b35876$var$util.isIdContinueChar($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
return; |
|
} |
|
return $5dc3ee1f90b35876$var$newToken('identifier', $5dc3ee1f90b35876$var$buffer); |
|
}, |
|
identifierNameEscape () { |
|
if ($5dc3ee1f90b35876$var$c !== 'u') throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
$5dc3ee1f90b35876$var$read(); |
|
const u = $5dc3ee1f90b35876$var$unicodeEscape(); |
|
switch(u){ |
|
case '$': |
|
case '_': |
|
case '\u200C': |
|
case '\u200D': |
|
break; |
|
default: |
|
if (!$5dc3ee1f90b35876$var$util.isIdContinueChar(u)) throw $5dc3ee1f90b35876$var$invalidIdentifier(); |
|
break; |
|
} |
|
$5dc3ee1f90b35876$var$buffer += u; |
|
$5dc3ee1f90b35876$var$lexState = 'identifierName'; |
|
}, |
|
sign () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '.': |
|
$5dc3ee1f90b35876$var$buffer = $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalPointLeading'; |
|
return; |
|
case '0': |
|
$5dc3ee1f90b35876$var$buffer = $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'zero'; |
|
return; |
|
case '1': |
|
case '2': |
|
case '3': |
|
case '4': |
|
case '5': |
|
case '6': |
|
case '7': |
|
case '8': |
|
case '9': |
|
$5dc3ee1f90b35876$var$buffer = $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalInteger'; |
|
return; |
|
case 'I': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$literal('nfinity'); |
|
return $5dc3ee1f90b35876$var$newToken('numeric', $5dc3ee1f90b35876$var$sign * Infinity); |
|
case 'N': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$literal('aN'); |
|
return $5dc3ee1f90b35876$var$newToken('numeric', NaN); |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
zero () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '.': |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalPoint'; |
|
return; |
|
case 'e': |
|
case 'E': |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalExponent'; |
|
return; |
|
case 'x': |
|
case 'X': |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'hexadecimal'; |
|
return; |
|
} |
|
return $5dc3ee1f90b35876$var$newToken('numeric', $5dc3ee1f90b35876$var$sign * 0); |
|
}, |
|
decimalInteger () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '.': |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalPoint'; |
|
return; |
|
case 'e': |
|
case 'E': |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalExponent'; |
|
return; |
|
} |
|
if ($5dc3ee1f90b35876$var$util.isDigit($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
return; |
|
} |
|
return $5dc3ee1f90b35876$var$newToken('numeric', $5dc3ee1f90b35876$var$sign * Number($5dc3ee1f90b35876$var$buffer)); |
|
}, |
|
decimalPointLeading () { |
|
if ($5dc3ee1f90b35876$var$util.isDigit($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalFraction'; |
|
return; |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
decimalPoint () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case 'e': |
|
case 'E': |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalExponent'; |
|
return; |
|
} |
|
if ($5dc3ee1f90b35876$var$util.isDigit($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalFraction'; |
|
return; |
|
} |
|
return $5dc3ee1f90b35876$var$newToken('numeric', $5dc3ee1f90b35876$var$sign * Number($5dc3ee1f90b35876$var$buffer)); |
|
}, |
|
decimalFraction () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case 'e': |
|
case 'E': |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalExponent'; |
|
return; |
|
} |
|
if ($5dc3ee1f90b35876$var$util.isDigit($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
return; |
|
} |
|
return $5dc3ee1f90b35876$var$newToken('numeric', $5dc3ee1f90b35876$var$sign * Number($5dc3ee1f90b35876$var$buffer)); |
|
}, |
|
decimalExponent () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '+': |
|
case '-': |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalExponentSign'; |
|
return; |
|
} |
|
if ($5dc3ee1f90b35876$var$util.isDigit($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalExponentInteger'; |
|
return; |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
decimalExponentSign () { |
|
if ($5dc3ee1f90b35876$var$util.isDigit($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'decimalExponentInteger'; |
|
return; |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
decimalExponentInteger () { |
|
if ($5dc3ee1f90b35876$var$util.isDigit($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
return; |
|
} |
|
return $5dc3ee1f90b35876$var$newToken('numeric', $5dc3ee1f90b35876$var$sign * Number($5dc3ee1f90b35876$var$buffer)); |
|
}, |
|
hexadecimal () { |
|
if ($5dc3ee1f90b35876$var$util.isHexDigit($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'hexadecimalInteger'; |
|
return; |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
hexadecimalInteger () { |
|
if ($5dc3ee1f90b35876$var$util.isHexDigit($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
return; |
|
} |
|
return $5dc3ee1f90b35876$var$newToken('numeric', $5dc3ee1f90b35876$var$sign * Number($5dc3ee1f90b35876$var$buffer)); |
|
}, |
|
string () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '\\': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$escape(); |
|
return; |
|
case '"': |
|
if ($5dc3ee1f90b35876$var$doubleQuote) { |
|
$5dc3ee1f90b35876$var$read(); |
|
return $5dc3ee1f90b35876$var$newToken('string', $5dc3ee1f90b35876$var$buffer); |
|
} |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
return; |
|
case "'": |
|
if (!$5dc3ee1f90b35876$var$doubleQuote) { |
|
$5dc3ee1f90b35876$var$read(); |
|
return $5dc3ee1f90b35876$var$newToken('string', $5dc3ee1f90b35876$var$buffer); |
|
} |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
return; |
|
case '\n': |
|
case '\r': |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
case '\u2028': |
|
case '\u2029': |
|
$5dc3ee1f90b35876$var$separatorChar($5dc3ee1f90b35876$var$c); |
|
break; |
|
case undefined: |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
} |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
}, |
|
start () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '{': |
|
case '[': |
|
return $5dc3ee1f90b35876$var$newToken('punctuator', $5dc3ee1f90b35876$var$read()); |
|
} |
|
$5dc3ee1f90b35876$var$lexState = 'value'; |
|
}, |
|
beforePropertyName () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case '$': |
|
case '_': |
|
$5dc3ee1f90b35876$var$buffer = $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'identifierName'; |
|
return; |
|
case '\\': |
|
$5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'identifierNameStartEscape'; |
|
return; |
|
case '}': |
|
return $5dc3ee1f90b35876$var$newToken('punctuator', $5dc3ee1f90b35876$var$read()); |
|
case '"': |
|
case "'": |
|
$5dc3ee1f90b35876$var$doubleQuote = $5dc3ee1f90b35876$var$read() === '"'; |
|
$5dc3ee1f90b35876$var$lexState = 'string'; |
|
return; |
|
} |
|
if ($5dc3ee1f90b35876$var$util.isIdStartChar($5dc3ee1f90b35876$var$c)) { |
|
$5dc3ee1f90b35876$var$buffer += $5dc3ee1f90b35876$var$read(); |
|
$5dc3ee1f90b35876$var$lexState = 'identifierName'; |
|
return; |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
afterPropertyName () { |
|
if ($5dc3ee1f90b35876$var$c === ':') return $5dc3ee1f90b35876$var$newToken('punctuator', $5dc3ee1f90b35876$var$read()); |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
beforePropertyValue () { |
|
$5dc3ee1f90b35876$var$lexState = 'value'; |
|
}, |
|
afterPropertyValue () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case ',': |
|
case '}': |
|
return $5dc3ee1f90b35876$var$newToken('punctuator', $5dc3ee1f90b35876$var$read()); |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
beforeArrayValue () { |
|
if ($5dc3ee1f90b35876$var$c === ']') return $5dc3ee1f90b35876$var$newToken('punctuator', $5dc3ee1f90b35876$var$read()); |
|
$5dc3ee1f90b35876$var$lexState = 'value'; |
|
}, |
|
afterArrayValue () { |
|
switch($5dc3ee1f90b35876$var$c){ |
|
case ',': |
|
case ']': |
|
return $5dc3ee1f90b35876$var$newToken('punctuator', $5dc3ee1f90b35876$var$read()); |
|
} |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
}, |
|
end () { |
|
// This code is unreachable since it's handled by the default lexState. |
|
// if (c === undefined) { |
|
// read() |
|
// return newToken('eof') |
|
// } |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
} |
|
}; |
|
function $5dc3ee1f90b35876$var$newToken(type, value) { |
|
return { |
|
type: type, |
|
value: value, |
|
line: $5dc3ee1f90b35876$var$line, |
|
column: $5dc3ee1f90b35876$var$column |
|
}; |
|
} |
|
function $5dc3ee1f90b35876$var$literal(s) { |
|
for (const c of s){ |
|
const p = $5dc3ee1f90b35876$var$peek(); |
|
if (p !== c) throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
$5dc3ee1f90b35876$var$read(); |
|
} |
|
} |
|
function $5dc3ee1f90b35876$var$escape() { |
|
const c = $5dc3ee1f90b35876$var$peek(); |
|
switch(c){ |
|
case 'b': |
|
$5dc3ee1f90b35876$var$read(); |
|
return '\b'; |
|
case 'f': |
|
$5dc3ee1f90b35876$var$read(); |
|
return '\f'; |
|
case 'n': |
|
$5dc3ee1f90b35876$var$read(); |
|
return '\n'; |
|
case 'r': |
|
$5dc3ee1f90b35876$var$read(); |
|
return '\r'; |
|
case 't': |
|
$5dc3ee1f90b35876$var$read(); |
|
return '\t'; |
|
case 'v': |
|
$5dc3ee1f90b35876$var$read(); |
|
return '\v'; |
|
case '0': |
|
$5dc3ee1f90b35876$var$read(); |
|
if ($5dc3ee1f90b35876$var$util.isDigit($5dc3ee1f90b35876$var$peek())) throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
return '\0'; |
|
case 'x': |
|
$5dc3ee1f90b35876$var$read(); |
|
return $5dc3ee1f90b35876$var$hexEscape(); |
|
case 'u': |
|
$5dc3ee1f90b35876$var$read(); |
|
return $5dc3ee1f90b35876$var$unicodeEscape(); |
|
case '\n': |
|
case '\u2028': |
|
case '\u2029': |
|
$5dc3ee1f90b35876$var$read(); |
|
return ''; |
|
case '\r': |
|
$5dc3ee1f90b35876$var$read(); |
|
if ($5dc3ee1f90b35876$var$peek() === '\n') $5dc3ee1f90b35876$var$read(); |
|
return ''; |
|
case '1': |
|
case '2': |
|
case '3': |
|
case '4': |
|
case '5': |
|
case '6': |
|
case '7': |
|
case '8': |
|
case '9': |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
case undefined: |
|
throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
} |
|
return $5dc3ee1f90b35876$var$read(); |
|
} |
|
function $5dc3ee1f90b35876$var$hexEscape() { |
|
let buffer = ''; |
|
let c = $5dc3ee1f90b35876$var$peek(); |
|
if (!$5dc3ee1f90b35876$var$util.isHexDigit(c)) throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
buffer += $5dc3ee1f90b35876$var$read(); |
|
c = $5dc3ee1f90b35876$var$peek(); |
|
if (!$5dc3ee1f90b35876$var$util.isHexDigit(c)) throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
buffer += $5dc3ee1f90b35876$var$read(); |
|
return String.fromCodePoint(parseInt(buffer, 16)); |
|
} |
|
function $5dc3ee1f90b35876$var$unicodeEscape() { |
|
let buffer = ''; |
|
let count = 4; |
|
while(count-- > 0){ |
|
const c = $5dc3ee1f90b35876$var$peek(); |
|
if (!$5dc3ee1f90b35876$var$util.isHexDigit(c)) throw $5dc3ee1f90b35876$var$invalidChar($5dc3ee1f90b35876$var$read()); |
|
buffer += $5dc3ee1f90b35876$var$read(); |
|
} |
|
return String.fromCodePoint(parseInt(buffer, 16)); |
|
} |
|
const $5dc3ee1f90b35876$var$parseStates = { |
|
start () { |
|
if ($5dc3ee1f90b35876$var$token.type === 'eof') throw $5dc3ee1f90b35876$var$invalidEOF(); |
|
$5dc3ee1f90b35876$var$push(); |
|
}, |
|
beforePropertyName () { |
|
switch($5dc3ee1f90b35876$var$token.type){ |
|
case 'identifier': |
|
case 'string': |
|
$5dc3ee1f90b35876$var$key = $5dc3ee1f90b35876$var$token.value; |
|
$5dc3ee1f90b35876$var$parseState = 'afterPropertyName'; |
|
return; |
|
case 'punctuator': |
|
// This code is unreachable since it's handled by the lexState. |
|
// if (token.value !== '}') { |
|
// throw invalidToken() |
|
// } |
|
$5dc3ee1f90b35876$var$pop(); |
|
return; |
|
case 'eof': |
|
throw $5dc3ee1f90b35876$var$invalidEOF(); |
|
} |
|
// This code is unreachable since it's handled by the lexState. |
|
// throw invalidToken() |
|
}, |
|
afterPropertyName () { |
|
// This code is unreachable since it's handled by the lexState. |
|
// if (token.type !== 'punctuator' || token.value !== ':') { |
|
// throw invalidToken() |
|
// } |
|
if ($5dc3ee1f90b35876$var$token.type === 'eof') throw $5dc3ee1f90b35876$var$invalidEOF(); |
|
$5dc3ee1f90b35876$var$parseState = 'beforePropertyValue'; |
|
}, |
|
beforePropertyValue () { |
|
if ($5dc3ee1f90b35876$var$token.type === 'eof') throw $5dc3ee1f90b35876$var$invalidEOF(); |
|
$5dc3ee1f90b35876$var$push(); |
|
}, |
|
beforeArrayValue () { |
|
if ($5dc3ee1f90b35876$var$token.type === 'eof') throw $5dc3ee1f90b35876$var$invalidEOF(); |
|
if ($5dc3ee1f90b35876$var$token.type === 'punctuator' && $5dc3ee1f90b35876$var$token.value === ']') { |
|
$5dc3ee1f90b35876$var$pop(); |
|
return; |
|
} |
|
$5dc3ee1f90b35876$var$push(); |
|
}, |
|
afterPropertyValue () { |
|
// This code is unreachable since it's handled by the lexState. |
|
// if (token.type !== 'punctuator') { |
|
// throw invalidToken() |
|
// } |
|
if ($5dc3ee1f90b35876$var$token.type === 'eof') throw $5dc3ee1f90b35876$var$invalidEOF(); |
|
switch($5dc3ee1f90b35876$var$token.value){ |
|
case ',': |
|
$5dc3ee1f90b35876$var$parseState = 'beforePropertyName'; |
|
return; |
|
case '}': |
|
$5dc3ee1f90b35876$var$pop(); |
|
} |
|
// This code is unreachable since it's handled by the lexState. |
|
// throw invalidToken() |
|
}, |
|
afterArrayValue () { |
|
// This code is unreachable since it's handled by the lexState. |
|
// if (token.type !== 'punctuator') { |
|
// throw invalidToken() |
|
// } |
|
if ($5dc3ee1f90b35876$var$token.type === 'eof') throw $5dc3ee1f90b35876$var$invalidEOF(); |
|
switch($5dc3ee1f90b35876$var$token.value){ |
|
case ',': |
|
$5dc3ee1f90b35876$var$parseState = 'beforeArrayValue'; |
|
return; |
|
case ']': |
|
$5dc3ee1f90b35876$var$pop(); |
|
} |
|
// This code is unreachable since it's handled by the lexState. |
|
// throw invalidToken() |
|
}, |
|
end () { |
|
// This code is unreachable since it's handled by the lexState. |
|
// if (token.type !== 'eof') { |
|
// throw invalidToken() |
|
// } |
|
} |
|
}; |
|
function $5dc3ee1f90b35876$var$push() { |
|
let value; |
|
switch($5dc3ee1f90b35876$var$token.type){ |
|
case 'punctuator': |
|
switch($5dc3ee1f90b35876$var$token.value){ |
|
case '{': |
|
value = { |
|
}; |
|
break; |
|
case '[': |
|
value = []; |
|
break; |
|
} |
|
break; |
|
case 'null': |
|
case 'boolean': |
|
case 'numeric': |
|
case 'string': |
|
value = $5dc3ee1f90b35876$var$token.value; |
|
break; |
|
} |
|
if ($5dc3ee1f90b35876$var$root === undefined) $5dc3ee1f90b35876$var$root = value; |
|
else { |
|
const parent = $5dc3ee1f90b35876$var$stack[$5dc3ee1f90b35876$var$stack.length - 1]; |
|
if (Array.isArray(parent)) parent.push(value); |
|
else parent[$5dc3ee1f90b35876$var$key] = value; |
|
} |
|
if (value !== null && typeof value === 'object') { |
|
$5dc3ee1f90b35876$var$stack.push(value); |
|
if (Array.isArray(value)) $5dc3ee1f90b35876$var$parseState = 'beforeArrayValue'; |
|
else $5dc3ee1f90b35876$var$parseState = 'beforePropertyName'; |
|
} else { |
|
const current = $5dc3ee1f90b35876$var$stack[$5dc3ee1f90b35876$var$stack.length - 1]; |
|
if (current == null) $5dc3ee1f90b35876$var$parseState = 'end'; |
|
else if (Array.isArray(current)) $5dc3ee1f90b35876$var$parseState = 'afterArrayValue'; |
|
else $5dc3ee1f90b35876$var$parseState = 'afterPropertyValue'; |
|
} |
|
} |
|
function $5dc3ee1f90b35876$var$pop() { |
|
$5dc3ee1f90b35876$var$stack.pop(); |
|
const current = $5dc3ee1f90b35876$var$stack[$5dc3ee1f90b35876$var$stack.length - 1]; |
|
if (current == null) $5dc3ee1f90b35876$var$parseState = 'end'; |
|
else if (Array.isArray(current)) $5dc3ee1f90b35876$var$parseState = 'afterArrayValue'; |
|
else $5dc3ee1f90b35876$var$parseState = 'afterPropertyValue'; |
|
} |
|
// This code is unreachable. |
|
// function invalidParseState () { |
|
// return new Error(`JSON5: invalid parse state '${parseState}'`) |
|
// } |
|
// This code is unreachable. |
|
// function invalidLexState (state) { |
|
// return new Error(`JSON5: invalid lex state '${state}'`) |
|
// } |
|
function $5dc3ee1f90b35876$var$invalidChar(c) { |
|
if (c === undefined) return $5dc3ee1f90b35876$var$syntaxError(`JSON5: invalid end of input at ${$5dc3ee1f90b35876$var$line}:${$5dc3ee1f90b35876$var$column}`); |
|
return $5dc3ee1f90b35876$var$syntaxError(`JSON5: invalid character '${$5dc3ee1f90b35876$var$formatChar(c)}' at ${$5dc3ee1f90b35876$var$line}:${$5dc3ee1f90b35876$var$column}`); |
|
} |
|
function $5dc3ee1f90b35876$var$invalidEOF() { |
|
return $5dc3ee1f90b35876$var$syntaxError(`JSON5: invalid end of input at ${$5dc3ee1f90b35876$var$line}:${$5dc3ee1f90b35876$var$column}`); |
|
} |
|
// This code is unreachable. |
|
// function invalidToken () { |
|
// if (token.type === 'eof') { |
|
// return syntaxError(`JSON5: invalid end of input at ${line}:${column}`) |
|
// } |
|
// const c = String.fromCodePoint(token.value.codePointAt(0)) |
|
// return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`) |
|
// } |
|
function $5dc3ee1f90b35876$var$invalidIdentifier() { |
|
$5dc3ee1f90b35876$var$column -= 5; |
|
return $5dc3ee1f90b35876$var$syntaxError(`JSON5: invalid identifier character at ${$5dc3ee1f90b35876$var$line}:${$5dc3ee1f90b35876$var$column}`); |
|
} |
|
function $5dc3ee1f90b35876$var$separatorChar(c) { |
|
console.warn(`JSON5: '${$5dc3ee1f90b35876$var$formatChar(c)}' in strings is not valid ECMAScript; consider escaping`); |
|
} |
|
function $5dc3ee1f90b35876$var$formatChar(c) { |
|
const replacements = { |
|
"'": "\\'", |
|
'"': '\\"', |
|
'\\': '\\\\', |
|
'\b': '\\b', |
|
'\f': '\\f', |
|
'\n': '\\n', |
|
'\r': '\\r', |
|
'\t': '\\t', |
|
'\v': '\\v', |
|
'\0': '\\0', |
|
'\u2028': '\\u2028', |
|
'\u2029': '\\u2029' |
|
}; |
|
if (replacements[c]) return replacements[c]; |
|
if (c < ' ') { |
|
const hexString = c.charCodeAt(0).toString(16); |
|
return '\\x' + ('00' + hexString).substring(hexString.length); |
|
} |
|
return c; |
|
} |
|
function $5dc3ee1f90b35876$var$syntaxError(message) { |
|
const err = new SyntaxError(message); |
|
err.lineNumber = $5dc3ee1f90b35876$var$line; |
|
err.columnNumber = $5dc3ee1f90b35876$var$column; |
|
return err; |
|
} |
|
var $5dc3ee1f90b35876$var$stringify = function stringify(value1, replacer, space) { |
|
const stack = []; |
|
let indent = ''; |
|
let propertyList; |
|
let replacerFunc; |
|
let gap = ''; |
|
let quote; |
|
if (replacer != null && typeof replacer === 'object' && !Array.isArray(replacer)) { |
|
space = replacer.space; |
|
quote = replacer.quote; |
|
replacer = replacer.replacer; |
|
} |
|
if (typeof replacer === 'function') replacerFunc = replacer; |
|
else if (Array.isArray(replacer)) { |
|
propertyList = []; |
|
for (const v of replacer){ |
|
let item; |
|
if (typeof v === 'string') item = v; |
|
else if (typeof v === 'number' || v instanceof String || v instanceof Number) item = String(v); |
|
if (item !== undefined && propertyList.indexOf(item) < 0) propertyList.push(item); |
|
} |
|
} |
|
if (space instanceof Number) space = Number(space); |
|
else if (space instanceof String) space = String(space); |
|
if (typeof space === 'number') { |
|
if (space > 0) { |
|
space = Math.min(10, Math.floor(space)); |
|
gap = ' '.substr(0, space); |
|
} |
|
} else if (typeof space === 'string') gap = space.substr(0, 10); |
|
function serializeProperty(key, holder) { |
|
let value = holder[key]; |
|
if (value != null) { |
|
if (typeof value.toJSON5 === 'function') { |
|
value = value.toJSON5(key); |
|
} else if (typeof value.toJSON === 'function') { |
|
value = value.toJSON(key); |
|
} |
|
} |
|
if (replacerFunc) { |
|
value = replacerFunc.call(holder, key, value); |
|
} |
|
if (value instanceof Number) { |
|
value = Number(value); |
|
} else if (value instanceof String) { |
|
value = String(value); |
|
} else if (value instanceof Boolean) { |
|
value = value.valueOf(); |
|
} |
|
switch(value){ |
|
case null: |
|
return 'null'; |
|
case true: |
|
return 'true'; |
|
case false: |
|
return 'false'; |
|
} |
|
if (typeof value === 'string') { |
|
return quoteString(value, false); |
|
} |
|
if (typeof value === 'number') { |
|
return String(value); |
|
} |
|
if (typeof value === 'object') { |
|
return Array.isArray(value) ? serializeArray(value) : serializeObject(value); |
|
} |
|
return undefined; |
|
} |
|
function quoteString(value) { |
|
const quotes = { |
|
"'": 0.1, |
|
'"': 0.2 |
|
}; |
|
const replacements = { |
|
"'": "\\'", |
|
'"': '\\"', |
|
'\\': '\\\\', |
|
'\b': '\\b', |
|
'\f': '\\f', |
|
'\n': '\\n', |
|
'\r': '\\r', |
|
'\t': '\\t', |
|
'\v': '\\v', |
|
'\0': '\\0', |
|
'\u2028': '\\u2028', |
|
'\u2029': '\\u2029' |
|
}; |
|
let product = ''; |
|
for(let i = 0; i < value.length; i++){ |
|
const c = value[i]; |
|
switch(c){ |
|
case "'": |
|
case '"': |
|
quotes[c]++; |
|
product += c; |
|
continue; |
|
case '\0': |
|
if ($5dc3ee1f90b35876$var$util.isDigit(value[i + 1])) { |
|
product += '\\x00'; |
|
continue; |
|
} |
|
} |
|
if (replacements[c]) { |
|
product += replacements[c]; |
|
continue; |
|
} |
|
if (c < ' ') { |
|
let hexString = c.charCodeAt(0).toString(16); |
|
product += '\\x' + ('00' + hexString).substring(hexString.length); |
|
continue; |
|
} |
|
product += c; |
|
} |
|
const quoteChar = quote || Object.keys(quotes).reduce((a, b)=>quotes[a] < quotes[b] ? a : b |
|
); |
|
product = product.replace(new RegExp(quoteChar, 'g'), replacements[quoteChar]); |
|
return quoteChar + product + quoteChar; |
|
} |
|
function serializeObject(value) { |
|
if (stack.indexOf(value) >= 0) { |
|
throw TypeError('Converting circular structure to JSON5'); |
|
} |
|
stack.push(value); |
|
let stepback = indent; |
|
indent = indent + gap; |
|
let keys = propertyList || Object.keys(value); |
|
let partial = []; |
|
for (const key of keys){ |
|
const propertyString = serializeProperty(key, value); |
|
if (propertyString !== undefined) { |
|
let member = serializeKey(key) + ':'; |
|
if (gap !== '') { |
|
member += ' '; |
|
} |
|
member += propertyString; |
|
partial.push(member); |
|
} |
|
} |
|
let final; |
|
if (partial.length === 0) { |
|
final = '{}'; |
|
} else { |
|
let properties; |
|
if (gap === '') { |
|
properties = partial.join(','); |
|
final = '{' + properties + '}'; |
|
} else { |
|
let separator = ',\n' + indent; |
|
properties = partial.join(separator); |
|
final = '{\n' + indent + properties + ',\n' + stepback + '}'; |
|
} |
|
} |
|
stack.pop(); |
|
indent = stepback; |
|
return final; |
|
} |
|
function serializeKey(key) { |
|
if (key.length === 0) { |
|
return quoteString(key, true); |
|
} |
|
const firstChar = String.fromCodePoint(key.codePointAt(0)); |
|
if (!$5dc3ee1f90b35876$var$util.isIdStartChar(firstChar)) { |
|
return quoteString(key, true); |
|
} |
|
for(let i = firstChar.length; i < key.length; i++){ |
|
if (!$5dc3ee1f90b35876$var$util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) { |
|
return quoteString(key, true); |
|
} |
|
} |
|
return key; |
|
} |
|
function serializeArray(value) { |
|
if (stack.indexOf(value) >= 0) { |
|
throw TypeError('Converting circular structure to JSON5'); |
|
} |
|
stack.push(value); |
|
let stepback = indent; |
|
indent = indent + gap; |
|
let partial = []; |
|
for(let i = 0; i < value.length; i++){ |
|
const propertyString = serializeProperty(String(i), value); |
|
partial.push(propertyString !== undefined ? propertyString : 'null'); |
|
} |
|
let final; |
|
if (partial.length === 0) { |
|
final = '[]'; |
|
} else { |
|
if (gap === '') { |
|
let properties = partial.join(','); |
|
final = '[' + properties + ']'; |
|
} else { |
|
let separator = ',\n' + indent; |
|
let properties = partial.join(separator); |
|
final = '[\n' + indent + properties + ',\n' + stepback + ']'; |
|
} |
|
} |
|
stack.pop(); |
|
indent = stepback; |
|
return final; |
|
} |
|
return serializeProperty('', { |
|
'': value1 |
|
}); |
|
}; |
|
const $5dc3ee1f90b35876$var$JSON5 = { |
|
parse: $5dc3ee1f90b35876$var$parse, |
|
stringify: $5dc3ee1f90b35876$var$stringify |
|
}; |
|
var $5dc3ee1f90b35876$var$lib = $5dc3ee1f90b35876$var$JSON5; |
|
var $5dc3ee1f90b35876$export$2e2bcd8739ae039 = $5dc3ee1f90b35876$var$lib; |
|
|
|
|
|
var $830470103c08108e$export$98e6a39c04603d36; |
|
var $830470103c08108e$export$fac44ee5b035f737; |
|
'use strict'; |
|
|
|
$830470103c08108e$export$98e6a39c04603d36 = (parcelRequire("5SlBN")); |
|
|
|
$830470103c08108e$export$fac44ee5b035f737 = (parcelRequire("224JI")); |
|
|
|
|
|
var $1c9e97ff3b9eceee$exports = {}; |
|
'use strict'; |
|
var $3d36175a98d16391$exports = {}; |
|
'use strict'; |
|
$3d36175a98d16391$exports = $3d36175a98d16391$var$Yallist; |
|
$3d36175a98d16391$var$Yallist.Node = $3d36175a98d16391$var$Node; |
|
$3d36175a98d16391$var$Yallist.create = $3d36175a98d16391$var$Yallist; |
|
function $3d36175a98d16391$var$Yallist(list) { |
|
var self = this; |
|
if (!(self instanceof $3d36175a98d16391$var$Yallist)) self = new $3d36175a98d16391$var$Yallist(); |
|
self.tail = null; |
|
self.head = null; |
|
self.length = 0; |
|
if (list && typeof list.forEach === 'function') list.forEach(function(item) { |
|
self.push(item); |
|
}); |
|
else if (arguments.length > 0) for(var i = 0, l = arguments.length; i < l; i++)self.push(arguments[i]); |
|
return self; |
|
} |
|
$3d36175a98d16391$var$Yallist.prototype.removeNode = function(node) { |
|
if (node.list !== this) throw new Error('removing node which does not belong to this list'); |
|
var next = node.next; |
|
var prev = node.prev; |
|
if (next) next.prev = prev; |
|
if (prev) prev.next = next; |
|
if (node === this.head) this.head = next; |
|
if (node === this.tail) this.tail = prev; |
|
node.list.length--; |
|
node.next = null; |
|
node.prev = null; |
|
node.list = null; |
|
return next; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.unshiftNode = function(node) { |
|
if (node === this.head) return; |
|
if (node.list) node.list.removeNode(node); |
|
var head = this.head; |
|
node.list = this; |
|
node.next = head; |
|
if (head) head.prev = node; |
|
this.head = node; |
|
if (!this.tail) this.tail = node; |
|
this.length++; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.pushNode = function(node) { |
|
if (node === this.tail) return; |
|
if (node.list) node.list.removeNode(node); |
|
var tail = this.tail; |
|
node.list = this; |
|
node.prev = tail; |
|
if (tail) tail.next = node; |
|
this.tail = node; |
|
if (!this.head) this.head = node; |
|
this.length++; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.push = function() { |
|
for(var i = 0, l = arguments.length; i < l; i++)$3d36175a98d16391$var$push(this, arguments[i]); |
|
return this.length; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.unshift = function() { |
|
for(var i = 0, l = arguments.length; i < l; i++)$3d36175a98d16391$var$unshift(this, arguments[i]); |
|
return this.length; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.pop = function() { |
|
if (!this.tail) return undefined; |
|
var res = this.tail.value; |
|
this.tail = this.tail.prev; |
|
if (this.tail) this.tail.next = null; |
|
else this.head = null; |
|
this.length--; |
|
return res; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.shift = function() { |
|
if (!this.head) return undefined; |
|
var res = this.head.value; |
|
this.head = this.head.next; |
|
if (this.head) this.head.prev = null; |
|
else this.tail = null; |
|
this.length--; |
|
return res; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.forEach = function(fn, thisp) { |
|
thisp = thisp || this; |
|
for(var walker = this.head, i = 0; walker !== null; i++){ |
|
fn.call(thisp, walker.value, i, this); |
|
walker = walker.next; |
|
} |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.forEachReverse = function(fn, thisp) { |
|
thisp = thisp || this; |
|
for(var walker = this.tail, i = this.length - 1; walker !== null; i--){ |
|
fn.call(thisp, walker.value, i, this); |
|
walker = walker.prev; |
|
} |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.get = function(n) { |
|
for(var i = 0, walker = this.head; walker !== null && i < n; i++)// abort out of the list early if we hit a cycle |
|
walker = walker.next; |
|
if (i === n && walker !== null) return walker.value; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.getReverse = function(n) { |
|
for(var i = 0, walker = this.tail; walker !== null && i < n; i++)// abort out of the list early if we hit a cycle |
|
walker = walker.prev; |
|
if (i === n && walker !== null) return walker.value; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.map = function(fn, thisp) { |
|
thisp = thisp || this; |
|
var res = new $3d36175a98d16391$var$Yallist(); |
|
for(var walker = this.head; walker !== null;){ |
|
res.push(fn.call(thisp, walker.value, this)); |
|
walker = walker.next; |
|
} |
|
return res; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.mapReverse = function(fn, thisp) { |
|
thisp = thisp || this; |
|
var res = new $3d36175a98d16391$var$Yallist(); |
|
for(var walker = this.tail; walker !== null;){ |
|
res.push(fn.call(thisp, walker.value, this)); |
|
walker = walker.prev; |
|
} |
|
return res; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.reduce = function(fn, initial) { |
|
var acc; |
|
var walker = this.head; |
|
if (arguments.length > 1) acc = initial; |
|
else if (this.head) { |
|
walker = this.head.next; |
|
acc = this.head.value; |
|
} else throw new TypeError('Reduce of empty list with no initial value'); |
|
for(var i = 0; walker !== null; i++){ |
|
acc = fn(acc, walker.value, i); |
|
walker = walker.next; |
|
} |
|
return acc; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.reduceReverse = function(fn, initial) { |
|
var acc; |
|
var walker = this.tail; |
|
if (arguments.length > 1) acc = initial; |
|
else if (this.tail) { |
|
walker = this.tail.prev; |
|
acc = this.tail.value; |
|
} else throw new TypeError('Reduce of empty list with no initial value'); |
|
for(var i = this.length - 1; walker !== null; i--){ |
|
acc = fn(acc, walker.value, i); |
|
walker = walker.prev; |
|
} |
|
return acc; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.toArray = function() { |
|
var arr = new Array(this.length); |
|
for(var i = 0, walker = this.head; walker !== null; i++){ |
|
arr[i] = walker.value; |
|
walker = walker.next; |
|
} |
|
return arr; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.toArrayReverse = function() { |
|
var arr = new Array(this.length); |
|
for(var i = 0, walker = this.tail; walker !== null; i++){ |
|
arr[i] = walker.value; |
|
walker = walker.prev; |
|
} |
|
return arr; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.slice = function(from, to) { |
|
to = to || this.length; |
|
if (to < 0) to += this.length; |
|
from = from || 0; |
|
if (from < 0) from += this.length; |
|
var ret = new $3d36175a98d16391$var$Yallist(); |
|
if (to < from || to < 0) return ret; |
|
if (from < 0) from = 0; |
|
if (to > this.length) to = this.length; |
|
for(var i = 0, walker = this.head; walker !== null && i < from; i++)walker = walker.next; |
|
for(; walker !== null && i < to; i++, walker = walker.next)ret.push(walker.value); |
|
return ret; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.sliceReverse = function(from, to) { |
|
to = to || this.length; |
|
if (to < 0) to += this.length; |
|
from = from || 0; |
|
if (from < 0) from += this.length; |
|
var ret = new $3d36175a98d16391$var$Yallist(); |
|
if (to < from || to < 0) return ret; |
|
if (from < 0) from = 0; |
|
if (to > this.length) to = this.length; |
|
for(var i = this.length, walker = this.tail; walker !== null && i > to; i--)walker = walker.prev; |
|
for(; walker !== null && i > from; i--, walker = walker.prev)ret.push(walker.value); |
|
return ret; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.splice = function(start, deleteCount, ...nodes) { |
|
if (start > this.length) start = this.length - 1; |
|
if (start < 0) start = this.length + start; |
|
for(var i = 0, walker = this.head; walker !== null && i < start; i++)walker = walker.next; |
|
var ret = []; |
|
for(var i = 0; walker && i < deleteCount; i++){ |
|
ret.push(walker.value); |
|
walker = this.removeNode(walker); |
|
} |
|
if (walker === null) walker = this.tail; |
|
if (walker !== this.head && walker !== this.tail) walker = walker.prev; |
|
for(var i = 0; i < nodes.length; i++)walker = $3d36175a98d16391$var$insert(this, walker, nodes[i]); |
|
return ret; |
|
}; |
|
$3d36175a98d16391$var$Yallist.prototype.reverse = function() { |
|
var head = this.head; |
|
var tail = this.tail; |
|
for(var walker = head; walker !== null; walker = walker.prev){ |
|
var p = walker.prev; |
|
walker.prev = walker.next; |
|
walker.next = p; |
|
} |
|
this.head = tail; |
|
this.tail = head; |
|
return this; |
|
}; |
|
function $3d36175a98d16391$var$insert(self, node, value) { |
|
var inserted = node === self.head ? new $3d36175a98d16391$var$Node(value, null, node, self) : new $3d36175a98d16391$var$Node(value, node, node.next, self); |
|
if (inserted.next === null) self.tail = inserted; |
|
if (inserted.prev === null) self.head = inserted; |
|
self.length++; |
|
return inserted; |
|
} |
|
function $3d36175a98d16391$var$push(self, item) { |
|
self.tail = new $3d36175a98d16391$var$Node(item, self.tail, null, self); |
|
if (!self.head) self.head = self.tail; |
|
self.length++; |
|
} |
|
function $3d36175a98d16391$var$unshift(self, item) { |
|
self.head = new $3d36175a98d16391$var$Node(item, null, self.head, self); |
|
if (!self.tail) self.tail = self.head; |
|
self.length++; |
|
} |
|
function $3d36175a98d16391$var$Node(value, prev, next, list) { |
|
if (!(this instanceof $3d36175a98d16391$var$Node)) return new $3d36175a98d16391$var$Node(value, prev, next, list); |
|
this.list = list; |
|
this.value = value; |
|
if (prev) { |
|
prev.next = this; |
|
this.prev = prev; |
|
} else this.prev = null; |
|
if (next) { |
|
next.prev = this; |
|
this.next = next; |
|
} else this.next = null; |
|
} |
|
|
|
try { |
|
// add if support for Symbol.iterator is present |
|
(parcelRequire("lADnf"))($3d36175a98d16391$var$Yallist); |
|
} catch (er) { |
|
} |
|
|
|
|
|
const $1c9e97ff3b9eceee$var$MAX = Symbol('max'); |
|
const $1c9e97ff3b9eceee$var$LENGTH = Symbol('length'); |
|
const $1c9e97ff3b9eceee$var$LENGTH_CALCULATOR = Symbol('lengthCalculator'); |
|
const $1c9e97ff3b9eceee$var$ALLOW_STALE = Symbol('allowStale'); |
|
const $1c9e97ff3b9eceee$var$MAX_AGE = Symbol('maxAge'); |
|
const $1c9e97ff3b9eceee$var$DISPOSE = Symbol('dispose'); |
|
const $1c9e97ff3b9eceee$var$NO_DISPOSE_ON_SET = Symbol('noDisposeOnSet'); |
|
const $1c9e97ff3b9eceee$var$LRU_LIST = Symbol('lruList'); |
|
const $1c9e97ff3b9eceee$var$CACHE = Symbol('cache'); |
|
const $1c9e97ff3b9eceee$var$UPDATE_AGE_ON_GET = Symbol('updateAgeOnGet'); |
|
const $1c9e97ff3b9eceee$var$naiveLength = ()=>1 |
|
; |
|
// lruList is a yallist where the head is the youngest |
|
// item, and the tail is the oldest. the list contains the Hit |
|
// objects as the entries. |
|
// Each Hit object has a reference to its Yallist.Node. This |
|
// never changes. |
|
// |
|
// cache is a Map (or PseudoMap) that matches the keys to |
|
// the Yallist.Node object. |
|
class $1c9e97ff3b9eceee$var$LRUCache { |
|
constructor(options){ |
|
if (typeof options === 'number') options = { |
|
max: options |
|
}; |
|
if (!options) options = { |
|
}; |
|
if (options.max && (typeof options.max !== 'number' || options.max < 0)) throw new TypeError('max must be a non-negative number'); |
|
// Kind of weird to have a default max of Infinity, but oh well. |
|
const max = this[$1c9e97ff3b9eceee$var$MAX] = options.max || Infinity; |
|
const lc = options.length || $1c9e97ff3b9eceee$var$naiveLength; |
|
this[$1c9e97ff3b9eceee$var$LENGTH_CALCULATOR] = typeof lc !== 'function' ? $1c9e97ff3b9eceee$var$naiveLength : lc; |
|
this[$1c9e97ff3b9eceee$var$ALLOW_STALE] = options.stale || false; |
|
if (options.maxAge && typeof options.maxAge !== 'number') throw new TypeError('maxAge must be a number'); |
|
this[$1c9e97ff3b9eceee$var$MAX_AGE] = options.maxAge || 0; |
|
this[$1c9e97ff3b9eceee$var$DISPOSE] = options.dispose; |
|
this[$1c9e97ff3b9eceee$var$NO_DISPOSE_ON_SET] = options.noDisposeOnSet || false; |
|
this[$1c9e97ff3b9eceee$var$UPDATE_AGE_ON_GET] = options.updateAgeOnGet || false; |
|
this.reset(); |
|
} |
|
// resize the cache when the max changes. |
|
set max(mL) { |
|
if (typeof mL !== 'number' || mL < 0) throw new TypeError('max must be a non-negative number'); |
|
this[$1c9e97ff3b9eceee$var$MAX] = mL || Infinity; |
|
$1c9e97ff3b9eceee$var$trim(this); |
|
} |
|
get max() { |
|
return this[$1c9e97ff3b9eceee$var$MAX]; |
|
} |
|
set allowStale(allowStale) { |
|
this[$1c9e97ff3b9eceee$var$ALLOW_STALE] = !!allowStale; |
|
} |
|
get allowStale() { |
|
return this[$1c9e97ff3b9eceee$var$ALLOW_STALE]; |
|
} |
|
set maxAge(mA) { |
|
if (typeof mA !== 'number') throw new TypeError('maxAge must be a non-negative number'); |
|
this[$1c9e97ff3b9eceee$var$MAX_AGE] = mA; |
|
$1c9e97ff3b9eceee$var$trim(this); |
|
} |
|
get maxAge() { |
|
return this[$1c9e97ff3b9eceee$var$MAX_AGE]; |
|
} |
|
// resize the cache when the lengthCalculator changes. |
|
set lengthCalculator(lC) { |
|
if (typeof lC !== 'function') lC = $1c9e97ff3b9eceee$var$naiveLength; |
|
if (lC !== this[$1c9e97ff3b9eceee$var$LENGTH_CALCULATOR]) { |
|
this[$1c9e97ff3b9eceee$var$LENGTH_CALCULATOR] = lC; |
|
this[$1c9e97ff3b9eceee$var$LENGTH] = 0; |
|
this[$1c9e97ff3b9eceee$var$LRU_LIST].forEach((hit)=>{ |
|
hit.length = this[$1c9e97ff3b9eceee$var$LENGTH_CALCULATOR](hit.value, hit.key); |
|
this[$1c9e97ff3b9eceee$var$LENGTH] += hit.length; |
|
}); |
|
} |
|
$1c9e97ff3b9eceee$var$trim(this); |
|
} |
|
get lengthCalculator() { |
|
return this[$1c9e97ff3b9eceee$var$LENGTH_CALCULATOR]; |
|
} |
|
get length() { |
|
return this[$1c9e97ff3b9eceee$var$LENGTH]; |
|
} |
|
get itemCount() { |
|
return this[$1c9e97ff3b9eceee$var$LRU_LIST].length; |
|
} |
|
rforEach(fn, thisp) { |
|
thisp = thisp || this; |
|
for(let walker = this[$1c9e97ff3b9eceee$var$LRU_LIST].tail; walker !== null;){ |
|
const prev = walker.prev; |
|
$1c9e97ff3b9eceee$var$forEachStep(this, fn, walker, thisp); |
|
walker = prev; |
|
} |
|
} |
|
forEach(fn, thisp) { |
|
thisp = thisp || this; |
|
for(let walker = this[$1c9e97ff3b9eceee$var$LRU_LIST].head; walker !== null;){ |
|
const next = walker.next; |
|
$1c9e97ff3b9eceee$var$forEachStep(this, fn, walker, thisp); |
|
walker = next; |
|
} |
|
} |
|
keys() { |
|
return this[$1c9e97ff3b9eceee$var$LRU_LIST].toArray().map((k)=>k.key |
|
); |
|
} |
|
values() { |
|
return this[$1c9e97ff3b9eceee$var$LRU_LIST].toArray().map((k)=>k.value |
|
); |
|
} |
|
reset() { |
|
if (this[$1c9e97ff3b9eceee$var$DISPOSE] && this[$1c9e97ff3b9eceee$var$LRU_LIST] && this[$1c9e97ff3b9eceee$var$LRU_LIST].length) this[$1c9e97ff3b9eceee$var$LRU_LIST].forEach((hit)=>this[$1c9e97ff3b9eceee$var$DISPOSE](hit.key, hit.value) |
|
); |
|
this[$1c9e97ff3b9eceee$var$CACHE] = new Map() // hash of items by key |
|
; |
|
this[$1c9e97ff3b9eceee$var$LRU_LIST] = new $3d36175a98d16391$exports() // list of items in order of use recency |
|
; |
|
this[$1c9e97ff3b9eceee$var$LENGTH] = 0 // length of items in the list |
|
; |
|
} |
|
dump() { |
|
return this[$1c9e97ff3b9eceee$var$LRU_LIST].map((hit)=>$1c9e97ff3b9eceee$var$isStale(this, hit) ? false : { |
|
k: hit.key, |
|
v: hit.value, |
|
e: hit.now + (hit.maxAge || 0) |
|
} |
|
).toArray().filter((h)=>h |
|
); |
|
} |
|
dumpLru() { |
|
return this[$1c9e97ff3b9eceee$var$LRU_LIST]; |
|
} |
|
set(key, value, maxAge) { |
|
maxAge = maxAge || this[$1c9e97ff3b9eceee$var$MAX_AGE]; |
|
if (maxAge && typeof maxAge !== 'number') throw new TypeError('maxAge must be a number'); |
|
const now = maxAge ? Date.now() : 0; |
|
const len = this[$1c9e97ff3b9eceee$var$LENGTH_CALCULATOR](value, key); |
|
if (this[$1c9e97ff3b9eceee$var$CACHE].has(key)) { |
|
if (len > this[$1c9e97ff3b9eceee$var$MAX]) { |
|
$1c9e97ff3b9eceee$var$del(this, this[$1c9e97ff3b9eceee$var$CACHE].get(key)); |
|
return false; |
|
} |
|
const node = this[$1c9e97ff3b9eceee$var$CACHE].get(key); |
|
const item = node.value; |
|
// dispose of the old one before overwriting |
|
// split out into 2 ifs for better coverage tracking |
|
if (this[$1c9e97ff3b9eceee$var$DISPOSE]) { |
|
if (!this[$1c9e97ff3b9eceee$var$NO_DISPOSE_ON_SET]) this[$1c9e97ff3b9eceee$var$DISPOSE](key, item.value); |
|
} |
|
item.now = now; |
|
item.maxAge = maxAge; |
|
item.value = value; |
|
this[$1c9e97ff3b9eceee$var$LENGTH] += len - item.length; |
|
item.length = len; |
|
this.get(key); |
|
$1c9e97ff3b9eceee$var$trim(this); |
|
return true; |
|
} |
|
const hit = new $1c9e97ff3b9eceee$var$Entry(key, value, len, now, maxAge); |
|
// oversized objects fall out of cache automatically. |
|
if (hit.length > this[$1c9e97ff3b9eceee$var$MAX]) { |
|
if (this[$1c9e97ff3b9eceee$var$DISPOSE]) this[$1c9e97ff3b9eceee$var$DISPOSE](key, value); |
|
return false; |
|
} |
|
this[$1c9e97ff3b9eceee$var$LENGTH] += hit.length; |
|
this[$1c9e97ff3b9eceee$var$LRU_LIST].unshift(hit); |
|
this[$1c9e97ff3b9eceee$var$CACHE].set(key, this[$1c9e97ff3b9eceee$var$LRU_LIST].head); |
|
$1c9e97ff3b9eceee$var$trim(this); |
|
return true; |
|
} |
|
has(key) { |
|
if (!this[$1c9e97ff3b9eceee$var$CACHE].has(key)) return false; |
|
const hit = this[$1c9e97ff3b9eceee$var$CACHE].get(key).value; |
|
return !$1c9e97ff3b9eceee$var$isStale(this, hit); |
|
} |
|
get(key) { |
|
return $1c9e97ff3b9eceee$var$get(this, key, true); |
|
} |
|
peek(key) { |
|
return $1c9e97ff3b9eceee$var$get(this, key, false); |
|
} |
|
pop() { |
|
const node = this[$1c9e97ff3b9eceee$var$LRU_LIST].tail; |
|
if (!node) return null; |
|
$1c9e97ff3b9eceee$var$del(this, node); |
|
return node.value; |
|
} |
|
del(key) { |
|
$1c9e97ff3b9eceee$var$del(this, this[$1c9e97ff3b9eceee$var$CACHE].get(key)); |
|
} |
|
load(arr) { |
|
// reset the cache |
|
this.reset(); |
|
const now = Date.now(); |
|
// A previous serialized cache has the most recent items first |
|
for(let l = arr.length - 1; l >= 0; l--){ |
|
const hit = arr[l]; |
|
const expiresAt = hit.e || 0; |
|
if (expiresAt === 0) // the item was created without expiration in a non aged cache |
|
this.set(hit.k, hit.v); |
|
else { |
|
const maxAge = expiresAt - now; |
|
// dont add already expired items |
|
if (maxAge > 0) this.set(hit.k, hit.v, maxAge); |
|
} |
|
} |
|
} |
|
prune() { |
|
this[$1c9e97ff3b9eceee$var$CACHE].forEach((value, key)=>$1c9e97ff3b9eceee$var$get(this, key, false) |
|
); |
|
} |
|
} |
|
const $1c9e97ff3b9eceee$var$get = (self, key, doUse)=>{ |
|
const node = self[$1c9e97ff3b9eceee$var$CACHE].get(key); |
|
if (node) { |
|
const hit = node.value; |
|
if ($1c9e97ff3b9eceee$var$isStale(self, hit)) { |
|
$1c9e97ff3b9eceee$var$del(self, node); |
|
if (!self[$1c9e97ff3b9eceee$var$ALLOW_STALE]) return undefined; |
|
} else if (doUse) { |
|
if (self[$1c9e97ff3b9eceee$var$UPDATE_AGE_ON_GET]) node.value.now = Date.now(); |
|
self[$1c9e97ff3b9eceee$var$LRU_LIST].unshiftNode(node); |
|
} |
|
return hit.value; |
|
} |
|
}; |
|
const $1c9e97ff3b9eceee$var$isStale = (self, hit)=>{ |
|
if (!hit || !hit.maxAge && !self[$1c9e97ff3b9eceee$var$MAX_AGE]) return false; |
|
const diff = Date.now() - hit.now; |
|
return hit.maxAge ? diff > hit.maxAge : self[$1c9e97ff3b9eceee$var$MAX_AGE] && diff > self[$1c9e97ff3b9eceee$var$MAX_AGE]; |
|
}; |
|
const $1c9e97ff3b9eceee$var$trim = (self)=>{ |
|
if (self[$1c9e97ff3b9eceee$var$LENGTH] > self[$1c9e97ff3b9eceee$var$MAX]) for(let walker = self[$1c9e97ff3b9eceee$var$LRU_LIST].tail; self[$1c9e97ff3b9eceee$var$LENGTH] > self[$1c9e97ff3b9eceee$var$MAX] && walker !== null;){ |
|
// We know that we're about to delete this one, and also |
|
// what the next least recently used key will be, so just |
|
// go ahead and set it now. |
|
const prev = walker.prev; |
|
$1c9e97ff3b9eceee$var$del(self, walker); |
|
walker = prev; |
|
} |
|
}; |
|
const $1c9e97ff3b9eceee$var$del = (self, node)=>{ |
|
if (node) { |
|
const hit = node.value; |
|
if (self[$1c9e97ff3b9eceee$var$DISPOSE]) self[$1c9e97ff3b9eceee$var$DISPOSE](hit.key, hit.value); |
|
self[$1c9e97ff3b9eceee$var$LENGTH] -= hit.length; |
|
self[$1c9e97ff3b9eceee$var$CACHE].delete(hit.key); |
|
self[$1c9e97ff3b9eceee$var$LRU_LIST].removeNode(node); |
|
} |
|
}; |
|
class $1c9e97ff3b9eceee$var$Entry { |
|
constructor(key, value, length, now, maxAge){ |
|
this.key = key; |
|
this.value = value; |
|
this.length = length; |
|
this.now = now; |
|
this.maxAge = maxAge || 0; |
|
} |
|
} |
|
const $1c9e97ff3b9eceee$var$forEachStep = (self, fn, node, thisp)=>{ |
|
let hit = node.value; |
|
if ($1c9e97ff3b9eceee$var$isStale(self, hit)) { |
|
$1c9e97ff3b9eceee$var$del(self, node); |
|
if (!self[$1c9e97ff3b9eceee$var$ALLOW_STALE]) hit = undefined; |
|
} |
|
if (hit) fn.call(thisp, hit.value, hit.key, self); |
|
}; |
|
$1c9e97ff3b9eceee$exports = $1c9e97ff3b9eceee$var$LRUCache; |
|
|
|
|
|
const $10671d0be444e08b$var$configCache = new (/*@__PURE__*/$parcel$interopDefault($1c9e97ff3b9eceee$exports))({ |
|
max: 500 |
|
}); |
|
const $10671d0be444e08b$var$resolveCache = new Map(); |
|
function $10671d0be444e08b$export$7eca4ea16d4c8343(fs, filepath, filenames, projectRoot) { |
|
// Cache the result of resolving config for this directory. |
|
// This is automatically invalidated at the end of the current build. |
|
let key = ($parcel$interopDefault($8C1kk$path)).dirname(filepath) + filenames.join(','); |
|
let cached = $10671d0be444e08b$var$resolveCache.get(key); |
|
if (cached !== undefined) return Promise.resolve(cached); |
|
let resolved = fs.findAncestorFile(filenames, ($parcel$interopDefault($8C1kk$path)).dirname(filepath), projectRoot); |
|
$10671d0be444e08b$var$resolveCache.set(key, resolved); |
|
return Promise.resolve(resolved); |
|
} |
|
function $10671d0be444e08b$export$d175e66e9fcd7b75(fs, filepath, filenames, projectRoot) { |
|
return fs.findAncestorFile(filenames, ($parcel$interopDefault($8C1kk$path)).dirname(filepath), projectRoot); |
|
} |
|
async function $10671d0be444e08b$export$c1a4367d4847eb06(fs, filepath, filenames, projectRoot, opts) { |
|
var ref; |
|
let parse = (ref = opts === null || opts === void 0 ? void 0 : opts.parse) !== null && ref !== void 0 ? ref : true; |
|
let configFile = await $10671d0be444e08b$export$7eca4ea16d4c8343(fs, filepath, filenames, projectRoot); |
|
if (configFile) { |
|
let cachedOutput = $10671d0be444e08b$var$configCache.get(String(parse) + configFile); |
|
if (cachedOutput) return cachedOutput; |
|
try { |
|
let extname = ($parcel$interopDefault($8C1kk$path)).extname(configFile).slice(1); |
|
if (extname === 'js') { |
|
let output = { |
|
// $FlowFixMe |
|
config: (/*@__PURE__*/$parcel$interopDefault($284aeb9e515b63c0$exports))(require(configFile)), |
|
files: [ |
|
{ |
|
filePath: configFile |
|
} |
|
] |
|
}; |
|
$10671d0be444e08b$var$configCache.set(configFile, output); |
|
return output; |
|
} |
|
let configContent = await fs.readFile(configFile, 'utf8'); |
|
let config; |
|
if (parse === false) config = configContent; |
|
else { |
|
var ref1; |
|
let parse = (ref1 = opts === null || opts === void 0 ? void 0 : opts.parser) !== null && ref1 !== void 0 ? ref1 : $10671d0be444e08b$var$getParser(extname); |
|
try { |
|
config = parse(configContent); |
|
} catch (e) { |
|
if (extname !== '' && extname !== 'json') throw e; |
|
let pos = { |
|
line: e.lineNumber, |
|
column: e.columnNumber |
|
}; |
|
throw new ($parcel$interopDefault($8C1kk$parceldiagnostic))({ |
|
diagnostic: { |
|
message: `Failed to parse ${($parcel$interopDefault($8C1kk$path)).basename(configFile)}`, |
|
origin: '@parcel/utils', |
|
codeFrames: [ |
|
{ |
|
language: 'json5', |
|
filePath: configFile, |
|
code: configContent, |
|
codeHighlights: [ |
|
{ |
|
start: pos, |
|
end: pos, |
|
message: e.message |
|
} |
|
] |
|
} |
|
] |
|
} |
|
}); |
|
} |
|
} |
|
let output = { |
|
config: config, |
|
files: [ |
|
{ |
|
filePath: configFile |
|
} |
|
] |
|
}; |
|
$10671d0be444e08b$var$configCache.set(String(parse) + configFile, output); |
|
return output; |
|
} catch (err) { |
|
if (err.code === 'MODULE_NOT_FOUND' || err.code === 'ENOENT') return null; |
|
throw err; |
|
} |
|
} |
|
return null; |
|
} |
|
$10671d0be444e08b$export$c1a4367d4847eb06.clear = ()=>{ |
|
$10671d0be444e08b$var$configCache.reset(); |
|
$10671d0be444e08b$var$resolveCache.clear(); |
|
}; |
|
function $10671d0be444e08b$var$getParser(extname) { |
|
switch(extname){ |
|
case 'toml': |
|
return $830470103c08108e$export$98e6a39c04603d36; |
|
case 'json': |
|
default: |
|
return $5dc3ee1f90b35876$export$2e2bcd8739ae039.parse; |
|
} |
|
} |
|
|
|
|
|
async function $6aebdac47db0459e$export$6643be4f4e63e994(fs, moduleName, dir) { |
|
let potentialModules = []; |
|
let root = ($parcel$interopDefault($8C1kk$path)).parse(dir).root; |
|
let isOrganisationModule = moduleName.startsWith('@'); |
|
while(dir !== root){ |
|
// Skip node_modules directories |
|
if (($parcel$interopDefault($8C1kk$path)).basename(dir) === 'node_modules') dir = ($parcel$interopDefault($8C1kk$path)).dirname(dir); |
|
try { |
|
let modulesDir = ($parcel$interopDefault($8C1kk$path)).join(dir, 'node_modules'); |
|
let stats = await fs.stat(modulesDir); |
|
if (stats.isDirectory()) { |
|
let dirContent = (await fs.readdir(modulesDir)).sort(); // Filter out the modules that interest us |
|
let modules = dirContent.filter((i)=>isOrganisationModule ? i.startsWith('@') : !i.startsWith('@') |
|
); // If it's an organisation module, loop through all the modules of that organisation |
|
if (isOrganisationModule) await Promise.all(modules.map(async (item)=>{ |
|
let orgDirPath = ($parcel$interopDefault($8C1kk$path)).join(modulesDir, item); |
|
let orgDirContent = (await fs.readdir(orgDirPath)).sort(); // Add all org packages |
|
potentialModules.push(...orgDirContent.map((i)=>`${item}/${i}` |
|
)); |
|
})); |
|
} |
|
} catch (err) { |
|
} // Move up a directory |
|
dir = ($parcel$interopDefault($8C1kk$path)).dirname(dir); |
|
} |
|
return $4ca1027d34905147$export$2115c2c0a84eef61(potentialModules.sort(), moduleName).slice(0, 2); |
|
} |
|
async function $6aebdac47db0459e$var$findAllFilesUp({ fs: fs , dir: dir , root: root , basedir: basedir , maxlength: maxlength , collected: collected , leadingDotSlash: leadingDotSlash = true , includeDirectories: includeDirectories = true }) { |
|
let dirContent = (await fs.readdir(dir)).sort(); |
|
return Promise.all(dirContent.map(async (item)=>{ |
|
let fullPath = ($parcel$interopDefault($8C1kk$path)).join(dir, item); |
|
let relativeFilePath = $3dff16cfd200ff25$export$7413eea5ad243d4(basedir, fullPath, leadingDotSlash); |
|
if (relativeFilePath.length < maxlength) { |
|
let stats = await fs.stat(fullPath); |
|
let isDir = stats.isDirectory(); |
|
if (isDir && includeDirectories || stats.isFile()) collected.push(relativeFilePath); |
|
// If it's a directory, run over each item within said directory... |
|
if (isDir) return $6aebdac47db0459e$var$findAllFilesUp({ |
|
fs: fs, |
|
dir: fullPath, |
|
root: root, |
|
basedir: basedir, |
|
maxlength: maxlength, |
|
collected: collected |
|
}); |
|
} |
|
})); |
|
} |
|
async function $6aebdac47db0459e$export$4eeb1b3271a29661(fs, fileSpecifier, dir, projectRoot, leadingDotSlash = true, includeDirectories = true, includeExtension = false) { |
|
let potentialFiles = []; // Find our root, we won't recommend files above the package root as that's bad practise |
|
let pkg = await $10671d0be444e08b$export$7eca4ea16d4c8343(fs, ($parcel$interopDefault($8C1kk$path)).join(dir, 'index'), [ |
|
'package.json' |
|
], projectRoot); |
|
let pkgRoot = pkg ? ($parcel$interopDefault($8C1kk$path)).dirname(pkg) : projectRoot; |
|
await $6aebdac47db0459e$var$findAllFilesUp({ |
|
fs: fs, |
|
dir: pkgRoot, |
|
root: pkgRoot, |
|
basedir: dir, |
|
maxlength: fileSpecifier.length + 10, |
|
collected: potentialFiles, |
|
leadingDotSlash: leadingDotSlash, |
|
includeDirectories: includeDirectories |
|
}); |
|
if (($parcel$interopDefault($8C1kk$path)).extname(fileSpecifier) === '' && !includeExtension) potentialFiles = potentialFiles.map((p)=>{ |
|
let ext = ($parcel$interopDefault($8C1kk$path)).extname(p); |
|
return ext.length > 0 ? p.slice(0, -ext.length) : p; |
|
}); |
|
return $4ca1027d34905147$export$2115c2c0a84eef61(potentialFiles, fileSpecifier).slice(0, 2); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function $a3de5fd908122828$export$e234f0a8b913b7b9(blob) { |
|
if (blob instanceof $8C1kk$stream.Readable) return $29bb96d8a6524ff0$export$f109d1c79a5ae5a1(blob); |
|
else if (blob instanceof $8C1kk$buffer.Buffer) return Promise.resolve($8C1kk$buffer.Buffer.from(blob)); |
|
else return Promise.resolve($8C1kk$buffer.Buffer.from(blob, 'utf8')); |
|
} |
|
async function $a3de5fd908122828$export$c6adc95df13c8b9e(blob) { |
|
if (blob instanceof $8C1kk$stream.Readable) return (await $29bb96d8a6524ff0$export$f109d1c79a5ae5a1(blob)).toString(); |
|
else if (blob instanceof $8C1kk$buffer.Buffer) return blob.toString(); |
|
else return blob; |
|
} |
|
|
|
|
|
function $9631335a11debdd4$export$7a5d5c156e7dc406(array) { |
|
return [ |
|
...new Set(array) |
|
]; |
|
} |
|
function $9631335a11debdd4$export$61559eb31990eff6(obj) { |
|
return Object.entries(obj).sort(([keyA], [keyB])=>keyA.localeCompare(keyB) |
|
); |
|
} |
|
function $9631335a11debdd4$export$1a9b883158ac407c(object) { |
|
let sortedEntries = $9631335a11debdd4$export$61559eb31990eff6(object); |
|
for(let i = 0; i < sortedEntries.length; i++)sortedEntries[i][1] = $9631335a11debdd4$var$sortEntry(sortedEntries[i][1]); |
|
return sortedEntries; |
|
} |
|
function $9631335a11debdd4$var$sortEntry(entry) { |
|
if (Array.isArray(entry)) return entry.map($9631335a11debdd4$var$sortEntry); |
|
if (typeof entry === 'object' && entry != null) return $9631335a11debdd4$export$1a9b883158ac407c(entry); |
|
return entry; |
|
} |
|
function $9631335a11debdd4$export$8bd517cc5b3722f7(a, b) { |
|
let difference = new Set(); |
|
for (let e of a)if (!b.has(e)) difference.add(e); |
|
return difference; |
|
} |
|
function $9631335a11debdd4$export$9404cfefeb010e68(a, b) { |
|
for (let entry of a)if (!b.has(entry)) a.delete(entry); |
|
} |
|
function $9631335a11debdd4$export$667066422fa0af46(a, b) { |
|
return new Set([ |
|
...a, |
|
...b |
|
]); |
|
} |
|
|
|
|
|
|
|
class $5783bf7916ff59db$export$674cd7dcb504ac5c extends Map { |
|
constructor(getDefault, entries){ |
|
super(entries); |
|
this._getDefault = getDefault; |
|
} |
|
get(key) { |
|
let ret; |
|
if (this.has(key)) ret = super.get(key); |
|
else { |
|
ret = this._getDefault(key); |
|
this.set(key, ret); |
|
} // $FlowFixMe |
|
return ret; |
|
} |
|
} // Duplicated from DefaultMap implementation for Flow |
|
class $5783bf7916ff59db$export$4924f7ffab2ae440 extends WeakMap { |
|
constructor(getDefault, entries){ |
|
super(entries); |
|
this._getDefault = getDefault; |
|
} |
|
get(key) { |
|
let ret; |
|
if (this.has(key)) ret = super.get(key); |
|
else { |
|
ret = this._getDefault(key); |
|
this.set(key, ret); |
|
} // $FlowFixMe |
|
return ret; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
function $4b14026b40817fca$export$8a9ede1a78d6a1fe(stream) { |
|
let hash = new $8C1kk$parcelhash.Hash(); |
|
return new Promise((resolve, reject)=>{ |
|
stream.on('error', (err)=>{ |
|
reject(err); |
|
}); |
|
stream.on('data', (chunk)=>{ |
|
hash.writeBuffer(chunk); |
|
}).on('end', function() { |
|
resolve(hash.finish()); |
|
}).on('error', (err)=>{ |
|
reject(err); |
|
}); |
|
}); |
|
} |
|
function $4b14026b40817fca$export$3477f9615e12f61d(obj) { |
|
return $8C1kk$parcelhash.hashString(JSON.stringify($9631335a11debdd4$export$1a9b883158ac407c(obj))); |
|
} |
|
function $4b14026b40817fca$export$42462553d605d8cd(fs, filePath) { |
|
return $4b14026b40817fca$export$8a9ede1a78d6a1fe(fs.createReadStream(filePath)); |
|
} |
|
|
|
|
|
let $1c93db5abaa33eaa$export$8b1c306fed4227bf; // $FlowFixMe[prop-missing] |
|
if (process.browser) { |
|
$1c93db5abaa33eaa$export$8b1c306fed4227bf = ArrayBuffer; // Safari has removed the constructor |
|
if (typeof SharedArrayBuffer !== 'undefined') { |
|
let channel = new MessageChannel(); |
|
try { |
|
// Firefox might throw when sending the Buffer over a MessagePort |
|
channel.port1.postMessage(new SharedArrayBuffer(0)); |
|
$1c93db5abaa33eaa$export$8b1c306fed4227bf = SharedArrayBuffer; |
|
} catch (_) { |
|
} |
|
channel.port1.close(); |
|
channel.port2.close(); |
|
} |
|
} else $1c93db5abaa33eaa$export$8b1c306fed4227bf = SharedArrayBuffer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function $0e887a49fdd81cad$export$3b1983e9896f988b(options) { |
|
let server; |
|
if (!options.https) server = ($parcel$interopDefault($8C1kk$http)).createServer(options.listener); |
|
else if (options.https === true) { |
|
let { cert: cert , key: key } = await $c6cbdbdbaf0fafc1$export$2e2bcd8739ae039(options.outputFS, options.cacheDir, options.host); |
|
server = ($parcel$interopDefault($8C1kk$https)).createServer({ |
|
cert: cert, |
|
key: key |
|
}, options.listener); |
|
} else { |
|
let { cert: cert , key: key } = await $186980c178984fd2$export$2e2bcd8739ae039(options.inputFS, options.https); |
|
server = ($parcel$interopDefault($8C1kk$https)).createServer({ |
|
cert: cert, |
|
key: key |
|
}, options.listener); |
|
} // HTTPServer#close only stops accepting new connections, and does not close existing ones. |
|
// Before closing, destroy any active connections through their sockets. Additionally, remove sockets when they close: |
|
// https://stackoverflow.com/questions/18874689/force-close-all-connections-in-a-node-js-http-server |
|
// https://stackoverflow.com/questions/14626636/how-do-i-shutdown-a-node-js-https-server-immediately/14636625#14636625 |
|
let sockets = new Set(); |
|
server.on('connection', (socket)=>{ |
|
(/*@__PURE__*/$parcel$interopDefault($812806c6461f2963$exports))(sockets).add(socket); |
|
socket.on('close', ()=>{ |
|
(/*@__PURE__*/$parcel$interopDefault($812806c6461f2963$exports))(sockets).delete(socket); |
|
}); |
|
}); |
|
return { |
|
server: server, |
|
stop () { |
|
return new Promise((resolve, reject)=>{ |
|
for (let socket of (/*@__PURE__*/$parcel$interopDefault($812806c6461f2963$exports))(sockets))socket.destroy(); |
|
sockets = new Set(); |
|
server.close((err)=>{ |
|
if (err != null) { |
|
reject(err); |
|
return; |
|
} |
|
resolve(); |
|
}); |
|
}); |
|
} |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function $bc66accb63b05e9a$export$d0d0105f44defc19({ bundle: bundle , bundleGraph: bundleGraph , contents: contents , map: map , relative: relative = true }) { |
|
let replacements = new Map(); |
|
let urlDependencies = []; |
|
bundle.traverse((node)=>{ |
|
if (node.type === 'dependency' && node.value.specifierType === 'url') urlDependencies.push(node.value); |
|
}); |
|
for (let dependency of urlDependencies){ |
|
var ref; |
|
if (dependency.specifierType !== 'url') continue; |
|
var ref1; |
|
let placeholder = (ref1 = (ref = dependency.meta) === null || ref === void 0 ? void 0 : ref.placeholder) !== null && ref1 !== void 0 ? ref1 : dependency.id; |
|
($parcel$interopDefault($8C1kk$assert))(typeof placeholder === 'string'); |
|
let resolved = bundleGraph.getReferencedBundle(dependency, bundle); |
|
if (resolved == null) { |
|
replacements.set(placeholder, { |
|
from: placeholder, |
|
to: dependency.specifier |
|
}); |
|
continue; |
|
} |
|
if (resolved.bundleBehavior === 'inline') continue; |
|
replacements.set(placeholder, $bc66accb63b05e9a$export$a22ef0cbdf8abc95({ |
|
dependency: dependency, |
|
fromBundle: bundle, |
|
toBundle: resolved, |
|
relative: relative |
|
})); |
|
} |
|
return $bc66accb63b05e9a$var$performReplacement(replacements, contents, map); |
|
} |
|
async function $bc66accb63b05e9a$export$f074a8f9bef628fd({ bundle: bundle , bundleGraph: bundleGraph , contents: contents , map: map , getInlineReplacement: getInlineReplacement , getInlineBundleContents: getInlineBundleContents }) { |
|
let replacements = new Map(); |
|
let dependencies = []; |
|
bundle.traverse((node)=>{ |
|
if (node.type === 'dependency') dependencies.push(node.value); |
|
}); |
|
for (let dependency of dependencies){ |
|
let entryBundle = bundleGraph.getReferencedBundle(dependency, bundle); |
|
if ((entryBundle === null || entryBundle === void 0 ? void 0 : entryBundle.bundleBehavior) !== 'inline') continue; |
|
let packagedBundle = await getInlineBundleContents(entryBundle, bundleGraph); |
|
let packagedContents = (packagedBundle.contents instanceof $8C1kk$stream.Readable ? await $29bb96d8a6524ff0$export$f109d1c79a5ae5a1(packagedBundle.contents) : packagedBundle.contents).toString(); |
|
let inlineType = (/*@__PURE__*/$parcel$interopDefault($812806c6461f2963$exports))(entryBundle.getMainEntry()).meta.inlineType; |
|
if (inlineType == null || inlineType === 'string') { |
|
var ref; |
|
var ref2; |
|
let placeholder = (ref2 = (ref = dependency.meta) === null || ref === void 0 ? void 0 : ref.placeholder) !== null && ref2 !== void 0 ? ref2 : dependency.id; |
|
($parcel$interopDefault($8C1kk$assert))(typeof placeholder === 'string'); |
|
replacements.set(placeholder, getInlineReplacement(dependency, inlineType, packagedContents)); |
|
} |
|
} |
|
return $bc66accb63b05e9a$var$performReplacement(replacements, contents, map); |
|
} |
|
function $bc66accb63b05e9a$export$a22ef0cbdf8abc95({ dependency: dependency , fromBundle: fromBundle , toBundle: toBundle , relative: relative }) { |
|
var ref; |
|
let to; |
|
let orig = ($parcel$interopDefault($8C1kk$url)).parse(dependency.specifier); |
|
if (relative) { |
|
to = ($parcel$interopDefault($8C1kk$url)).format({ |
|
pathname: $76ed5e95485fb544$export$402b5a120b1183b3(fromBundle, toBundle, { |
|
leadingDotSlash: false |
|
}), |
|
hash: orig.hash |
|
}); // If the resulting path includes a colon character and doesn't start with a ./ or ../ |
|
// we need to add one so that the first part before the colon isn't parsed as a URL protocol. |
|
if (to.includes(':') && !to.startsWith('./') && !to.startsWith('../')) to = './' + to; |
|
} else to = $dfabc3743c08d51c$export$2e2bcd8739ae039(toBundle.target.publicUrl, ($parcel$interopDefault($8C1kk$url)).format({ |
|
pathname: (/*@__PURE__*/$parcel$interopDefault($812806c6461f2963$exports))(toBundle.name), |
|
hash: orig.hash |
|
})); |
|
var ref3; |
|
let placeholder = (ref3 = (ref = dependency.meta) === null || ref === void 0 ? void 0 : ref.placeholder) !== null && ref3 !== void 0 ? ref3 : dependency.id; |
|
($parcel$interopDefault($8C1kk$assert))(typeof placeholder === 'string'); |
|
return { |
|
from: placeholder, |
|
to: to |
|
}; |
|
} |
|
function $bc66accb63b05e9a$var$performReplacement(replacements, contents, map) { |
|
let finalContents = contents; |
|
for (let { from: from , to: to } of replacements.values())// Perform replacement |
|
finalContents = finalContents.split(from).join(to); |
|
return { |
|
contents: finalContents, |
|
map: // TODO: Update sourcemap with adjusted contents |
|
map |
|
}; |
|
} |
|
|
|
|
|
|
|
function $29bb96d8a6524ff0$export$457f03b1bf37ec1a(stream) { |
|
return new Promise((resolve, reject)=>{ |
|
let length = 0; |
|
stream.on('data', (chunk)=>{ |
|
length += chunk; |
|
}); |
|
stream.on('end', ()=>resolve(length) |
|
); |
|
stream.on('error', reject); |
|
}); |
|
} |
|
function $29bb96d8a6524ff0$export$dc30d0b81ccad9c7(str) { |
|
// https://stackoverflow.com/questions/12755997/how-to-create-streams-from-string-in-node-js |
|
const stream = new $8C1kk$stream.Readable(); |
|
stream.push(str); |
|
stream.push(null); |
|
return stream; |
|
} |
|
function $29bb96d8a6524ff0$export$f109d1c79a5ae5a1(stream) { |
|
return new Promise((resolve, reject)=>{ |
|
let buf = Buffer.from([]); |
|
stream.on('data', (data)=>{ |
|
buf = Buffer.concat([ |
|
buf, |
|
data |
|
]); |
|
}); |
|
stream.on('end', ()=>{ |
|
resolve(buf); |
|
}); |
|
stream.on('error', reject); |
|
}); |
|
} |
|
function $29bb96d8a6524ff0$export$5ba0b0e7e2e9ae7a(blob) { |
|
if (blob instanceof $8C1kk$stream.Readable) return blob; |
|
return $29bb96d8a6524ff0$export$dc30d0b81ccad9c7(blob); |
|
} |
|
function $29bb96d8a6524ff0$export$7ebca75e1135fcd6(promise) { |
|
const stream = new $8C1kk$stream.PassThrough(); |
|
promise.then((blob)=>{ |
|
if (blob instanceof $8C1kk$stream.Readable) blob.pipe(stream); |
|
else stream.end(blob); |
|
}); |
|
return stream; |
|
} |
|
function $29bb96d8a6524ff0$export$68f6769cfac79897(stream, fallback) { |
|
const res = new $8C1kk$stream.PassThrough(); |
|
stream.on('error', (err)=>{ |
|
if (err.code === 'ENOENT') fallback().pipe(res); |
|
else res.emit('error', err); |
|
}); |
|
stream.pipe(res); |
|
return res; |
|
} |
|
|
|
|
|
|
|
|
|
function $76ed5e95485fb544$export$402b5a120b1183b3(from, to, opts = { |
|
leadingDotSlash: true |
|
}) { |
|
let fromPath = ($parcel$interopDefault($8C1kk$path)).join(from.target.distDir, from.name); |
|
let toPath = ($parcel$interopDefault($8C1kk$path)).join(to.target.distDir, to.name); |
|
return $3dff16cfd200ff25$export$7413eea5ad243d4(($parcel$interopDefault($8C1kk$path)).dirname(fromPath), toPath, opts.leadingDotSlash); |
|
} |
|
|
|
|
|
var $f5b89fa4b66a8af6$exports = {}; |
|
'use strict'; |
|
$f5b89fa4b66a8af6$exports = $f5b89fa4b66a8af6$var$ansiHTML; |
|
// Reference to https://github.com/sindresorhus/ansi-regex |
|
var $f5b89fa4b66a8af6$var$_regANSI = /(?:(?:\u001b\[)|\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\u001b[A-M]/; |
|
var $f5b89fa4b66a8af6$var$_defColors = { |
|
reset: [ |
|
'fff', |
|
'000' |
|
], |
|
black: '000', |
|
red: 'ff0000', |
|
green: '209805', |
|
yellow: 'e8bf03', |
|
blue: '0000ff', |
|
magenta: 'ff00ff', |
|
cyan: '00ffee', |
|
lightgrey: 'f0f0f0', |
|
darkgrey: '888' |
|
}; |
|
var $f5b89fa4b66a8af6$var$_styles = { |
|
30: 'black', |
|
31: 'red', |
|
32: 'green', |
|
33: 'yellow', |
|
34: 'blue', |
|
35: 'magenta', |
|
36: 'cyan', |
|
37: 'lightgrey' |
|
}; |
|
var $f5b89fa4b66a8af6$var$_openTags = { |
|
'1': 'font-weight:bold', |
|
'2': 'opacity:0.5', |
|
'3': '<i>', |
|
'4': '<u>', |
|
'8': 'display:none', |
|
'9': '<del>' // delete |
|
}; |
|
var $f5b89fa4b66a8af6$var$_closeTags = { |
|
'23': '</i>', |
|
'24': '</u>', |
|
'29': '</del>' // reset delete |
|
}; |
|
[ |
|
0, |
|
21, |
|
22, |
|
27, |
|
28, |
|
39, |
|
49 |
|
].forEach(function(n) { |
|
$f5b89fa4b66a8af6$var$_closeTags[n] = '</span>'; |
|
}); |
|
/** |
|
* Converts text with ANSI color codes to HTML markup. |
|
* @param {String} text |
|
* @returns {*} |
|
*/ function $f5b89fa4b66a8af6$var$ansiHTML(text) { |
|
// Returns the text if the string has no ANSI escape code. |
|
if (!$f5b89fa4b66a8af6$var$_regANSI.test(text)) return text; |
|
// Cache opened sequence. |
|
var ansiCodes = []; |
|
// Replace with markup. |
|
var ret = text.replace(/\033\[(\d+)m/g, function(match, seq) { |
|
var ot = $f5b89fa4b66a8af6$var$_openTags[seq]; |
|
if (ot) { |
|
// If current sequence has been opened, close it. |
|
if (!!~ansiCodes.indexOf(seq)) { |
|
ansiCodes.pop(); |
|
return '</span>'; |
|
} |
|
// Open tag. |
|
ansiCodes.push(seq); |
|
return ot[0] === '<' ? ot : '<span style="' + ot + ';">'; |
|
} |
|
var ct = $f5b89fa4b66a8af6$var$_closeTags[seq]; |
|
if (ct) { |
|
// Pop sequence |
|
ansiCodes.pop(); |
|
return ct; |
|
} |
|
return ''; |
|
}); |
|
// Make sure tags are closed. |
|
var l = ansiCodes.length; |
|
l > 0 && (ret += Array(l + 1).join('</span>')); |
|
return ret; |
|
} |
|
/** |
|
* Customize colors. |
|
* @param {Object} colors reference to _defColors |
|
*/ $f5b89fa4b66a8af6$var$ansiHTML.setColors = function(colors) { |
|
if (typeof colors !== 'object') throw new Error('`colors` parameter must be an Object.'); |
|
var _finalColors = { |
|
}; |
|
for(var key in $f5b89fa4b66a8af6$var$_defColors){ |
|
var hex = colors.hasOwnProperty(key) ? colors[key] : null; |
|
if (!hex) { |
|
_finalColors[key] = $f5b89fa4b66a8af6$var$_defColors[key]; |
|
continue; |
|
} |
|
if ('reset' === key) { |
|
if (typeof hex === 'string') hex = [ |
|
hex |
|
]; |
|
if (!Array.isArray(hex) || hex.length === 0 || hex.some(function(h) { |
|
return typeof h !== 'string'; |
|
})) throw new Error('The value of `' + key + '` property must be an Array and each item could only be a hex string, e.g.: FF0000'); |
|
var defHexColor = $f5b89fa4b66a8af6$var$_defColors[key]; |
|
if (!hex[0]) hex[0] = defHexColor[0]; |
|
if (hex.length === 1 || !hex[1]) { |
|
hex = [ |
|
hex[0] |
|
]; |
|
hex.push(defHexColor[1]); |
|
} |
|
hex = hex.slice(0, 2); |
|
} else if (typeof hex !== 'string') throw new Error('The value of `' + key + '` property must be a hex string, e.g.: FF0000'); |
|
_finalColors[key] = hex; |
|
} |
|
$f5b89fa4b66a8af6$var$_setTags(_finalColors); |
|
}; |
|
/** |
|
* Reset colors. |
|
*/ $f5b89fa4b66a8af6$var$ansiHTML.reset = function() { |
|
$f5b89fa4b66a8af6$var$_setTags($f5b89fa4b66a8af6$var$_defColors); |
|
}; |
|
/** |
|
* Expose tags, including open and close. |
|
* @type {Object} |
|
*/ $f5b89fa4b66a8af6$var$ansiHTML.tags = { |
|
}; |
|
if (Object.defineProperty) { |
|
Object.defineProperty($f5b89fa4b66a8af6$var$ansiHTML.tags, 'open', { |
|
get: function() { |
|
return $f5b89fa4b66a8af6$var$_openTags; |
|
} |
|
}); |
|
Object.defineProperty($f5b89fa4b66a8af6$var$ansiHTML.tags, 'close', { |
|
get: function() { |
|
return $f5b89fa4b66a8af6$var$_closeTags; |
|
} |
|
}); |
|
} else { |
|
$f5b89fa4b66a8af6$var$ansiHTML.tags.open = $f5b89fa4b66a8af6$var$_openTags; |
|
$f5b89fa4b66a8af6$var$ansiHTML.tags.close = $f5b89fa4b66a8af6$var$_closeTags; |
|
} |
|
function $f5b89fa4b66a8af6$var$_setTags(colors) { |
|
// reset all |
|
$f5b89fa4b66a8af6$var$_openTags['0'] = 'font-weight:normal;opacity:1;color:#' + colors.reset[0] + ';background:#' + colors.reset[1]; |
|
// inverse |
|
$f5b89fa4b66a8af6$var$_openTags['7'] = 'color:#' + colors.reset[1] + ';background:#' + colors.reset[0]; |
|
// dark grey |
|
$f5b89fa4b66a8af6$var$_openTags['90'] = 'color:#' + colors.darkgrey; |
|
for(var code in $f5b89fa4b66a8af6$var$_styles){ |
|
var color = $f5b89fa4b66a8af6$var$_styles[code]; |
|
var oriColor = colors[color] || '000'; |
|
$f5b89fa4b66a8af6$var$_openTags[code] = 'color:#' + oriColor; |
|
code = parseInt(code); |
|
$f5b89fa4b66a8af6$var$_openTags[(code + 10).toString()] = 'background:#' + oriColor; |
|
} |
|
} |
|
$f5b89fa4b66a8af6$var$ansiHTML.reset(); |
|
|
|
|
|
// Based on _.escape https://github.com/lodash/lodash/blob/master/escape.js |
|
const $557d7b477cbdc368$var$reUnescapedHtml = /[&<>"']/g; |
|
const $557d7b477cbdc368$var$reHasUnescapedHtml = RegExp($557d7b477cbdc368$var$reUnescapedHtml.source); |
|
const $557d7b477cbdc368$var$htmlEscapes = { |
|
'&': '&', |
|
'<': '<', |
|
'>': '>', |
|
'"': '"', |
|
"'": ''' |
|
}; |
|
function $557d7b477cbdc368$export$5dd27816c66fb702(s) { |
|
if ($557d7b477cbdc368$var$reHasUnescapedHtml.test(s)) return s.replace($557d7b477cbdc368$var$reUnescapedHtml, (c)=>$557d7b477cbdc368$var$htmlEscapes[c] |
|
); |
|
return s; |
|
} |
|
|
|
|
|
function $7ea2b0152b726098$export$565d0ff71645da31(ansi) { |
|
return (/*@__PURE__*/$parcel$interopDefault($f5b89fa4b66a8af6$exports))($557d7b477cbdc368$export$5dd27816c66fb702(ansi)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
const $46fc74961fdcfe31$export$db8833b274702782 = /(?:\/\*|\/\/)\s*[@#]\s*sourceMappingURL\s*=\s*([^\s*]+)(?:\s*\*\/)?\s*$/; |
|
const $46fc74961fdcfe31$var$DATA_URL_RE = /^data:[^;]+(?:;charset=[^;]+)?;base64,(.*)/; |
|
const $46fc74961fdcfe31$export$4b206fdd01e58041 = new Set([ |
|
'css', |
|
'es', |
|
'es6', |
|
'js', |
|
'jsx', |
|
'mjs', |
|
'ts', |
|
'tsx' |
|
]); |
|
function $46fc74961fdcfe31$export$ff36203a2e5cc203(contents) { |
|
return contents.match($46fc74961fdcfe31$export$db8833b274702782); |
|
} |
|
async function $46fc74961fdcfe31$export$527a92fa675f5e93(fs, filename, contents) { |
|
let match = $46fc74961fdcfe31$export$ff36203a2e5cc203(contents); |
|
if (match) { |
|
let url = match[1].trim(); |
|
let dataURLMatch = url.match($46fc74961fdcfe31$var$DATA_URL_RE); |
|
let mapFilePath; |
|
if (dataURLMatch) mapFilePath = filename; |
|
else { |
|
mapFilePath = url.replace(/^file:\/\//, ''); |
|
mapFilePath = $3dff16cfd200ff25$export$e434c7255acda994(mapFilePath) ? mapFilePath : ($parcel$interopDefault($8C1kk$path)).join(($parcel$interopDefault($8C1kk$path)).dirname(filename), mapFilePath); |
|
} |
|
return { |
|
url: url, |
|
filename: mapFilePath, |
|
map: JSON.parse(dataURLMatch ? Buffer.from(dataURLMatch[1], 'base64').toString() : await fs.readFile(mapFilePath, 'utf8')) |
|
}; |
|
} |
|
} |
|
async function $46fc74961fdcfe31$export$c500fecaca54de65(filename, contents, options) { |
|
let foundMap = await $46fc74961fdcfe31$export$527a92fa675f5e93(options.fs, filename, contents); |
|
if (foundMap) { |
|
let mapSourceRoot = ($parcel$interopDefault($8C1kk$path)).dirname(filename); |
|
if (foundMap.map.sourceRoot && !$3dff16cfd200ff25$export$16778b798ae8e49d(foundMap.map.sourceRoot).startsWith('/')) mapSourceRoot = ($parcel$interopDefault($8C1kk$path)).join(mapSourceRoot, foundMap.map.sourceRoot); |
|
let sourcemapInstance = new ($parcel$interopDefault($8C1kk$parcelsourcemap))(options.projectRoot); |
|
sourcemapInstance.addVLQMap({ |
|
...foundMap.map, |
|
sources: foundMap.map.sources.map((s)=>{ |
|
return ($parcel$interopDefault($8C1kk$path)).join(mapSourceRoot, s); |
|
}) |
|
}); |
|
return sourcemapInstance; |
|
} |
|
} |
|
function $46fc74961fdcfe31$export$2fed780245c466c1(loc, originalMap) { |
|
let { filePath: filePath , start: { line: startLine , column: startCol } , end: { line: endLine , column: endCol } } = loc; |
|
let lineDiff = endLine - startLine; |
|
let colDiff = endCol - startCol; |
|
let start = originalMap.findClosestMapping(startLine, startCol); |
|
let end = originalMap.findClosestMapping(endLine, endCol); |
|
if (start === null || start === void 0 ? void 0 : start.original) { |
|
if (start.source) filePath = start.source; |
|
({ line: startLine , column: startCol } = start.original); |
|
startCol++; // source map columns are 0-based |
|
} |
|
if (end === null || end === void 0 ? void 0 : end.original) { |
|
({ line: endLine , column: endCol } = end.original); |
|
endCol++; |
|
if (endLine < startLine) { |
|
endLine = startLine; |
|
endCol = startCol; |
|
} else if (endLine === startLine && endCol < startCol && lineDiff === 0) endCol = startCol + colDiff; |
|
} else { |
|
endLine = startLine; |
|
endCol = startCol; |
|
} |
|
return { |
|
filePath: filePath, |
|
start: { |
|
line: startLine, |
|
column: startCol |
|
}, |
|
end: { |
|
line: endLine, |
|
column: endCol |
|
} |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
//# sourceMappingURL=index.js.map
|