UNPKG

ndn-js

Version:

A JavaScript client library for Named Data Networking

1,433 lines (1,292 loc) 2.25 MB
// Domain Public by Eric Wendelin http://www.eriwen.com/ (2008) // Luke Smith http://lucassmith.name/ (2008) // Loic Dachary <loic@dachary.org> (2008) // Johan Euphrosine <proppy@aminche.com> (2008) // Oyvind Sean Kinsey http://kinsey.no/blog (2010) // Victor Homyakov <victor-homyakov@users.sourceforge.net> (2010) /*global module, exports, define, ActiveXObject*/ (function(global, factory) { if (typeof exports === 'object') { // Node module.exports.printStackTrace = factory(); } else if (typeof define === 'function' && define.amd) { // AMD define(factory); } else { // Browser globals global.printStackTrace = factory(); } }(this, function() { /** * Main function giving a function stack trace with a forced or passed in Error * * @cfg {Error} e The error to create a stacktrace from (optional) * @cfg {Boolean} guess If we should try to resolve the names of anonymous functions * @return {Array} of Strings with functions, lines, files, and arguments where possible */ function printStackTrace(options) { options = options || {guess: true}; var ex = options.e || null, guess = !!options.guess, mode = options.mode || null; var p = new printStackTrace.implementation(), result = p.run(ex, mode); return (guess) ? p.guessAnonymousFunctions(result) : result; } printStackTrace.implementation = function() { }; printStackTrace.implementation.prototype = { /** * @param {Error} [ex] The error to create a stacktrace from (optional) * @param {String} [mode] Forced mode (optional, mostly for unit tests) */ run: function(ex, mode) { ex = ex || this.createException(); mode = mode || this.mode(ex); if (mode === 'other') { return this.other(arguments.callee); } else { return this[mode](ex); } }, createException: function() { try { this.undef(); } catch (e) { return e; } }, /** * Mode could differ for different exception, e.g. * exceptions in Chrome may or may not have arguments or stack. * * @return {String} mode of operation for the exception */ mode: function(e) { if (typeof window !== 'undefined' && window.navigator.userAgent.indexOf('PhantomJS') > -1) { return 'phantomjs'; } if (e['arguments'] && e.stack) { return 'chrome'; } if (e.stack && e.sourceURL) { return 'safari'; } if (e.stack && e.number) { return 'ie'; } if (e.stack && e.fileName) { return 'firefox'; } if (e.message && e['opera#sourceloc']) { // e.message.indexOf("Backtrace:") > -1 -> opera9 // 'opera#sourceloc' in e -> opera9, opera10a // !e.stacktrace -> opera9 if (!e.stacktrace) { return 'opera9'; // use e.message } if (e.message.indexOf('\n') > -1 && e.message.split('\n').length > e.stacktrace.split('\n').length) { // e.message may have more stack entries than e.stacktrace return 'opera9'; // use e.message } return 'opera10a'; // use e.stacktrace } if (e.message && e.stack && e.stacktrace) { // e.stacktrace && e.stack -> opera10b if (e.stacktrace.indexOf("called from line") < 0) { return 'opera10b'; // use e.stacktrace, format differs from 'opera10a' } // e.stacktrace && e.stack -> opera11 return 'opera11'; // use e.stacktrace, format differs from 'opera10a', 'opera10b' } if (e.stack && !e.fileName) { // Chrome 27 does not have e.arguments as earlier versions, // but still does not have e.fileName as Firefox return 'chrome'; } return 'other'; }, /** * Given a context, function name, and callback function, overwrite it so that it calls * printStackTrace() first with a callback and then runs the rest of the body. * * @param {Object} context of execution (e.g. window) * @param {String} functionName to instrument * @param {Function} callback function to call with a stack trace on invocation */ instrumentFunction: function(context, functionName, callback) { context = context || window; var original = context[functionName]; context[functionName] = function instrumented() { callback.call(this, printStackTrace().slice(4)); return context[functionName]._instrumented.apply(this, arguments); }; context[functionName]._instrumented = original; }, /** * Given a context and function name of a function that has been * instrumented, revert the function to it's original (non-instrumented) * state. * * @param {Object} context of execution (e.g. window) * @param {String} functionName to de-instrument */ deinstrumentFunction: function(context, functionName) { if (context[functionName].constructor === Function && context[functionName]._instrumented && context[functionName]._instrumented.constructor === Function) { context[functionName] = context[functionName]._instrumented; } }, /** * Given an Error object, return a formatted Array based on Chrome's stack string. * * @param e - Error object to inspect * @return Array<String> of function calls, files and line numbers */ chrome: function(e) { return (e.stack + '\n') .replace(/^[\s\S]+?\s+at\s+/, ' at ') // remove message .replace(/^\s+(at eval )?at\s+/gm, '') // remove 'at' and indentation .replace(/^([^\(]+?)([\n$])/gm, '{anonymous}() ($1)$2') .replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}() ($1)') .replace(/^(.+) \((.+)\)$/gm, '$1@$2') .split('\n') .slice(0, -1); }, /** * Given an Error object, return a formatted Array based on Safari's stack string. * * @param e - Error object to inspect * @return Array<String> of function calls, files and line numbers */ safari: function(e) { return e.stack.replace(/\[native code\]\n/m, '') .replace(/^(?=\w+Error\:).*$\n/m, '') .replace(/^@/gm, '{anonymous}()@') .split('\n'); }, /** * Given an Error object, return a formatted Array based on IE's stack string. * * @param e - Error object to inspect * @return Array<String> of function calls, files and line numbers */ ie: function(e) { return e.stack .replace(/^\s*at\s+(.*)$/gm, '$1') .replace(/^Anonymous function\s+/gm, '{anonymous}() ') .replace(/^(.+)\s+\((.+)\)$/gm, '$1@$2') .split('\n') .slice(1); }, /** * Given an Error object, return a formatted Array based on Firefox's stack string. * * @param e - Error object to inspect * @return Array<String> of function calls, files and line numbers */ firefox: function(e) { return e.stack.replace(/(?:\n@:0)?\s+$/m, '') .replace(/^(?:\((\S*)\))?@/gm, '{anonymous}($1)@') .split('\n'); }, opera11: function(e) { var ANON = '{anonymous}', lineRE = /^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/; var lines = e.stacktrace.split('\n'), result = []; for (var i = 0, len = lines.length; i < len; i += 2) { var match = lineRE.exec(lines[i]); if (match) { var location = match[4] + ':' + match[1] + ':' + match[2]; var fnName = match[3] || "global code"; fnName = fnName.replace(/<anonymous function: (\S+)>/, "$1").replace(/<anonymous function>/, ANON); result.push(fnName + '@' + location + ' -- ' + lines[i + 1].replace(/^\s+/, '')); } } return result; }, opera10b: function(e) { // "<anonymous function: run>([arguments not available])@file://localhost/G:/js/stacktrace.js:27\n" + // "printStackTrace([arguments not available])@file://localhost/G:/js/stacktrace.js:18\n" + // "@file://localhost/G:/js/test/functional/testcase1.html:15" var lineRE = /^(.*)@(.+):(\d+)$/; var lines = e.stacktrace.split('\n'), result = []; for (var i = 0, len = lines.length; i < len; i++) { var match = lineRE.exec(lines[i]); if (match) { var fnName = match[1] ? (match[1] + '()') : "global code"; result.push(fnName + '@' + match[2] + ':' + match[3]); } } return result; }, /** * Given an Error object, return a formatted Array based on Opera 10's stacktrace string. * * @param e - Error object to inspect * @return Array<String> of function calls, files and line numbers */ opera10a: function(e) { // " Line 27 of linked script file://localhost/G:/js/stacktrace.js\n" // " Line 11 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html: In function foo\n" var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i; var lines = e.stacktrace.split('\n'), result = []; for (var i = 0, len = lines.length; i < len; i += 2) { var match = lineRE.exec(lines[i]); if (match) { var fnName = match[3] || ANON; result.push(fnName + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, '')); } } return result; }, // Opera 7.x-9.2x only! opera9: function(e) { // " Line 43 of linked script file://localhost/G:/js/stacktrace.js\n" // " Line 7 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html\n" var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)/i; var lines = e.message.split('\n'), result = []; for (var i = 2, len = lines.length; i < len; i += 2) { var match = lineRE.exec(lines[i]); if (match) { result.push(ANON + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, '')); } } return result; }, phantomjs: function(e) { var ANON = '{anonymous}', lineRE = /(\S+) \((\S+)\)/i; var lines = e.stack.split('\n'), result = []; for (var i = 1, len = lines.length; i < len; i++) { lines[i] = lines[i].replace(/^\s+at\s+/gm, ''); var match = lineRE.exec(lines[i]); if (match) { result.push(match[1] + '()@' + match[2]); } else { result.push(ANON + '()@' + lines[i]); } } return result; }, // Safari 5-, IE 9-, and others other: function(curr) { var ANON = '{anonymous}', fnRE = /function(?:\s+([\w$]+))?\s*\(/, stack = [], fn, args, maxStackSize = 10; var slice = Array.prototype.slice; while (curr && stack.length < maxStackSize) { fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON; try { args = slice.call(curr['arguments'] || []); } catch (e) { args = ['Cannot access arguments: ' + e]; } stack[stack.length] = fn + '(' + this.stringifyArguments(args) + ')'; try { curr = curr.caller; } catch (e) { stack[stack.length] = 'Cannot access caller: ' + e; break; } } return stack; }, /** * Given arguments array as a String, substituting type names for non-string types. * * @param {Arguments,Array} args * @return {String} stringified arguments */ stringifyArguments: function(args) { var result = []; var slice = Array.prototype.slice; for (var i = 0; i < args.length; ++i) { var arg = args[i]; if (arg === undefined) { result[i] = 'undefined'; } else if (arg === null) { result[i] = 'null'; } else if (arg.constructor) { // TODO constructor comparison does not work for iframes if (arg.constructor === Array) { if (arg.length < 3) { result[i] = '[' + this.stringifyArguments(arg) + ']'; } else { result[i] = '[' + this.stringifyArguments(slice.call(arg, 0, 1)) + '...' + this.stringifyArguments(slice.call(arg, -1)) + ']'; } } else if (arg.constructor === Object) { result[i] = '#object'; } else if (arg.constructor === Function) { result[i] = '#function'; } else if (arg.constructor === String) { result[i] = '"' + arg + '"'; } else if (arg.constructor === Number) { result[i] = arg; } else { result[i] = '?'; } } } return result.join(','); }, sourceCache: {}, /** * @return {String} the text from a given URL */ ajax: function(url) { var req = this.createXMLHTTPObject(); if (req) { try { req.open('GET', url, false); //req.overrideMimeType('text/plain'); //req.overrideMimeType('text/javascript'); req.send(null); //return req.status == 200 ? req.responseText : ''; return req.responseText; } catch (e) { } } return ''; }, /** * Try XHR methods in order and store XHR factory. * * @return {XMLHttpRequest} XHR function or equivalent */ createXMLHTTPObject: function() { var xmlhttp, XMLHttpFactories = [ function() { return new XMLHttpRequest(); }, function() { return new ActiveXObject('Msxml2.XMLHTTP'); }, function() { return new ActiveXObject('Msxml3.XMLHTTP'); }, function() { return new ActiveXObject('Microsoft.XMLHTTP'); } ]; for (var i = 0; i < XMLHttpFactories.length; i++) { try { xmlhttp = XMLHttpFactories[i](); // Use memoization to cache the factory this.createXMLHTTPObject = XMLHttpFactories[i]; return xmlhttp; } catch (e) { } } }, /** * Given a URL, check if it is in the same domain (so we can get the source * via Ajax). * * @param url {String} source url * @return {Boolean} False if we need a cross-domain request */ isSameDomain: function(url) { return typeof location !== "undefined" && url.indexOf(location.hostname) !== -1; // location may not be defined, e.g. when running from nodejs. }, /** * Get source code from given URL if in the same domain. * * @param url {String} JS source URL * @return {Array} Array of source code lines */ getSource: function(url) { // TODO reuse source from script tags? if (!(url in this.sourceCache)) { this.sourceCache[url] = this.ajax(url).split('\n'); } return this.sourceCache[url]; }, guessAnonymousFunctions: function(stack) { for (var i = 0; i < stack.length; ++i) { var reStack = /\{anonymous\}\(.*\)@(.*)/, reRef = /^(.*?)(?::(\d+))(?::(\d+))?(?: -- .+)?$/, frame = stack[i], ref = reStack.exec(frame); if (ref) { var m = reRef.exec(ref[1]); if (m) { // If falsey, we did not get any file/line information var file = m[1], lineno = m[2], charno = m[3] || 0; if (file && this.isSameDomain(file) && lineno) { var functionName = this.guessAnonymousFunction(file, lineno, charno); stack[i] = frame.replace('{anonymous}', functionName); } } } } return stack; }, guessAnonymousFunction: function(url, lineNo, charNo) { var ret; try { ret = this.findFunctionName(this.getSource(url), lineNo); } catch (e) { ret = 'getSource failed with url: ' + url + ', exception: ' + e.toString(); } return ret; }, findFunctionName: function(source, lineNo) { // FIXME findFunctionName fails for compressed source // (more than one function on the same line) // function {name}({args}) m[1]=name m[2]=args var reFunctionDeclaration = /function\s+([^(]*?)\s*\(([^)]*)\)/; // {name} = function ({args}) TODO args capture // /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*function(?:[^(]*)/ var reFunctionExpression = /['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*function\b/; // {name} = eval() var reFunctionEvaluation = /['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*(?:eval|new Function)\b/; // Walk backwards in the source lines until we find // the line which matches one of the patterns above var code = "", line, maxLines = Math.min(lineNo, 20), m, commentPos; for (var i = 0; i < maxLines; ++i) { // lineNo is 1-based, source[] is 0-based line = source[lineNo - i - 1]; commentPos = line.indexOf('//'); if (commentPos >= 0) { line = line.substr(0, commentPos); } // TODO check other types of comments? Commented code may lead to false positive if (line) { code = line + code; m = reFunctionExpression.exec(code); if (m && m[1]) { return m[1]; } m = reFunctionDeclaration.exec(code); if (m && m[1]) { //return m[1] + "(" + (m[2] || "") + ")"; return m[1]; } m = reFunctionEvaluation.exec(code); if (m && m[1]) { return m[1]; } } } return '(?)'; } }; return printStackTrace; })); (function(globals){ /** * Copyright (C) 2014-2019 Regents of the University of California. * @author: Ryan Bennett * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * A copy of the GNU Lesser General Public License is in the file COPYING. */ // define a shim require function so that a node/browserify require calls dont cause errors when ndn-js is used via <script> tag /** @ignore */ var ndn = ndn || {} /** @ignore */ var exports = ndn; /** @ignore */ var module = {} /** @ignore */ function require(){return ndn;} /** * Copyright (C) 2016-2019 Regents of the University of California. * @author: Jeff Thompson <jefft0@remap.ucla.edu> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * A copy of the GNU Lesser General Public License is in the file COPYING. */ // This is included after stacktrace.js and browserify-require.js so that // require().printStackTrace works. exports.printStackTrace = globals.printStackTrace; /** * This module checks for the availability of various crypto.subtle api's at runtime, * exporting a function that returns the known availability of necessary NDN crypto apis * Copyright (C) 2014-2019 Regents of the University of California. * @author: Ryan Bennett <nomad.ry@gmail.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * A copy of the GNU Lesser General Public License is in the file COPYING. */ function DetectSubtleCrypto(){ var use = false; var baselineSupport = ( (typeof crypto !== 'undefined' && crypto && crypto.subtle) && ( (location.protocol === "https:" || "chrome-extension:" || "chrome:") || (location.hostname === "localhost" || location.hostname === "127.0.0.1") ) ) ? true : false ; if (baselineSupport) { var algo = { name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, hash:{name:"SHA-256"}, publicExponent: new Uint8Array([0x01, 0x00, 0x01])}; var keypair; //try to perform every RSA crypto operation we need, if everything works, set use = true crypto.subtle.generateKey( algo, true, //exportable; ["sign", "verify"]).then(function(key){ keypair = key; return crypto.subtle.sign(algo, key.privateKey, new Uint8Array([1,2,3,4,5])); }).then(function(signature){ return crypto.subtle.verify(algo, keypair.publicKey, signature, new Uint8Array([1,2,3,4,5])); }).then(function(verified){ return crypto.subtle.exportKey("pkcs8",keypair.privateKey); }).then(function(pkcs8){ return crypto.subtle.importKey("pkcs8", pkcs8, algo, true, ["sign"]); }).then(function(importedKey){ return crypto.subtle.exportKey("spki", keypair.publicKey); }).then(function(spki){ return crypto.subtle.importKey("spki", spki, algo, true, ["verify"]); }).then(function(importedKey){ var testDigest = new Uint8Array([1,2,3,4,5]); return crypto.subtle.digest({name:"SHA-256"}, testDigest.buffer); }).then(function(result){ use = true; }, function(err){ console.log("DetectSubtleCrypto encountered error, not using crypto.subtle: ", err) }); } return function useSubtleCrypto(){ return use; } } var UseSubtleCrypto = DetectSubtleCrypto(); exports.UseSubtleCrypto = UseSubtleCrypto; /*! CryptoJS v3.1.2 core-fix.js * code.google.com/p/crypto-js * (c) 2009-2013 by Jeff Mott. All rights reserved. * code.google.com/p/crypto-js/wiki/License * THIS IS FIX of 'core.js' to fix Hmac issue. * https://code.google.com/p/crypto-js/issues/detail?id=84 * https://crypto-js.googlecode.com/svn-history/r667/branches/3.x/src/core.js */ /** * CryptoJS core components. */ var CryptoJS = CryptoJS || (function (Math, undefined) { /** * CryptoJS namespace. */ var C = {}; /** * Library namespace. */ var C_lib = C.lib = {}; /** * Base object for prototypal inheritance. */ var Base = C_lib.Base = (function () { function F() {} return { /** * Creates a new object that inherits from this object. * * @param {Object} overrides Properties to copy into the new object. * * @return {Object} The new object. * * @static * * @example * * var MyType = CryptoJS.lib.Base.extend({ * field: 'value', * * method: function () { * } * }); */ extend: function (overrides) { // Spawn F.prototype = this; var subtype = new F(); // Augment if (overrides) { subtype.mixIn(overrides); } // Create default initializer if (!subtype.hasOwnProperty('init')) { subtype.init = function () { subtype.$super.init.apply(this, arguments); }; } // Initializer's prototype is the subtype object subtype.init.prototype = subtype; // Reference supertype subtype.$super = this; return subtype; }, /** * Extends this object and runs the init method. * Arguments to create() will be passed to init(). * * @return {Object} The new object. * * @static * * @example * * var instance = MyType.create(); */ create: function () { var instance = this.extend(); instance.init.apply(instance, arguments); return instance; }, /** * Initializes a newly created object. * Override this method to add some logic when your objects are created. * * @example * * var MyType = CryptoJS.lib.Base.extend({ * init: function () { * // ... * } * }); */ init: function () { }, /** * Copies properties into this object. * * @param {Object} properties The properties to mix in. * * @example * * MyType.mixIn({ * field: 'value' * }); */ mixIn: function (properties) { for (var propertyName in properties) { if (properties.hasOwnProperty(propertyName)) { this[propertyName] = properties[propertyName]; } } // IE won't copy toString using the loop above if (properties.hasOwnProperty('toString')) { this.toString = properties.toString; } }, /** * Creates a copy of this object. * * @return {Object} The clone. * * @example * * var clone = instance.clone(); */ clone: function () { return this.init.prototype.extend(this); } }; }()); /** * An array of 32-bit words. * * @property {Array} words The array of 32-bit words. * @property {number} sigBytes The number of significant bytes in this word array. */ var WordArray = C_lib.WordArray = Base.extend({ /** * Initializes a newly created word array. * * @param {Array} words (Optional) An array of 32-bit words. * @param {number} sigBytes (Optional) The number of significant bytes in the words. * * @example * * var wordArray = CryptoJS.lib.WordArray.create(); * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); */ init: function (words, sigBytes) { words = this.words = words || []; if (sigBytes != undefined) { this.sigBytes = sigBytes; } else { this.sigBytes = words.length * 4; } }, /** * Converts this word array to a string. * * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex * * @return {string} The stringified word array. * * @example * * var string = wordArray + ''; * var string = wordArray.toString(); * var string = wordArray.toString(CryptoJS.enc.Utf8); */ toString: function (encoder) { return (encoder || Hex).stringify(this); }, /** * Concatenates a word array to this word array. * * @param {WordArray} wordArray The word array to append. * * @return {WordArray} This word array. * * @example * * wordArray1.concat(wordArray2); */ concat: function (wordArray) { // Shortcuts var thisWords = this.words; var thatWords = wordArray.words; var thisSigBytes = this.sigBytes; var thatSigBytes = wordArray.sigBytes; // Clamp excess bits this.clamp(); // Concat if (thisSigBytes % 4) { // Copy one byte at a time for (var i = 0; i < thatSigBytes; i++) { var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); } } else { // Copy one word at a time for (var i = 0; i < thatSigBytes; i += 4) { thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; } } this.sigBytes += thatSigBytes; // Chainable return this; }, /** * Removes insignificant bits. * * @example * * wordArray.clamp(); */ clamp: function () { // Shortcuts var words = this.words; var sigBytes = this.sigBytes; // Clamp words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); words.length = Math.ceil(sigBytes / 4); }, /** * Creates a copy of this word array. * * @return {WordArray} The clone. * * @example * * var clone = wordArray.clone(); */ clone: function () { var clone = Base.clone.call(this); clone.words = this.words.slice(0); return clone; }, /** * Creates a word array filled with random bytes. * * @param {number} nBytes The number of random bytes to generate. * * @return {WordArray} The random word array. * * @static * * @example * * var wordArray = CryptoJS.lib.WordArray.random(16); */ random: function (nBytes) { var words = []; for (var i = 0; i < nBytes; i += 4) { words.push((Math.random() * 0x100000000) | 0); } return new WordArray.init(words, nBytes); } }); /** * Encoder namespace. */ var C_enc = C.enc = {}; /** * Hex encoding strategy. */ var Hex = C_enc.Hex = { /** * Converts a word array to a hex string. * * @param {WordArray} wordArray The word array. * * @return {string} The hex string. * * @static * * @example * * var hexString = CryptoJS.enc.Hex.stringify(wordArray); */ stringify: function (wordArray) { // Shortcuts var words = wordArray.words; var sigBytes = wordArray.sigBytes; // Convert var hexChars = []; for (var i = 0; i < sigBytes; i++) { var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; hexChars.push((bite >>> 4).toString(16)); hexChars.push((bite & 0x0f).toString(16)); } return hexChars.join(''); }, /** * Converts a hex string to a word array. * * @param {string} hexStr The hex string. * * @return {WordArray} The word array. * * @static * * @example * * var wordArray = CryptoJS.enc.Hex.parse(hexString); */ parse: function (hexStr) { // Shortcut var hexStrLength = hexStr.length; // Convert var words = []; for (var i = 0; i < hexStrLength; i += 2) { words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); } return new WordArray.init(words, hexStrLength / 2); } }; /** * Latin1 encoding strategy. */ var Latin1 = C_enc.Latin1 = { /** * Converts a word array to a Latin1 string. * * @param {WordArray} wordArray The word array. * * @return {string} The Latin1 string. * * @static * * @example * * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); */ stringify: function (wordArray) { // Shortcuts var words = wordArray.words; var sigBytes = wordArray.sigBytes; // Convert var latin1Chars = []; for (var i = 0; i < sigBytes; i++) { var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; latin1Chars.push(String.fromCharCode(bite)); } return latin1Chars.join(''); }, /** * Converts a Latin1 string to a word array. * * @param {string} latin1Str The Latin1 string. * * @return {WordArray} The word array. * * @static * * @example * * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); */ parse: function (latin1Str) { // Shortcut var latin1StrLength = latin1Str.length; // Convert var words = []; for (var i = 0; i < latin1StrLength; i++) { words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); } return new WordArray.init(words, latin1StrLength); } }; /** * UTF-8 encoding strategy. */ var Utf8 = C_enc.Utf8 = { /** * Converts a word array to a UTF-8 string. * * @param {WordArray} wordArray The word array. * * @return {string} The UTF-8 string. * * @static * * @example * * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); */ stringify: function (wordArray) { try { return decodeURIComponent(escape(Latin1.stringify(wordArray))); } catch (e) { throw new Error('Malformed UTF-8 data'); } }, /** * Converts a UTF-8 string to a word array. * * @param {string} utf8Str The UTF-8 string. * * @return {WordArray} The word array. * * @static * * @example * * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); */ parse: function (utf8Str) { return Latin1.parse(unescape(encodeURIComponent(utf8Str))); } }; /** * Abstract buffered block algorithm template. * * The property blockSize must be implemented in a concrete subtype. * * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 */ var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ /** * Resets this block algorithm's data buffer to its initial state. * * @example * * bufferedBlockAlgorithm.reset(); */ reset: function () { // Initial values this._data = new WordArray.init(); this._nDataBytes = 0; }, /** * Adds new data to this block algorithm's buffer. * * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. * * @example * * bufferedBlockAlgorithm._append('data'); * bufferedBlockAlgorithm._append(wordArray); */ _append: function (data) { // Convert string to WordArray, else assume WordArray already if (typeof data == 'string') { data = Utf8.parse(data); } // Append this._data.concat(data); this._nDataBytes += data.sigBytes; }, /** * Processes available data blocks. * * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. * * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. * * @return {WordArray} The processed data. * * @example * * var processedData = bufferedBlockAlgorithm._process(); * var processedData = bufferedBlockAlgorithm._process(!!'flush'); */ _process: function (doFlush) { // Shortcuts var data = this._data; var dataWords = data.words; var dataSigBytes = data.sigBytes; var blockSize = this.blockSize; var blockSizeBytes = blockSize * 4; // Count blocks ready var nBlocksReady = dataSigBytes / blockSizeBytes; if (doFlush) { // Round up to include partial blocks nBlocksReady = Math.ceil(nBlocksReady); } else { // Round down to include only full blocks, // less the number of blocks that must remain in the buffer nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); } // Count words ready var nWordsReady = nBlocksReady * blockSize; // Count bytes ready var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks if (nWordsReady) { for (var offset = 0; offset < nWordsReady; offset += blockSize) { // Perform concrete-algorithm logic this._doProcessBlock(dataWords, offset); } // Remove processed words var processedWords = dataWords.splice(0, nWordsReady); data.sigBytes -= nBytesReady; } // Return processed words return new WordArray.init(processedWords, nBytesReady); }, /** * Creates a copy of this object. * * @return {Object} The clone. * * @example * * var clone = bufferedBlockAlgorithm.clone(); */ clone: function () { var clone = Base.clone.call(this); clone._data = this._data.clone(); return clone; }, _minBufferSize: 0 }); /** * Abstract hasher template. * * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) */ var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ /** * Configuration options. */ cfg: Base.extend(), /** * Initializes a newly created hasher. * * @param {Object} cfg (Optional) The configuration options to use for this hash computation. * * @example * * var hasher = CryptoJS.algo.SHA256.create(); */ init: function (cfg) { // Apply config defaults this.cfg = this.cfg.extend(cfg); // Set initial values this.reset(); }, /** * Resets this hasher to its initial state. * * @example * * hasher.reset(); */ reset: function () { // Reset data buffer BufferedBlockAlgorithm.reset.call(this); // Perform concrete-hasher logic this._doReset(); }, /** * Updates this hasher with a message. * * @param {WordArray|string} messageUpdate The message to append. * * @return {Hasher} This hasher. * * @example * * hasher.update('message'); * hasher.update(wordArray); */ update: function (messageUpdate) { // Append this._append(messageUpdate); // Update the hash this._process(); // Chainable return this; }, /** * Finalizes the hash computation. * Note that the finalize operation is effectively a destructive, read-once operation. * * @param {WordArray|string} messageUpdate (Optional) A final message update. * * @return {WordArray} The hash. * * @example * * var hash = hasher.finalize(); * var hash = hasher.finalize('message'); * var hash = hasher.finalize(wordArray); */ finalize: function (messageUpdate) { // Final message update if (messageUpdate) { this._append(messageUpdate); } // Perform concrete-hasher logic var hash = this._doFinalize(); return hash; }, blockSize: 512/32, /** * Creates a shortcut function to a hasher's object interface. * * @param {Hasher} hasher The hasher to create a helper for. * * @return {Function} The shortcut function. * * @static * * @example * * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); */ _createHelper: function (hasher) { return function (message, cfg) { return new hasher.init(cfg).finalize(message); }; }, /** * Creates a shortcut function to the HMAC's object interface. * * @param {Hasher} hasher The hasher to use in this HMAC helper. * * @return {Function} The shortcut function. * * @static * * @example * * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); */ _createHmacHelper: function (hasher) { return function (message, key) { return new C_algo.HMAC.init(hasher, key).finalize(message); }; } }); /** * Algorithm namespace. */ var C_algo = C.algo = {}; return C; }(Math)); exports.CryptoJS = CryptoJS; module.exports = exports; /* CryptoJS v3.1.2 code.google.com/p/crypto-js (c) 2009-2013 by Jeff Mott. All rights reserved. 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. code.google.com/p/crypto-js/wiki/License */ var C = require('./core.js').CryptoJS; (function (Math) { // Shortcuts var C_lib = C.lib; var WordArray = C_lib.WordArray; var Hasher = C_lib.Hasher; var C_algo = C.algo; // Initialization and round constants tables var H = []; var K = []; // Compute constants (function () { function isPrime(n) { var sqrtN = Math.sqrt(n); for (var factor = 2; factor <= sqrtN; factor++) { if (!(n % factor)) { return false; } } return true; } function getFractionalBits(n) { return ((n - (n | 0)) * 0x100000000) | 0; } var n = 2; var nPrime = 0; while (nPrime < 64) { if (isPrime(n)) { if (nPrime < 8) { H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2)); } K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); nPrime++; } n++; } }()); // Reusable object var W = []; /** * SHA-256 hash algorithm. */ var SHA256 = C_algo.SHA256 = Hasher.extend({ _doReset: function () { this._hash = new WordArray.init(H.slice(0)); }, _doProcessBlock: function (M, offset) { // Shortcut var H = this._hash.words; // Working variables var a = H[0]; var b = H[1]; var c = H[2]; var d = H[3]; var e = H[4]; var f = H[5]; var g = H[6]; var h = H[7]; // Computation