http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/base64.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/base64.js b/externs/GCL/externs/goog/crypt/base64.js new file mode 100644 index 0000000..9103fa1 --- /dev/null +++ b/externs/GCL/externs/goog/crypt/base64.js @@ -0,0 +1,286 @@ +// Copyright 2007 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Base64 en/decoding. Not much to say here except that we + * work with decoded values in arrays of bytes. By "byte" I mean a number + * in [0, 255]. + * + * @author [email protected] (Gavin Doughtie) + */ + +goog.provide('goog.crypt.base64'); +goog.require('goog.crypt'); +goog.require('goog.userAgent'); + +// Static lookup maps, lazily populated by init_() + + +/** + * Maps bytes to characters. + * @type {Object} + * @private + */ +goog.crypt.base64.byteToCharMap_ = null; + + +/** + * Maps characters to bytes. + * @type {Object} + * @private + */ +goog.crypt.base64.charToByteMap_ = null; + + +/** + * Maps bytes to websafe characters. + * @type {Object} + * @private + */ +goog.crypt.base64.byteToCharMapWebSafe_ = null; + + +/** + * Maps websafe characters to bytes. + * @type {Object} + * @private + */ +goog.crypt.base64.charToByteMapWebSafe_ = null; + + +/** + * Our default alphabet, shared between + * ENCODED_VALS and ENCODED_VALS_WEBSAFE + * @type {string} + */ +goog.crypt.base64.ENCODED_VALS_BASE = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + + 'abcdefghijklmnopqrstuvwxyz' + + '0123456789'; + + +/** + * Our default alphabet. Value 64 (=) is special; it means "nothing." + * @type {string} + */ +goog.crypt.base64.ENCODED_VALS = + goog.crypt.base64.ENCODED_VALS_BASE + '+/='; + + +/** + * Our websafe alphabet. + * @type {string} + */ +goog.crypt.base64.ENCODED_VALS_WEBSAFE = + goog.crypt.base64.ENCODED_VALS_BASE + '-_.'; + + +/** + * Whether this browser supports the atob and btoa functions. This extension + * started at Mozilla but is now implemented by many browsers. We use the + * ASSUME_* variables to avoid pulling in the full useragent detection library + * but still allowing the standard per-browser compilations. + * + * @type {boolean} + */ +goog.crypt.base64.HAS_NATIVE_SUPPORT = goog.userAgent.GECKO || + goog.userAgent.WEBKIT || + goog.userAgent.OPERA || + typeof(goog.global.atob) == 'function'; + + +/** + * Base64-encode an array of bytes. + * + * @param {Array<number>|Uint8Array} input An array of bytes (numbers with + * value in [0, 255]) to encode. + * @param {boolean=} opt_webSafe Boolean indicating we should use the + * alternative alphabet. + * @return {string} The base64 encoded string. + */ +goog.crypt.base64.encodeByteArray = function(input, opt_webSafe) { + if (!goog.isArrayLike(input)) { + throw Error('encodeByteArray takes an array as a parameter'); + } + + goog.crypt.base64.init_(); + + var byteToCharMap = opt_webSafe ? + goog.crypt.base64.byteToCharMapWebSafe_ : + goog.crypt.base64.byteToCharMap_; + + var output = []; + + for (var i = 0; i < input.length; i += 3) { + var byte1 = input[i]; + var haveByte2 = i + 1 < input.length; + var byte2 = haveByte2 ? input[i + 1] : 0; + var haveByte3 = i + 2 < input.length; + var byte3 = haveByte3 ? input[i + 2] : 0; + + var outByte1 = byte1 >> 2; + var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4); + var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6); + var outByte4 = byte3 & 0x3F; + + if (!haveByte3) { + outByte4 = 64; + + if (!haveByte2) { + outByte3 = 64; + } + } + + output.push(byteToCharMap[outByte1], + byteToCharMap[outByte2], + byteToCharMap[outByte3], + byteToCharMap[outByte4]); + } + + return output.join(''); +}; + + +/** + * Base64-encode a string. + * + * @param {string} input A string to encode. + * @param {boolean=} opt_webSafe If true, we should use the + * alternative alphabet. + * @return {string} The base64 encoded string. + */ +goog.crypt.base64.encodeString = function(input, opt_webSafe) { + // Shortcut for Mozilla browsers that implement + // a native base64 encoder in the form of "btoa/atob" + if (goog.crypt.base64.HAS_NATIVE_SUPPORT && !opt_webSafe) { + return goog.global.btoa(input); + } + return goog.crypt.base64.encodeByteArray( + goog.crypt.stringToByteArray(input), opt_webSafe); +}; + + +/** + * Base64-decode a string. + * + * @param {string} input to decode. + * @param {boolean=} opt_webSafe True if we should use the + * alternative alphabet. + * @return {string} string representing the decoded value. + */ +goog.crypt.base64.decodeString = function(input, opt_webSafe) { + // Shortcut for Mozilla browsers that implement + // a native base64 encoder in the form of "btoa/atob" + if (goog.crypt.base64.HAS_NATIVE_SUPPORT && !opt_webSafe) { + return goog.global.atob(input); + } + return goog.crypt.byteArrayToString( + goog.crypt.base64.decodeStringToByteArray(input, opt_webSafe)); +}; + + +/** + * Base64-decode a string. + * + * In base-64 decoding, groups of four characters are converted into three + * bytes. If the encoder did not apply padding, the input length may not + * be a multiple of 4. + * + * In this case, the last group will have fewer than 4 characters, and + * padding will be inferred. If the group has one or two characters, it decodes + * to one byte. If the group has three characters, it decodes to two bytes. + * + * @param {string} input Input to decode. + * @param {boolean=} opt_webSafe True if we should use the web-safe alphabet. + * @return {!Array<number>} bytes representing the decoded value. + */ +goog.crypt.base64.decodeStringToByteArray = function(input, opt_webSafe) { + goog.crypt.base64.init_(); + + var charToByteMap = opt_webSafe ? + goog.crypt.base64.charToByteMapWebSafe_ : + goog.crypt.base64.charToByteMap_; + + var output = []; + + for (var i = 0; i < input.length; ) { + var byte1 = charToByteMap[input.charAt(i++)]; + + var haveByte2 = i < input.length; + var byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0; + ++i; + + var haveByte3 = i < input.length; + var byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64; + ++i; + + var haveByte4 = i < input.length; + var byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64; + ++i; + + if (byte1 == null || byte2 == null || + byte3 == null || byte4 == null) { + throw Error(); + } + + var outByte1 = (byte1 << 2) | (byte2 >> 4); + output.push(outByte1); + + if (byte3 != 64) { + var outByte2 = ((byte2 << 4) & 0xF0) | (byte3 >> 2); + output.push(outByte2); + + if (byte4 != 64) { + var outByte3 = ((byte3 << 6) & 0xC0) | byte4; + output.push(outByte3); + } + } + } + + return output; +}; + + +/** + * Lazy static initialization function. Called before + * accessing any of the static map variables. + * @private + */ +goog.crypt.base64.init_ = function() { + if (!goog.crypt.base64.byteToCharMap_) { + goog.crypt.base64.byteToCharMap_ = {}; + goog.crypt.base64.charToByteMap_ = {}; + goog.crypt.base64.byteToCharMapWebSafe_ = {}; + goog.crypt.base64.charToByteMapWebSafe_ = {}; + + // We want quick mappings back and forth, so we precompute two maps. + for (var i = 0; i < goog.crypt.base64.ENCODED_VALS.length; i++) { + goog.crypt.base64.byteToCharMap_[i] = + goog.crypt.base64.ENCODED_VALS.charAt(i); + goog.crypt.base64.charToByteMap_[goog.crypt.base64.byteToCharMap_[i]] = i; + goog.crypt.base64.byteToCharMapWebSafe_[i] = + goog.crypt.base64.ENCODED_VALS_WEBSAFE.charAt(i); + goog.crypt.base64.charToByteMapWebSafe_[ + goog.crypt.base64.byteToCharMapWebSafe_[i]] = i; + + // Be forgiving when decoding and correctly decode both encodings. + if (i >= goog.crypt.base64.ENCODED_VALS_BASE.length) { + goog.crypt.base64.charToByteMap_[ + goog.crypt.base64.ENCODED_VALS_WEBSAFE.charAt(i)] = i; + goog.crypt.base64.charToByteMapWebSafe_[ + goog.crypt.base64.ENCODED_VALS.charAt(i)] = i; + } + } + } +};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/basen.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/basen.js b/externs/GCL/externs/goog/crypt/basen.js new file mode 100644 index 0000000..2bac248 --- /dev/null +++ b/externs/GCL/externs/goog/crypt/basen.js @@ -0,0 +1,242 @@ +// Copyright 2007 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Numeric base conversion library. Works for arbitrary bases and + * arbitrary length numbers. + * + * For base-64 conversion use base64.js because it is optimized for the specific + * conversion to base-64 while this module is generic. Base-64 is defined here + * mostly for demonstration purpose. + * + * TODO: Make base64 and baseN classes that have common interface. (Perhaps...) + * + */ + +goog.provide('goog.crypt.baseN'); + + +/** + * Base-2, i.e. '01'. + * @type {string} + */ +goog.crypt.baseN.BASE_BINARY = '01'; + + +/** + * Base-8, i.e. '01234567'. + * @type {string} + */ +goog.crypt.baseN.BASE_OCTAL = '01234567'; + + +/** + * Base-10, i.e. '0123456789'. + * @type {string} + */ +goog.crypt.baseN.BASE_DECIMAL = '0123456789'; + + +/** + * Base-16 using lower case, i.e. '0123456789abcdef'. + * @type {string} + */ +goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL = '0123456789abcdef'; + + +/** + * Base-16 using upper case, i.e. '0123456789ABCDEF'. + * @type {string} + */ +goog.crypt.baseN.BASE_UPPERCASE_HEXADECIMAL = '0123456789ABCDEF'; + + +/** + * The more-known version of the BASE-64 encoding. Uses + and / characters. + * @type {string} + */ +goog.crypt.baseN.BASE_64 = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + + +/** + * URL-safe version of the BASE-64 encoding. + * @type {string} + */ +goog.crypt.baseN.BASE_64_URL_SAFE = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; + + +/** + * Converts a number from one numeric base to another. + * + * The bases are represented as strings, which list allowed digits. Each digit + * should be unique. The bases can either be user defined, or any of + * goog.crypt.baseN.BASE_xxx. + * + * The number is in human-readable format, most significant digit first, and is + * a non-negative integer. Base designators such as $, 0x, d, b or h (at end) + * will be interpreted as digits, so avoid them. Leading zeros will be trimmed. + * + * Note: for huge bases the result may be inaccurate because of overflowing + * 64-bit doubles used by JavaScript for integer calculus. This may happen + * if the product of the number of digits in the input and output bases comes + * close to 10^16, which is VERY unlikely (100M digits in each base), but + * may be possible in the future unicode world. (Unicode 3.2 has less than 100K + * characters. However, it reserves some more, close to 1M.) + * + * @param {string} number The number to convert. + * @param {string} inputBase The numeric base the number is in (all digits). + * @param {string} outputBase Requested numeric base. + * @return {string} The converted number. + */ +goog.crypt.baseN.recodeString = function(number, inputBase, outputBase) { + if (outputBase == '') { + throw Error('Empty output base'); + } + + // Check if number is 0 (special case when we don't want to return ''). + var isZero = true; + for (var i = 0, n = number.length; i < n; i++) { + if (number.charAt(i) != inputBase.charAt(0)) { + isZero = false; + break; + } + } + if (isZero) { + return outputBase.charAt(0); + } + + var numberDigits = goog.crypt.baseN.stringToArray_(number, inputBase); + + var inputBaseSize = inputBase.length; + var outputBaseSize = outputBase.length; + + // result = 0. + var result = []; + + // For all digits of number, starting with the most significant ... + for (var i = numberDigits.length - 1; i >= 0; i--) { + + // result *= number.base. + var carry = 0; + for (var j = 0, n = result.length; j < n; j++) { + var digit = result[j]; + // This may overflow for huge bases. See function comment. + digit = digit * inputBaseSize + carry; + if (digit >= outputBaseSize) { + var remainder = digit % outputBaseSize; + carry = (digit - remainder) / outputBaseSize; + digit = remainder; + } else { + carry = 0; + } + result[j] = digit; + } + while (carry) { + var remainder = carry % outputBaseSize; + result.push(remainder); + carry = (carry - remainder) / outputBaseSize; + } + + // result += number[i]. + carry = numberDigits[i]; + var j = 0; + while (carry) { + if (j >= result.length) { + // Extend result with a leading zero which will be overwritten below. + result.push(0); + } + var digit = result[j]; + digit += carry; + if (digit >= outputBaseSize) { + var remainder = digit % outputBaseSize; + carry = (digit - remainder) / outputBaseSize; + digit = remainder; + } else { + carry = 0; + } + result[j] = digit; + j++; + } + } + + return goog.crypt.baseN.arrayToString_(result, outputBase); +}; + + +/** + * Converts a string representation of a number to an array of digit values. + * + * More precisely, the digit values are indices into the number base, which + * is represented as a string, which can either be user defined or one of the + * BASE_xxx constants. + * + * Throws an Error if the number contains a digit not found in the base. + * + * @param {string} number The string to convert, most significant digit first. + * @param {string} base Digits in the base. + * @return {!Array<number>} Array of digit values, least significant digit + * first. + * @private + */ +goog.crypt.baseN.stringToArray_ = function(number, base) { + var index = {}; + for (var i = 0, n = base.length; i < n; i++) { + index[base.charAt(i)] = i; + } + var result = []; + for (var i = number.length - 1; i >= 0; i--) { + var character = number.charAt(i); + var digit = index[character]; + if (typeof digit == 'undefined') { + throw Error('Number ' + number + + ' contains a character not found in base ' + + base + ', which is ' + character); + } + result.push(digit); + } + return result; +}; + + +/** + * Converts an array representation of a number to a string. + * + * More precisely, the elements of the input array are indices into the base, + * which is represented as a string, which can either be user defined or one of + * the BASE_xxx constants. + * + * Throws an Error if the number contains a digit which is outside the range + * 0 ... base.length - 1. + * + * @param {Array<number>} number Array of digit values, least significant + * first. + * @param {string} base Digits in the base. + * @return {string} Number as a string, most significant digit first. + * @private + */ +goog.crypt.baseN.arrayToString_ = function(number, base) { + var n = number.length; + var chars = []; + var baseSize = base.length; + for (var i = n - 1; i >= 0; i--) { + var digit = number[i]; + if (digit >= baseSize || digit < 0) { + throw Error('Number ' + number + ' contains an invalid digit: ' + digit); + } + chars.push(base.charAt(digit)); + } + return chars.join(''); +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/blobhasher.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/blobhasher.js b/externs/GCL/externs/goog/crypt/blobhasher.js new file mode 100644 index 0000000..cb4af79 --- /dev/null +++ b/externs/GCL/externs/goog/crypt/blobhasher.js @@ -0,0 +1,285 @@ +// Copyright 2011 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Asynchronous hash computer for the Blob interface. + * + * The Blob interface, part of the HTML5 File API, is supported on Chrome 7+, + * Firefox 4.0 and Opera 11. No Blob interface implementation is expected on + * Internet Explorer 10. Chrome 11, Firefox 5.0 and the subsequent release of + * Opera are supposed to use vendor prefixes due to evolving API, see + * http://dev.w3.org/2006/webapi/FileAPI/ for details. + * + * This implementation currently uses upcoming Chrome and Firefox prefixes, + * plus the original Blob.slice specification, as implemented on Chrome 10 + * and Firefox 4.0. + * + */ + +goog.provide('goog.crypt.BlobHasher'); +goog.provide('goog.crypt.BlobHasher.EventType'); + +goog.require('goog.asserts'); +goog.require('goog.events.EventTarget'); +goog.require('goog.fs'); +goog.require('goog.log'); + + + +/** + * Construct the hash computer. + * + * @param {!goog.crypt.Hash} hashFn The hash function to use. + * @param {number=} opt_blockSize Processing block size. + * @constructor + * @struct + * @suppress {checkStructDictInheritance} + * @extends {goog.events.EventTarget} + * @final + */ +goog.crypt.BlobHasher = function(hashFn, opt_blockSize) { + goog.crypt.BlobHasher.base(this, 'constructor'); + + /** + * The actual hash function. + * @type {!goog.crypt.Hash} + * @private + */ + this.hashFn_ = hashFn; + + /** + * The blob being processed or null if no blob is being processed. + * @type {Blob} + * @private + */ + this.blob_ = null; + + /** + * Computed hash value. + * @type {Array<number>} + * @private + */ + this.hashVal_ = null; + + /** + * Number of bytes already processed. + * @type {number} + * @private + */ + this.bytesProcessed_ = 0; + + /** + * The number of bytes to hash or Infinity for no limit. + * @type {number} + * @private + */ + this.hashingLimit_ = Infinity; + + /** + * Processing block size. + * @type {number} + * @private + */ + this.blockSize_ = opt_blockSize || 5000000; + + /** + * File reader object. Will be null if no chunk is currently being read. + * @type {FileReader} + * @private + */ + this.fileReader_ = null; + + /** + * The logger used by this object. + * @type {goog.log.Logger} + * @private + */ + this.logger_ = goog.log.getLogger('goog.crypt.BlobHasher'); +}; +goog.inherits(goog.crypt.BlobHasher, goog.events.EventTarget); + + +/** + * Event names for hash computation events + * @enum {string} + */ +goog.crypt.BlobHasher.EventType = { + STARTED: 'started', + PROGRESS: 'progress', + THROTTLED: 'throttled', + COMPLETE: 'complete', + ABORT: 'abort', + ERROR: 'error' +}; + + +/** + * Start the hash computation. + * @param {!Blob} blob The blob of data to compute the hash for. + */ +goog.crypt.BlobHasher.prototype.hash = function(blob) { + this.abort(); + this.hashFn_.reset(); + this.blob_ = blob; + this.hashVal_ = null; + this.bytesProcessed_ = 0; + this.dispatchEvent(goog.crypt.BlobHasher.EventType.STARTED); + + this.processNextBlock_(); +}; + + +/** + * Sets the maximum number of bytes to hash or Infinity for no limit. Can be + * called before hash() to throttle the hash computation. The hash computation + * can then be continued by repeatedly calling setHashingLimit() with greater + * byte offsets. This is useful if you don't need the hash until some time in + * the future, for example when uploading a file and you don't need the hash + * until the transfer is complete. + * @param {number} byteOffset The byte offset to compute the hash up to. + * Should be a non-negative integer or Infinity for no limit. Negative + * values are not allowed. + */ +goog.crypt.BlobHasher.prototype.setHashingLimit = function(byteOffset) { + goog.asserts.assert(byteOffset >= 0, 'Hashing limit must be non-negative.'); + this.hashingLimit_ = byteOffset; + + // Resume processing if a blob is currently being hashed, but no block read + // is currently in progress. + if (this.blob_ && !this.fileReader_) { + this.processNextBlock_(); + } +}; + + +/** + * Abort hash computation. + */ +goog.crypt.BlobHasher.prototype.abort = function() { + if (this.fileReader_) { + this.fileReader_.abort(); + this.fileReader_ = null; + } + + if (this.blob_) { + this.blob_ = null; + this.dispatchEvent(goog.crypt.BlobHasher.EventType.ABORT); + } +}; + + +/** + * @return {number} Number of bytes processed so far. + */ +goog.crypt.BlobHasher.prototype.getBytesProcessed = function() { + return this.bytesProcessed_; +}; + + +/** + * @return {Array<number>} The computed hash value or null if not ready. + */ +goog.crypt.BlobHasher.prototype.getHash = function() { + return this.hashVal_; +}; + + +/** + * Helper function setting up the processing for the next block, or finalizing + * the computation if all blocks were processed. + * @private + */ +goog.crypt.BlobHasher.prototype.processNextBlock_ = function() { + goog.asserts.assert(this.blob_, 'A hash computation must be in progress.'); + + if (this.bytesProcessed_ < this.blob_.size) { + + if (this.hashingLimit_ <= this.bytesProcessed_) { + // Throttle limit reached. Wait until we are allowed to hash more bytes. + this.dispatchEvent(goog.crypt.BlobHasher.EventType.THROTTLED); + return; + } + + // We have to reset the FileReader every time, otherwise it fails on + // Chrome, including the latest Chrome 12 beta. + // http://code.google.com/p/chromium/issues/detail?id=82346 + this.fileReader_ = new FileReader(); + this.fileReader_.onload = goog.bind(this.onLoad_, this); + this.fileReader_.onerror = goog.bind(this.onError_, this); + + var endOffset = Math.min(this.hashingLimit_, this.blob_.size); + var size = Math.min(endOffset - this.bytesProcessed_, this.blockSize_); + var chunk = goog.fs.sliceBlob(this.blob_, this.bytesProcessed_, + this.bytesProcessed_ + size); + if (!chunk || chunk.size != size) { + goog.log.error(this.logger_, 'Failed slicing the blob'); + this.onError_(); + return; + } + + if (this.fileReader_.readAsArrayBuffer) { + this.fileReader_.readAsArrayBuffer(chunk); + } else if (this.fileReader_.readAsBinaryString) { + this.fileReader_.readAsBinaryString(chunk); + } else { + goog.log.error(this.logger_, 'Failed calling the chunk reader'); + this.onError_(); + } + } else { + this.hashVal_ = this.hashFn_.digest(); + this.blob_ = null; + this.dispatchEvent(goog.crypt.BlobHasher.EventType.COMPLETE); + } +}; + + +/** + * Handle processing block loaded. + * @private + */ +goog.crypt.BlobHasher.prototype.onLoad_ = function() { + goog.log.info(this.logger_, 'Successfully loaded a chunk'); + + var array = null; + if (this.fileReader_.result instanceof Array || + goog.isString(this.fileReader_.result)) { + array = this.fileReader_.result; + } else if (goog.global['ArrayBuffer'] && goog.global['Uint8Array'] && + this.fileReader_.result instanceof ArrayBuffer) { + array = new Uint8Array(this.fileReader_.result); + } + if (!array) { + goog.log.error(this.logger_, 'Failed reading the chunk'); + this.onError_(); + return; + } + + this.hashFn_.update(array); + this.bytesProcessed_ += array.length; + this.fileReader_ = null; + this.dispatchEvent(goog.crypt.BlobHasher.EventType.PROGRESS); + + this.processNextBlock_(); +}; + + +/** + * Handles error. + * @private + */ +goog.crypt.BlobHasher.prototype.onError_ = function() { + this.fileReader_ = null; + this.blob_ = null; + this.dispatchEvent(goog.crypt.BlobHasher.EventType.ERROR); +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/blockcipher.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/blockcipher.js b/externs/GCL/externs/goog/crypt/blockcipher.js new file mode 100644 index 0000000..be766f0 --- /dev/null +++ b/externs/GCL/externs/goog/crypt/blockcipher.js @@ -0,0 +1,52 @@ +// Copyright 2012 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Interface definition of a block cipher. A block cipher is a + * pair of algorithms that implement encryption and decryption of input bytes. + * + * @see http://en.wikipedia.org/wiki/Block_cipher + * + * @author [email protected] (Nathan Naze) + */ + +goog.provide('goog.crypt.BlockCipher'); + + + +/** + * Interface definition for a block cipher. + * @interface + */ +goog.crypt.BlockCipher = function() {}; + + +/** + * Encrypt a plaintext block. The implementation may expect (and assert) + * a particular block length. + * @param {!Array<number>} input Plaintext array of input bytes. + * @return {!Array<number>} Encrypted ciphertext array of bytes. Should be the + * same length as input. + */ +goog.crypt.BlockCipher.prototype.encrypt; + + +/** + * Decrypt a plaintext block. The implementation may expect (and assert) + * a particular block length. + * @param {!Array<number>} input Ciphertext. Array of input bytes. + * @return {!Array<number>} Decrypted plaintext array of bytes. Should be the + * same length as input. + */ +goog.crypt.BlockCipher.prototype.decrypt; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/cbc.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/cbc.js b/externs/GCL/externs/goog/crypt/cbc.js new file mode 100644 index 0000000..68a2656 --- /dev/null +++ b/externs/GCL/externs/goog/crypt/cbc.js @@ -0,0 +1,153 @@ +// Copyright 2012 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Implementation of CBC mode for block ciphers. See + * http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation + * #Cipher-block_chaining_.28CBC.29. for description. + * + * @author [email protected] (Nathan Naze) + */ + +goog.provide('goog.crypt.Cbc'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.crypt'); + + + +/** + * Implements the CBC mode for block ciphers. See + * http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation + * #Cipher-block_chaining_.28CBC.29 + * + * @param {!goog.crypt.BlockCipher} cipher The block cipher to use. + * @param {number=} opt_blockSize The block size of the cipher in bytes. + * Defaults to 16 bytes. + * @constructor + * @final + * @struct + */ +goog.crypt.Cbc = function(cipher, opt_blockSize) { + + /** + * Block cipher. + * @type {!goog.crypt.BlockCipher} + * @private + */ + this.cipher_ = cipher; + + /** + * Block size in bytes. + * @type {number} + * @private + */ + this.blockSize_ = opt_blockSize || 16; +}; + + +/** + * Encrypt a message. + * + * @param {!Array<number>} plainText Message to encrypt. An array of bytes. + * The length should be a multiple of the block size. + * @param {!Array<number>} initialVector Initial vector for the CBC mode. + * An array of bytes with the same length as the block size. + * @return {!Array<number>} Encrypted message. + */ +goog.crypt.Cbc.prototype.encrypt = function(plainText, initialVector) { + + goog.asserts.assert( + plainText.length % this.blockSize_ == 0, + 'Data\'s length must be multiple of block size.'); + + goog.asserts.assert( + initialVector.length == this.blockSize_, + 'Initial vector must be size of one block.'); + + // Implementation of + // http://en.wikipedia.org/wiki/File:Cbc_encryption.png + + var cipherText = []; + var vector = initialVector; + + // Generate each block of the encrypted cypher text. + for (var blockStartIndex = 0; + blockStartIndex < plainText.length; + blockStartIndex += this.blockSize_) { + + // Takes one block from the input message. + var plainTextBlock = goog.array.slice( + plainText, + blockStartIndex, + blockStartIndex + this.blockSize_); + + var input = goog.crypt.xorByteArray(plainTextBlock, vector); + var resultBlock = this.cipher_.encrypt(input); + + goog.array.extend(cipherText, resultBlock); + vector = resultBlock; + } + + return cipherText; +}; + + +/** + * Decrypt a message. + * + * @param {!Array<number>} cipherText Message to decrypt. An array of bytes. + * The length should be a multiple of the block size. + * @param {!Array<number>} initialVector Initial vector for the CBC mode. + * An array of bytes with the same length as the block size. + * @return {!Array<number>} Decrypted message. + */ +goog.crypt.Cbc.prototype.decrypt = function(cipherText, initialVector) { + + goog.asserts.assert( + cipherText.length % this.blockSize_ == 0, + 'Data\'s length must be multiple of block size.'); + + goog.asserts.assert( + initialVector.length == this.blockSize_, + 'Initial vector must be size of one block.'); + + // Implementation of + // http://en.wikipedia.org/wiki/File:Cbc_decryption.png + + var plainText = []; + var blockStartIndex = 0; + var vector = initialVector; + + // Generate each block of the decrypted plain text. + while (blockStartIndex < cipherText.length) { + + // Takes one block. + var cipherTextBlock = goog.array.slice( + cipherText, + blockStartIndex, + blockStartIndex + this.blockSize_); + + var resultBlock = this.cipher_.decrypt(cipherTextBlock); + var plainTextBlock = goog.crypt.xorByteArray(vector, resultBlock); + + goog.array.extend(plainText, plainTextBlock); + vector = cipherTextBlock; + + blockStartIndex += this.blockSize_; + } + + return plainText; +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/crypt.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/crypt.js b/externs/GCL/externs/goog/crypt/crypt.js new file mode 100644 index 0000000..e8f722a --- /dev/null +++ b/externs/GCL/externs/goog/crypt/crypt.js @@ -0,0 +1,173 @@ +// Copyright 2008 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Namespace with crypto related helper functions. + */ + +goog.provide('goog.crypt'); + +goog.require('goog.array'); +goog.require('goog.asserts'); + + +/** + * Turns a string into an array of bytes; a "byte" being a JS number in the + * range 0-255. + * @param {string} str String value to arrify. + * @return {!Array<number>} Array of numbers corresponding to the + * UCS character codes of each character in str. + */ +goog.crypt.stringToByteArray = function(str) { + var output = [], p = 0; + for (var i = 0; i < str.length; i++) { + var c = str.charCodeAt(i); + while (c > 0xff) { + output[p++] = c & 0xff; + c >>= 8; + } + output[p++] = c; + } + return output; +}; + + +/** + * Turns an array of numbers into the string given by the concatenation of the + * characters to which the numbers correspond. + * @param {Array<number>} bytes Array of numbers representing characters. + * @return {string} Stringification of the array. + */ +goog.crypt.byteArrayToString = function(bytes) { + var CHUNK_SIZE = 8192; + + // Special-case the simple case for speed's sake. + if (bytes.length < CHUNK_SIZE) { + return String.fromCharCode.apply(null, bytes); + } + + // The remaining logic splits conversion by chunks since + // Function#apply() has a maximum parameter count. + // See discussion: http://goo.gl/LrWmZ9 + + var str = ''; + for (var i = 0; i < bytes.length; i += CHUNK_SIZE) { + var chunk = goog.array.slice(bytes, i, i + CHUNK_SIZE); + str += String.fromCharCode.apply(null, chunk); + } + return str; +}; + + +/** + * Turns an array of numbers into the hex string given by the concatenation of + * the hex values to which the numbers correspond. + * @param {Uint8Array|Array<number>} array Array of numbers representing + * characters. + * @return {string} Hex string. + */ +goog.crypt.byteArrayToHex = function(array) { + return goog.array.map(array, function(numByte) { + var hexByte = numByte.toString(16); + return hexByte.length > 1 ? hexByte : '0' + hexByte; + }).join(''); +}; + + +/** + * Converts a hex string into an integer array. + * @param {string} hexString Hex string of 16-bit integers (two characters + * per integer). + * @return {!Array<number>} Array of {0,255} integers for the given string. + */ +goog.crypt.hexToByteArray = function(hexString) { + goog.asserts.assert(hexString.length % 2 == 0, + 'Key string length must be multiple of 2'); + var arr = []; + for (var i = 0; i < hexString.length; i += 2) { + arr.push(parseInt(hexString.substring(i, i + 2), 16)); + } + return arr; +}; + + +/** + * Converts a JS string to a UTF-8 "byte" array. + * @param {string} str 16-bit unicode string. + * @return {!Array<number>} UTF-8 byte array. + */ +goog.crypt.stringToUtf8ByteArray = function(str) { + // TODO(user): Use native implementations if/when available + str = str.replace(/\r\n/g, '\n'); + var out = [], p = 0; + for (var i = 0; i < str.length; i++) { + var c = str.charCodeAt(i); + if (c < 128) { + out[p++] = c; + } else if (c < 2048) { + out[p++] = (c >> 6) | 192; + out[p++] = (c & 63) | 128; + } else { + out[p++] = (c >> 12) | 224; + out[p++] = ((c >> 6) & 63) | 128; + out[p++] = (c & 63) | 128; + } + } + return out; +}; + + +/** + * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode. + * @param {Uint8Array|Array<number>} bytes UTF-8 byte array. + * @return {string} 16-bit Unicode string. + */ +goog.crypt.utf8ByteArrayToString = function(bytes) { + // TODO(user): Use native implementations if/when available + var out = [], pos = 0, c = 0; + while (pos < bytes.length) { + var c1 = bytes[pos++]; + if (c1 < 128) { + out[c++] = String.fromCharCode(c1); + } else if (c1 > 191 && c1 < 224) { + var c2 = bytes[pos++]; + out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63); + } else { + var c2 = bytes[pos++]; + var c3 = bytes[pos++]; + out[c++] = String.fromCharCode( + (c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63); + } + } + return out.join(''); +}; + + +/** + * XOR two byte arrays. + * @param {!ArrayBufferView|!Array<number>} bytes1 Byte array 1. + * @param {!ArrayBufferView|!Array<number>} bytes2 Byte array 2. + * @return {!Array<number>} Resulting XOR of the two byte arrays. + */ +goog.crypt.xorByteArray = function(bytes1, bytes2) { + goog.asserts.assert( + bytes1.length == bytes2.length, + 'XOR array lengths must match'); + + var result = []; + for (var i = 0; i < bytes1.length; i++) { + result.push(bytes1[i] ^ bytes2[i]); + } + return result; +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/hash.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/hash.js b/externs/GCL/externs/goog/crypt/hash.js new file mode 100644 index 0000000..51209be --- /dev/null +++ b/externs/GCL/externs/goog/crypt/hash.js @@ -0,0 +1,69 @@ +// Copyright 2011 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Abstract cryptographic hash interface. + * + * See goog.crypt.Sha1 and goog.crypt.Md5 for sample implementations. + * + */ + +goog.provide('goog.crypt.Hash'); + + + +/** + * Create a cryptographic hash instance. + * + * @constructor + * @struct + */ +goog.crypt.Hash = function() { + /** + * The block size for the hasher. + * @type {number} + */ + this.blockSize = -1; +}; + + +/** + * Resets the internal accumulator. + */ +goog.crypt.Hash.prototype.reset = goog.abstractMethod; + + +/** + * Adds a byte array (array with values in [0-255] range) or a string (might + * only contain 8-bit, i.e., Latin1 characters) to the internal accumulator. + * + * Many hash functions operate on blocks of data and implement optimizations + * when a full chunk of data is readily available. Hence it is often preferable + * to provide large chunks of data (a kilobyte or more) than to repeatedly + * call the update method with few tens of bytes. If this is not possible, or + * not feasible, it might be good to provide data in multiplies of hash block + * size (often 64 bytes). Please see the implementation and performance tests + * of your favourite hash. + * + * @param {Array<number>|Uint8Array|string} bytes Data used for the update. + * @param {number=} opt_length Number of bytes to use. + */ +goog.crypt.Hash.prototype.update = goog.abstractMethod; + + +/** + * @return {!Array<number>} The finalized hash computed + * from the internal accumulator. + */ +goog.crypt.Hash.prototype.digest = goog.abstractMethod; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/hash32.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/hash32.js b/externs/GCL/externs/goog/crypt/hash32.js new file mode 100644 index 0000000..fa24ccf --- /dev/null +++ b/externs/GCL/externs/goog/crypt/hash32.js @@ -0,0 +1,184 @@ +// Copyright 2008 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Implementation of 32-bit hashing functions. + * + * This is a direct port from the Google Java Hash class + * + */ + +goog.provide('goog.crypt.hash32'); + +goog.require('goog.crypt'); + + +/** + * Default seed used during hashing, digits of pie. + * See SEED32 in http://go/base.hash.java + * @type {number} + */ +goog.crypt.hash32.SEED32 = 314159265; + + +/** + * Arbitrary constant used during hashing. + * See CONSTANT32 in http://go/base.hash.java + * @type {number} + */ +goog.crypt.hash32.CONSTANT32 = -1640531527; + + +/** + * Hashes a string to a 32-bit value. + * @param {string} str String to hash. + * @return {number} 32-bit hash. + */ +goog.crypt.hash32.encodeString = function(str) { + return goog.crypt.hash32.encodeByteArray(goog.crypt.stringToByteArray(str)); +}; + + +/** + * Hashes a string to a 32-bit value, converting the string to UTF-8 before + * doing the encoding. + * @param {string} str String to hash. + * @return {number} 32-bit hash. + */ +goog.crypt.hash32.encodeStringUtf8 = function(str) { + return goog.crypt.hash32.encodeByteArray( + goog.crypt.stringToUtf8ByteArray(str)); +}; + + +/** + * Hashes an integer to a 32-bit value. + * @param {number} value Number to hash. + * @return {number} 32-bit hash. + */ +goog.crypt.hash32.encodeInteger = function(value) { + // TODO(user): Does this make sense in JavaScript with doubles? Should we + // force the value to be in the correct range? + return goog.crypt.hash32.mix32_({ + a: value, + b: goog.crypt.hash32.CONSTANT32, + c: goog.crypt.hash32.SEED32 + }); +}; + + +/** + * Hashes a "byte" array to a 32-bit value using the supplied seed. + * @param {Array<number>} bytes Array of bytes. + * @param {number=} opt_offset The starting position to use for hash + * computation. + * @param {number=} opt_length Number of bytes that are used for hashing. + * @param {number=} opt_seed The seed. + * @return {number} 32-bit hash. + */ +goog.crypt.hash32.encodeByteArray = function( + bytes, opt_offset, opt_length, opt_seed) { + var offset = opt_offset || 0; + var length = opt_length || bytes.length; + var seed = opt_seed || goog.crypt.hash32.SEED32; + + var mix = { + a: goog.crypt.hash32.CONSTANT32, + b: goog.crypt.hash32.CONSTANT32, + c: seed + }; + + var keylen; + for (keylen = length; keylen >= 12; keylen -= 12, offset += 12) { + mix.a += goog.crypt.hash32.wordAt_(bytes, offset); + mix.b += goog.crypt.hash32.wordAt_(bytes, offset + 4); + mix.c += goog.crypt.hash32.wordAt_(bytes, offset + 8); + goog.crypt.hash32.mix32_(mix); + } + // Hash any remaining bytes + mix.c += length; + switch (keylen) { // deal with rest. Some cases fall through + case 11: mix.c += (bytes[offset + 10]) << 24; + case 10: mix.c += (bytes[offset + 9] & 0xff) << 16; + case 9 : mix.c += (bytes[offset + 8] & 0xff) << 8; + // the first byte of c is reserved for the length + case 8 : + mix.b += goog.crypt.hash32.wordAt_(bytes, offset + 4); + mix.a += goog.crypt.hash32.wordAt_(bytes, offset); + break; + case 7 : mix.b += (bytes[offset + 6] & 0xff) << 16; + case 6 : mix.b += (bytes[offset + 5] & 0xff) << 8; + case 5 : mix.b += (bytes[offset + 4] & 0xff); + case 4 : + mix.a += goog.crypt.hash32.wordAt_(bytes, offset); + break; + case 3 : mix.a += (bytes[offset + 2] & 0xff) << 16; + case 2 : mix.a += (bytes[offset + 1] & 0xff) << 8; + case 1 : mix.a += (bytes[offset + 0] & 0xff); + // case 0 : nothing left to add + } + return goog.crypt.hash32.mix32_(mix); +}; + + +/** + * Performs an inplace mix of an object with the integer properties (a, b, c) + * and returns the final value of c. + * @param {Object} mix Object with properties, a, b, and c. + * @return {number} The end c-value for the mixing. + * @private + */ +goog.crypt.hash32.mix32_ = function(mix) { + var a = mix.a, b = mix.b, c = mix.c; + a -= b; a -= c; a ^= c >>> 13; + b -= c; b -= a; b ^= a << 8; + c -= a; c -= b; c ^= b >>> 13; + a -= b; a -= c; a ^= c >>> 12; + b -= c; b -= a; b ^= a << 16; + c -= a; c -= b; c ^= b >>> 5; + a -= b; a -= c; a ^= c >>> 3; + b -= c; b -= a; b ^= a << 10; + c -= a; c -= b; c ^= b >>> 15; + mix.a = a; mix.b = b; mix.c = c; + return c; +}; + + +/** + * Returns the word at a given offset. Treating an array of bytes a word at a + * time is far more efficient than byte-by-byte. + * @param {Array<number>} bytes Array of bytes. + * @param {number} offset Offset in the byte array. + * @return {number} Integer value for the word. + * @private + */ +goog.crypt.hash32.wordAt_ = function(bytes, offset) { + var a = goog.crypt.hash32.toSigned_(bytes[offset + 0]); + var b = goog.crypt.hash32.toSigned_(bytes[offset + 1]); + var c = goog.crypt.hash32.toSigned_(bytes[offset + 2]); + var d = goog.crypt.hash32.toSigned_(bytes[offset + 3]); + return a + (b << 8) + (c << 16) + (d << 24); +}; + + +/** + * Converts an unsigned "byte" to signed, that is, convert a value in the range + * (0, 2^8-1) to (-2^7, 2^7-1) in order to be compatible with Java's byte type. + * @param {number} n Unsigned "byte" value. + * @return {number} Signed "byte" value. + * @private + */ +goog.crypt.hash32.toSigned_ = function(n) { + return n > 127 ? n - 256 : n; +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/hmac.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/hmac.js b/externs/GCL/externs/goog/crypt/hmac.js new file mode 100644 index 0000000..15e0e1d --- /dev/null +++ b/externs/GCL/externs/goog/crypt/hmac.js @@ -0,0 +1,160 @@ +// Copyright 2011 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Implementation of HMAC in JavaScript. + * + * Usage: + * var hmac = new goog.crypt.Hmac(new goog.crypt.sha1(), key, 64); + * var digest = hmac.getHmac(bytes); + * + * @author [email protected] (Jige Yu) - port to closure + */ + + +goog.provide('goog.crypt.Hmac'); + +goog.require('goog.crypt.Hash'); + + + +/** + * @constructor + * @param {!goog.crypt.Hash} hasher An object to serve as a hash function. + * @param {Array<number>} key The secret key to use to calculate the hmac. + * Should be an array of not more than {@code blockSize} integers in + {0, 255}. + * @param {number=} opt_blockSize Optional. The block size {@code hasher} uses. + * If not specified, uses the block size from the hasher, or 16 if it is + * not specified. + * @extends {goog.crypt.Hash} + * @final + * @struct + */ +goog.crypt.Hmac = function(hasher, key, opt_blockSize) { + goog.crypt.Hmac.base(this, 'constructor'); + + /** + * The underlying hasher to calculate hash. + * + * @type {!goog.crypt.Hash} + * @private + */ + this.hasher_ = hasher; + + this.blockSize = opt_blockSize || hasher.blockSize || 16; + + /** + * The outer padding array of hmac + * + * @type {!Array<number>} + * @private + */ + this.keyO_ = new Array(this.blockSize); + + /** + * The inner padding array of hmac + * + * @type {!Array<number>} + * @private + */ + this.keyI_ = new Array(this.blockSize); + + this.initialize_(key); +}; +goog.inherits(goog.crypt.Hmac, goog.crypt.Hash); + + +/** + * Outer padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC + * + * @type {number} + * @private + */ +goog.crypt.Hmac.OPAD_ = 0x5c; + + +/** + * Inner padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC + * + * @type {number} + * @private + */ +goog.crypt.Hmac.IPAD_ = 0x36; + + +/** + * Initializes Hmac by precalculating the inner and outer paddings. + * + * @param {Array<number>} key The secret key to use to calculate the hmac. + * Should be an array of not more than {@code blockSize} integers in + {0, 255}. + * @private + */ +goog.crypt.Hmac.prototype.initialize_ = function(key) { + if (key.length > this.blockSize) { + this.hasher_.update(key); + key = this.hasher_.digest(); + this.hasher_.reset(); + } + // Precalculate padded and xor'd keys. + var keyByte; + for (var i = 0; i < this.blockSize; i++) { + if (i < key.length) { + keyByte = key[i]; + } else { + keyByte = 0; + } + this.keyO_[i] = keyByte ^ goog.crypt.Hmac.OPAD_; + this.keyI_[i] = keyByte ^ goog.crypt.Hmac.IPAD_; + } + // Be ready for an immediate update. + this.hasher_.update(this.keyI_); +}; + + +/** @override */ +goog.crypt.Hmac.prototype.reset = function() { + this.hasher_.reset(); + this.hasher_.update(this.keyI_); +}; + + +/** @override */ +goog.crypt.Hmac.prototype.update = function(bytes, opt_length) { + this.hasher_.update(bytes, opt_length); +}; + + +/** @override */ +goog.crypt.Hmac.prototype.digest = function() { + var temp = this.hasher_.digest(); + this.hasher_.reset(); + this.hasher_.update(this.keyO_); + this.hasher_.update(temp); + return this.hasher_.digest(); +}; + + +/** + * Calculates an HMAC for a given message. + * + * @param {Array<number>|Uint8Array|string} message Data to Hmac. + * @return {!Array<number>} the digest of the given message. + */ +goog.crypt.Hmac.prototype.getHmac = function(message) { + this.reset(); + this.update(message); + return this.digest(); +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/md5.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/md5.js b/externs/GCL/externs/goog/crypt/md5.js new file mode 100644 index 0000000..56335e1 --- /dev/null +++ b/externs/GCL/externs/goog/crypt/md5.js @@ -0,0 +1,435 @@ +// Copyright 2011 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview MD5 cryptographic hash. + * Implementation of http://tools.ietf.org/html/rfc1321 with common + * optimizations and tweaks (see http://en.wikipedia.org/wiki/MD5). + * + * Usage: + * var md5 = new goog.crypt.Md5(); + * md5.update(bytes); + * var hash = md5.digest(); + * + * Performance: + * Chrome 23 ~680 Mbit/s + * Chrome 13 (in a VM) ~250 Mbit/s + * Firefox 6.0 (in a VM) ~100 Mbit/s + * IE9 (in a VM) ~27 Mbit/s + * Firefox 3.6 ~15 Mbit/s + * IE8 (in a VM) ~13 Mbit/s + * + */ + +goog.provide('goog.crypt.Md5'); + +goog.require('goog.crypt.Hash'); + + + +/** + * MD5 cryptographic hash constructor. + * @constructor + * @extends {goog.crypt.Hash} + * @final + * @struct + */ +goog.crypt.Md5 = function() { + goog.crypt.Md5.base(this, 'constructor'); + + this.blockSize = 512 / 8; + + /** + * Holds the current values of accumulated A-D variables (MD buffer). + * @type {!Array<number>} + * @private + */ + this.chain_ = new Array(4); + + /** + * A buffer holding the data until the whole block can be processed. + * @type {!Array<number>} + * @private + */ + this.block_ = new Array(this.blockSize); + + /** + * The length of yet-unprocessed data as collected in the block. + * @type {number} + * @private + */ + this.blockLength_ = 0; + + /** + * The total length of the message so far. + * @type {number} + * @private + */ + this.totalLength_ = 0; + + this.reset(); +}; +goog.inherits(goog.crypt.Md5, goog.crypt.Hash); + + +/** + * Integer rotation constants used by the abbreviated implementation. + * They are hardcoded in the unrolled implementation, so it is left + * here commented out. + * @type {Array<number>} + * @private + * +goog.crypt.Md5.S_ = [ + 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 +]; + */ + +/** + * Sine function constants used by the abbreviated implementation. + * They are hardcoded in the unrolled implementation, so it is left + * here commented out. + * @type {Array<number>} + * @private + * +goog.crypt.Md5.T_ = [ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +]; + */ + + +/** @override */ +goog.crypt.Md5.prototype.reset = function() { + this.chain_[0] = 0x67452301; + this.chain_[1] = 0xefcdab89; + this.chain_[2] = 0x98badcfe; + this.chain_[3] = 0x10325476; + + this.blockLength_ = 0; + this.totalLength_ = 0; +}; + + +/** + * Internal compress helper function. It takes a block of data (64 bytes) + * and updates the accumulator. + * @param {Array<number>|Uint8Array|string} buf The block to compress. + * @param {number=} opt_offset Offset of the block in the buffer. + * @private + */ +goog.crypt.Md5.prototype.compress_ = function(buf, opt_offset) { + if (!opt_offset) { + opt_offset = 0; + } + + // We allocate the array every time, but it's cheap in practice. + var X = new Array(16); + + // Get 16 little endian words. It is not worth unrolling this for Chrome 11. + if (goog.isString(buf)) { + for (var i = 0; i < 16; ++i) { + X[i] = (buf.charCodeAt(opt_offset++)) | + (buf.charCodeAt(opt_offset++) << 8) | + (buf.charCodeAt(opt_offset++) << 16) | + (buf.charCodeAt(opt_offset++) << 24); + } + } else { + for (var i = 0; i < 16; ++i) { + X[i] = (buf[opt_offset++]) | + (buf[opt_offset++] << 8) | + (buf[opt_offset++] << 16) | + (buf[opt_offset++] << 24); + } + } + + var A = this.chain_[0]; + var B = this.chain_[1]; + var C = this.chain_[2]; + var D = this.chain_[3]; + var sum = 0; + + /* + * This is an abbreviated implementation, it is left here commented out for + * reference purposes. See below for an unrolled version in use. + * + var f, n, tmp; + for (var i = 0; i < 64; ++i) { + + if (i < 16) { + f = (D ^ (B & (C ^ D))); + n = i; + } else if (i < 32) { + f = (C ^ (D & (B ^ C))); + n = (5 * i + 1) % 16; + } else if (i < 48) { + f = (B ^ C ^ D); + n = (3 * i + 5) % 16; + } else { + f = (C ^ (B | (~D))); + n = (7 * i) % 16; + } + + tmp = D; + D = C; + C = B; + sum = (A + f + goog.crypt.Md5.T_[i] + X[n]) & 0xffffffff; + B += ((sum << goog.crypt.Md5.S_[i]) & 0xffffffff) | + (sum >>> (32 - goog.crypt.Md5.S_[i])); + A = tmp; + } + */ + + /* + * This is an unrolled MD5 implementation, which gives ~30% speedup compared + * to the abbreviated implementation above, as measured on Chrome 11. It is + * important to keep 32-bit croppings to minimum and inline the integer + * rotation. + */ + sum = (A + (D ^ (B & (C ^ D))) + X[0] + 0xd76aa478) & 0xffffffff; + A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25)); + sum = (D + (C ^ (A & (B ^ C))) + X[1] + 0xe8c7b756) & 0xffffffff; + D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20)); + sum = (C + (B ^ (D & (A ^ B))) + X[2] + 0x242070db) & 0xffffffff; + C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15)); + sum = (B + (A ^ (C & (D ^ A))) + X[3] + 0xc1bdceee) & 0xffffffff; + B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10)); + sum = (A + (D ^ (B & (C ^ D))) + X[4] + 0xf57c0faf) & 0xffffffff; + A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25)); + sum = (D + (C ^ (A & (B ^ C))) + X[5] + 0x4787c62a) & 0xffffffff; + D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20)); + sum = (C + (B ^ (D & (A ^ B))) + X[6] + 0xa8304613) & 0xffffffff; + C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15)); + sum = (B + (A ^ (C & (D ^ A))) + X[7] + 0xfd469501) & 0xffffffff; + B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10)); + sum = (A + (D ^ (B & (C ^ D))) + X[8] + 0x698098d8) & 0xffffffff; + A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25)); + sum = (D + (C ^ (A & (B ^ C))) + X[9] + 0x8b44f7af) & 0xffffffff; + D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20)); + sum = (C + (B ^ (D & (A ^ B))) + X[10] + 0xffff5bb1) & 0xffffffff; + C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15)); + sum = (B + (A ^ (C & (D ^ A))) + X[11] + 0x895cd7be) & 0xffffffff; + B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10)); + sum = (A + (D ^ (B & (C ^ D))) + X[12] + 0x6b901122) & 0xffffffff; + A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25)); + sum = (D + (C ^ (A & (B ^ C))) + X[13] + 0xfd987193) & 0xffffffff; + D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20)); + sum = (C + (B ^ (D & (A ^ B))) + X[14] + 0xa679438e) & 0xffffffff; + C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15)); + sum = (B + (A ^ (C & (D ^ A))) + X[15] + 0x49b40821) & 0xffffffff; + B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10)); + sum = (A + (C ^ (D & (B ^ C))) + X[1] + 0xf61e2562) & 0xffffffff; + A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27)); + sum = (D + (B ^ (C & (A ^ B))) + X[6] + 0xc040b340) & 0xffffffff; + D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23)); + sum = (C + (A ^ (B & (D ^ A))) + X[11] + 0x265e5a51) & 0xffffffff; + C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18)); + sum = (B + (D ^ (A & (C ^ D))) + X[0] + 0xe9b6c7aa) & 0xffffffff; + B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12)); + sum = (A + (C ^ (D & (B ^ C))) + X[5] + 0xd62f105d) & 0xffffffff; + A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27)); + sum = (D + (B ^ (C & (A ^ B))) + X[10] + 0x02441453) & 0xffffffff; + D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23)); + sum = (C + (A ^ (B & (D ^ A))) + X[15] + 0xd8a1e681) & 0xffffffff; + C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18)); + sum = (B + (D ^ (A & (C ^ D))) + X[4] + 0xe7d3fbc8) & 0xffffffff; + B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12)); + sum = (A + (C ^ (D & (B ^ C))) + X[9] + 0x21e1cde6) & 0xffffffff; + A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27)); + sum = (D + (B ^ (C & (A ^ B))) + X[14] + 0xc33707d6) & 0xffffffff; + D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23)); + sum = (C + (A ^ (B & (D ^ A))) + X[3] + 0xf4d50d87) & 0xffffffff; + C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18)); + sum = (B + (D ^ (A & (C ^ D))) + X[8] + 0x455a14ed) & 0xffffffff; + B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12)); + sum = (A + (C ^ (D & (B ^ C))) + X[13] + 0xa9e3e905) & 0xffffffff; + A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27)); + sum = (D + (B ^ (C & (A ^ B))) + X[2] + 0xfcefa3f8) & 0xffffffff; + D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23)); + sum = (C + (A ^ (B & (D ^ A))) + X[7] + 0x676f02d9) & 0xffffffff; + C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18)); + sum = (B + (D ^ (A & (C ^ D))) + X[12] + 0x8d2a4c8a) & 0xffffffff; + B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12)); + sum = (A + (B ^ C ^ D) + X[5] + 0xfffa3942) & 0xffffffff; + A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28)); + sum = (D + (A ^ B ^ C) + X[8] + 0x8771f681) & 0xffffffff; + D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21)); + sum = (C + (D ^ A ^ B) + X[11] + 0x6d9d6122) & 0xffffffff; + C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16)); + sum = (B + (C ^ D ^ A) + X[14] + 0xfde5380c) & 0xffffffff; + B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9)); + sum = (A + (B ^ C ^ D) + X[1] + 0xa4beea44) & 0xffffffff; + A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28)); + sum = (D + (A ^ B ^ C) + X[4] + 0x4bdecfa9) & 0xffffffff; + D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21)); + sum = (C + (D ^ A ^ B) + X[7] + 0xf6bb4b60) & 0xffffffff; + C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16)); + sum = (B + (C ^ D ^ A) + X[10] + 0xbebfbc70) & 0xffffffff; + B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9)); + sum = (A + (B ^ C ^ D) + X[13] + 0x289b7ec6) & 0xffffffff; + A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28)); + sum = (D + (A ^ B ^ C) + X[0] + 0xeaa127fa) & 0xffffffff; + D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21)); + sum = (C + (D ^ A ^ B) + X[3] + 0xd4ef3085) & 0xffffffff; + C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16)); + sum = (B + (C ^ D ^ A) + X[6] + 0x04881d05) & 0xffffffff; + B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9)); + sum = (A + (B ^ C ^ D) + X[9] + 0xd9d4d039) & 0xffffffff; + A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28)); + sum = (D + (A ^ B ^ C) + X[12] + 0xe6db99e5) & 0xffffffff; + D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21)); + sum = (C + (D ^ A ^ B) + X[15] + 0x1fa27cf8) & 0xffffffff; + C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16)); + sum = (B + (C ^ D ^ A) + X[2] + 0xc4ac5665) & 0xffffffff; + B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9)); + sum = (A + (C ^ (B | (~D))) + X[0] + 0xf4292244) & 0xffffffff; + A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26)); + sum = (D + (B ^ (A | (~C))) + X[7] + 0x432aff97) & 0xffffffff; + D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22)); + sum = (C + (A ^ (D | (~B))) + X[14] + 0xab9423a7) & 0xffffffff; + C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17)); + sum = (B + (D ^ (C | (~A))) + X[5] + 0xfc93a039) & 0xffffffff; + B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11)); + sum = (A + (C ^ (B | (~D))) + X[12] + 0x655b59c3) & 0xffffffff; + A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26)); + sum = (D + (B ^ (A | (~C))) + X[3] + 0x8f0ccc92) & 0xffffffff; + D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22)); + sum = (C + (A ^ (D | (~B))) + X[10] + 0xffeff47d) & 0xffffffff; + C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17)); + sum = (B + (D ^ (C | (~A))) + X[1] + 0x85845dd1) & 0xffffffff; + B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11)); + sum = (A + (C ^ (B | (~D))) + X[8] + 0x6fa87e4f) & 0xffffffff; + A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26)); + sum = (D + (B ^ (A | (~C))) + X[15] + 0xfe2ce6e0) & 0xffffffff; + D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22)); + sum = (C + (A ^ (D | (~B))) + X[6] + 0xa3014314) & 0xffffffff; + C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17)); + sum = (B + (D ^ (C | (~A))) + X[13] + 0x4e0811a1) & 0xffffffff; + B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11)); + sum = (A + (C ^ (B | (~D))) + X[4] + 0xf7537e82) & 0xffffffff; + A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26)); + sum = (D + (B ^ (A | (~C))) + X[11] + 0xbd3af235) & 0xffffffff; + D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22)); + sum = (C + (A ^ (D | (~B))) + X[2] + 0x2ad7d2bb) & 0xffffffff; + C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17)); + sum = (B + (D ^ (C | (~A))) + X[9] + 0xeb86d391) & 0xffffffff; + B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11)); + + this.chain_[0] = (this.chain_[0] + A) & 0xffffffff; + this.chain_[1] = (this.chain_[1] + B) & 0xffffffff; + this.chain_[2] = (this.chain_[2] + C) & 0xffffffff; + this.chain_[3] = (this.chain_[3] + D) & 0xffffffff; +}; + + +/** @override */ +goog.crypt.Md5.prototype.update = function(bytes, opt_length) { + if (!goog.isDef(opt_length)) { + opt_length = bytes.length; + } + var lengthMinusBlock = opt_length - this.blockSize; + + // Copy some object properties to local variables in order to save on access + // time from inside the loop (~10% speedup was observed on Chrome 11). + var block = this.block_; + var blockLength = this.blockLength_; + var i = 0; + + // The outer while loop should execute at most twice. + while (i < opt_length) { + // When we have no data in the block to top up, we can directly process the + // input buffer (assuming it contains sufficient data). This gives ~30% + // speedup on Chrome 14 and ~70% speedup on Firefox 6.0, but requires that + // the data is provided in large chunks (or in multiples of 64 bytes). + if (blockLength == 0) { + while (i <= lengthMinusBlock) { + this.compress_(bytes, i); + i += this.blockSize; + } + } + + if (goog.isString(bytes)) { + while (i < opt_length) { + block[blockLength++] = bytes.charCodeAt(i++); + if (blockLength == this.blockSize) { + this.compress_(block); + blockLength = 0; + // Jump to the outer loop so we use the full-block optimization. + break; + } + } + } else { + while (i < opt_length) { + block[blockLength++] = bytes[i++]; + if (blockLength == this.blockSize) { + this.compress_(block); + blockLength = 0; + // Jump to the outer loop so we use the full-block optimization. + break; + } + } + } + } + + this.blockLength_ = blockLength; + this.totalLength_ += opt_length; +}; + + +/** @override */ +goog.crypt.Md5.prototype.digest = function() { + // This must accommodate at least 1 padding byte (0x80), 8 bytes of + // total bitlength, and must end at a 64-byte boundary. + var pad = new Array((this.blockLength_ < 56 ? + this.blockSize : + this.blockSize * 2) - this.blockLength_); + + // Add padding: 0x80 0x00* + pad[0] = 0x80; + for (var i = 1; i < pad.length - 8; ++i) { + pad[i] = 0; + } + // Add the total number of bits, little endian 64-bit integer. + var totalBits = this.totalLength_ * 8; + for (var i = pad.length - 8; i < pad.length; ++i) { + pad[i] = totalBits & 0xff; + totalBits /= 0x100; // Don't use bit-shifting here! + } + this.update(pad); + + var digest = new Array(16); + var n = 0; + for (var i = 0; i < 4; ++i) { + for (var j = 0; j < 32; j += 8) { + digest[n++] = (this.chain_[i] >>> j) & 0xff; + } + } + return digest; +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/pbkdf2.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/pbkdf2.js b/externs/GCL/externs/goog/crypt/pbkdf2.js new file mode 100644 index 0000000..2fd1807 --- /dev/null +++ b/externs/GCL/externs/goog/crypt/pbkdf2.js @@ -0,0 +1,128 @@ +// Copyright 2012 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Implementation of PBKDF2 in JavaScript. + * @see http://en.wikipedia.org/wiki/PBKDF2 + * + * Currently we only support HMAC-SHA1 as the underlying hash function. To add a + * new hash function, add a static method similar to deriveKeyFromPasswordSha1() + * and implement the specific computeBlockCallback() using the hash function. + * + * Usage: + * var key = pbkdf2.deriveKeySha1( + * stringToByteArray('password'), stringToByteArray('salt'), 1000, 128); + * + */ + +goog.provide('goog.crypt.pbkdf2'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.crypt'); +goog.require('goog.crypt.Hmac'); +goog.require('goog.crypt.Sha1'); + + +/** + * Derives key from password using PBKDF2-SHA1 + * @param {!Array<number>} password Byte array representation of the password + * from which the key is derived. + * @param {!Array<number>} initialSalt Byte array representation of the salt. + * @param {number} iterations Number of interations when computing the key. + * @param {number} keyLength Length of the output key in bits. + * Must be multiple of 8. + * @return {!Array<number>} Byte array representation of the output key. + */ +goog.crypt.pbkdf2.deriveKeySha1 = function( + password, initialSalt, iterations, keyLength) { + // Length of the HMAC-SHA1 output in bits. + var HASH_LENGTH = 160; + + /** + * Compute each block of the key using HMAC-SHA1. + * @param {!Array<number>} index Byte array representation of the index of + * the block to be computed. + * @return {!Array<number>} Byte array representation of the output block. + */ + var computeBlock = function(index) { + // Initialize the result to be array of 0 such that its xor with the first + // block would be the first block. + var result = goog.array.repeat(0, HASH_LENGTH / 8); + // Initialize the salt of the first iteration to initialSalt || i. + var salt = initialSalt.concat(index); + var hmac = new goog.crypt.Hmac(new goog.crypt.Sha1(), password, 64); + // Compute and XOR each iteration. + for (var i = 0; i < iterations; i++) { + // The salt of the next iteration is the result of the current iteration. + salt = hmac.getHmac(salt); + result = goog.crypt.xorByteArray(result, salt); + } + return result; + }; + + return goog.crypt.pbkdf2.deriveKeyFromPassword_( + computeBlock, HASH_LENGTH, keyLength); +}; + + +/** + * Compute each block of the key using PBKDF2. + * @param {Function} computeBlock Function to compute each block of the output + * key. + * @param {number} hashLength Length of each block in bits. This is determined + * by the specific hash function used. Must be multiple of 8. + * @param {number} keyLength Length of the output key in bits. + * Must be multiple of 8. + * @return {!Array<number>} Byte array representation of the output key. + * @private + */ +goog.crypt.pbkdf2.deriveKeyFromPassword_ = + function(computeBlock, hashLength, keyLength) { + goog.asserts.assert(keyLength % 8 == 0, 'invalid output key length'); + + // Compute and concactate each block of the output key. + var numBlocks = Math.ceil(keyLength / hashLength); + goog.asserts.assert(numBlocks >= 1, 'invalid number of blocks'); + var result = []; + for (var i = 1; i <= numBlocks; i++) { + var indexBytes = goog.crypt.pbkdf2.integerToByteArray_(i); + result = result.concat(computeBlock(indexBytes)); + } + + // Trim the last block if needed. + var lastBlockSize = keyLength % hashLength; + if (lastBlockSize != 0) { + var desiredBytes = ((numBlocks - 1) * hashLength + lastBlockSize) / 8; + result.splice(desiredBytes, (hashLength - lastBlockSize) / 8); + } + return result; +}; + + +/** + * Converts an integer number to a 32-bit big endian byte array. + * @param {number} n Integer number to be converted. + * @return {!Array<number>} Byte Array representation of the 32-bit big endian + * encoding of n. + * @private + */ +goog.crypt.pbkdf2.integerToByteArray_ = function(n) { + var result = new Array(4); + result[0] = n >> 24 & 0xFF; + result[1] = n >> 16 & 0xFF; + result[2] = n >> 8 & 0xFF; + result[3] = n & 0xFF; + return result; +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/sha1.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/crypt/sha1.js b/externs/GCL/externs/goog/crypt/sha1.js new file mode 100644 index 0000000..b1a5219 --- /dev/null +++ b/externs/GCL/externs/goog/crypt/sha1.js @@ -0,0 +1,294 @@ +// Copyright 2005 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview SHA-1 cryptographic hash. + * Variable names follow the notation in FIPS PUB 180-3: + * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf. + * + * Usage: + * var sha1 = new goog.crypt.sha1(); + * sha1.update(bytes); + * var hash = sha1.digest(); + * + * Performance: + * Chrome 23: ~400 Mbit/s + * Firefox 16: ~250 Mbit/s + * + */ + +goog.provide('goog.crypt.Sha1'); + +goog.require('goog.crypt.Hash'); + + + +/** + * SHA-1 cryptographic hash constructor. + * + * The properties declared here are discussed in the above algorithm document. + * @constructor + * @extends {goog.crypt.Hash} + * @final + * @struct + */ +goog.crypt.Sha1 = function() { + goog.crypt.Sha1.base(this, 'constructor'); + + this.blockSize = 512 / 8; + + /** + * Holds the previous values of accumulated variables a-e in the compress_ + * function. + * @type {!Array<number>} + * @private + */ + this.chain_ = []; + + /** + * A buffer holding the partially computed hash result. + * @type {!Array<number>} + * @private + */ + this.buf_ = []; + + /** + * An array of 80 bytes, each a part of the message to be hashed. Referred to + * as the message schedule in the docs. + * @type {!Array<number>} + * @private + */ + this.W_ = []; + + /** + * Contains data needed to pad messages less than 64 bytes. + * @type {!Array<number>} + * @private + */ + this.pad_ = []; + + this.pad_[0] = 128; + for (var i = 1; i < this.blockSize; ++i) { + this.pad_[i] = 0; + } + + /** + * @private {number} + */ + this.inbuf_ = 0; + + /** + * @private {number} + */ + this.total_ = 0; + + this.reset(); +}; +goog.inherits(goog.crypt.Sha1, goog.crypt.Hash); + + +/** @override */ +goog.crypt.Sha1.prototype.reset = function() { + this.chain_[0] = 0x67452301; + this.chain_[1] = 0xefcdab89; + this.chain_[2] = 0x98badcfe; + this.chain_[3] = 0x10325476; + this.chain_[4] = 0xc3d2e1f0; + + this.inbuf_ = 0; + this.total_ = 0; +}; + + +/** + * Internal compress helper function. + * @param {!Array<number>|!Uint8Array|string} buf Block to compress. + * @param {number=} opt_offset Offset of the block in the buffer. + * @private + */ +goog.crypt.Sha1.prototype.compress_ = function(buf, opt_offset) { + if (!opt_offset) { + opt_offset = 0; + } + + var W = this.W_; + + // get 16 big endian words + if (goog.isString(buf)) { + for (var i = 0; i < 16; i++) { + // TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS + // have a bug that turns the post-increment ++ operator into pre-increment + // during JIT compilation. We have code that depends heavily on SHA-1 for + // correctness and which is affected by this bug, so I've removed all uses + // of post-increment ++ in which the result value is used. We can revert + // this change once the Safari bug + // (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and + // most clients have been updated. + W[i] = (buf.charCodeAt(opt_offset) << 24) | + (buf.charCodeAt(opt_offset + 1) << 16) | + (buf.charCodeAt(opt_offset + 2) << 8) | + (buf.charCodeAt(opt_offset + 3)); + opt_offset += 4; + } + } else { + for (var i = 0; i < 16; i++) { + W[i] = (buf[opt_offset] << 24) | + (buf[opt_offset + 1] << 16) | + (buf[opt_offset + 2] << 8) | + (buf[opt_offset + 3]); + opt_offset += 4; + } + } + + // expand to 80 words + for (var i = 16; i < 80; i++) { + var t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = ((t << 1) | (t >>> 31)) & 0xffffffff; + } + + var a = this.chain_[0]; + var b = this.chain_[1]; + var c = this.chain_[2]; + var d = this.chain_[3]; + var e = this.chain_[4]; + var f, k; + + // TODO(user): Try to unroll this loop to speed up the computation. + for (var i = 0; i < 80; i++) { + if (i < 40) { + if (i < 20) { + f = d ^ (b & (c ^ d)); + k = 0x5a827999; + } else { + f = b ^ c ^ d; + k = 0x6ed9eba1; + } + } else { + if (i < 60) { + f = (b & c) | (d & (b | c)); + k = 0x8f1bbcdc; + } else { + f = b ^ c ^ d; + k = 0xca62c1d6; + } + } + + var t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff; + e = d; + d = c; + c = ((b << 30) | (b >>> 2)) & 0xffffffff; + b = a; + a = t; + } + + this.chain_[0] = (this.chain_[0] + a) & 0xffffffff; + this.chain_[1] = (this.chain_[1] + b) & 0xffffffff; + this.chain_[2] = (this.chain_[2] + c) & 0xffffffff; + this.chain_[3] = (this.chain_[3] + d) & 0xffffffff; + this.chain_[4] = (this.chain_[4] + e) & 0xffffffff; +}; + + +/** @override */ +goog.crypt.Sha1.prototype.update = function(bytes, opt_length) { + // TODO(johnlenz): tighten the function signature and remove this check + if (bytes == null) { + return; + } + + if (!goog.isDef(opt_length)) { + opt_length = bytes.length; + } + + var lengthMinusBlock = opt_length - this.blockSize; + var n = 0; + // Using local instead of member variables gives ~5% speedup on Firefox 16. + var buf = this.buf_; + var inbuf = this.inbuf_; + + // The outer while loop should execute at most twice. + while (n < opt_length) { + // When we have no data in the block to top up, we can directly process the + // input buffer (assuming it contains sufficient data). This gives ~25% + // speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that + // the data is provided in large chunks (or in multiples of 64 bytes). + if (inbuf == 0) { + while (n <= lengthMinusBlock) { + this.compress_(bytes, n); + n += this.blockSize; + } + } + + if (goog.isString(bytes)) { + while (n < opt_length) { + buf[inbuf] = bytes.charCodeAt(n); + ++inbuf; + ++n; + if (inbuf == this.blockSize) { + this.compress_(buf); + inbuf = 0; + // Jump to the outer loop so we use the full-block optimization. + break; + } + } + } else { + while (n < opt_length) { + buf[inbuf] = bytes[n]; + ++inbuf; + ++n; + if (inbuf == this.blockSize) { + this.compress_(buf); + inbuf = 0; + // Jump to the outer loop so we use the full-block optimization. + break; + } + } + } + } + + this.inbuf_ = inbuf; + this.total_ += opt_length; +}; + + +/** @override */ +goog.crypt.Sha1.prototype.digest = function() { + var digest = []; + var totalBits = this.total_ * 8; + + // Add pad 0x80 0x00*. + if (this.inbuf_ < 56) { + this.update(this.pad_, 56 - this.inbuf_); + } else { + this.update(this.pad_, this.blockSize - (this.inbuf_ - 56)); + } + + // Add # bits. + for (var i = this.blockSize - 1; i >= 56; i--) { + this.buf_[i] = totalBits & 255; + totalBits /= 256; // Don't use bit-shifting here! + } + + this.compress_(this.buf_); + + var n = 0; + for (var i = 0; i < 5; i++) { + for (var j = 24; j >= 0; j -= 8) { + digest[n] = (this.chain_[i] >> j) & 255; + ++n; + } + } + + return digest; +};
