Path: blob/trunk/third_party/closure/goog/crypt/ctr.js
2868 views
// Copyright 2016 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314goog.provide('goog.crypt.Ctr');1516goog.require('goog.array');17goog.require('goog.asserts');18goog.require('goog.crypt');1920/**21* Implementation of Ctr mode for block ciphers. See22* http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation23* #Cipher-block_chaining_.28Ctr.29. for an overview, and24* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf25* for the spec.26*27* @param {!goog.crypt.BlockCipher} cipher The block cipher to use.28* @constructor29* @final30* @struct31*/32goog.crypt.Ctr = function(cipher) {3334/**35* Block cipher.36* @type {!goog.crypt.BlockCipher}37* @private38*/39this.cipher_ = cipher;40};4142/**43* Encrypts a message.44*45* @param {!Array<number>|!Uint8Array} plainText Message to encrypt. An array of46* bytes. The length does not have to be a multiple of the blocksize.47* @param {!Array<number>|!Uint8Array} initialVector Initial vector for the Ctr48* mode. An array of bytes with the same length as the block size, that49* should be not reused when using the same key.50* @return {!Array<number>} Encrypted message.51*/52goog.crypt.Ctr.prototype.encrypt = function(plainText, initialVector) {5354goog.asserts.assert(55initialVector.length == this.cipher_.BLOCK_SIZE,56'Initial vector must be size of one block.');5758// Copy the IV, so it's not modified.59var counter = goog.array.clone(initialVector);6061var keyStreamBlock = [];62var encryptedArray = [];63var plainTextBlock = [];6465while (encryptedArray.length < plainText.length) {66keyStreamBlock = this.cipher_.encrypt(counter);67goog.crypt.Ctr.incrementBigEndianCounter_(counter);6869plainTextBlock = goog.array.slice(70plainText, encryptedArray.length,71encryptedArray.length + this.cipher_.BLOCK_SIZE);72goog.array.extend(73encryptedArray,74goog.crypt.xorByteArray(75plainTextBlock,76goog.array.slice(keyStreamBlock, 0, plainTextBlock.length)));77}7879return encryptedArray;80};818283/**84* Decrypts a message. In CTR, this is the same as encrypting.85*86* @param {!Array<number>|!Uint8Array} cipherText Message to decrypt. The length87* does not have to be a multiple of the blocksize.88* @param {!Array<number>|!Uint8Array} initialVector Initial vector for the Ctr89* mode. An array of bytes with the same length as the block size.90* @return {!Array<number>} Decrypted message.91*/92goog.crypt.Ctr.prototype.decrypt = goog.crypt.Ctr.prototype.encrypt;9394/**95* Increments the big-endian integer represented in counter in-place.96*97* @param {!Array<number>|!Uint8Array} counter The array of bytes to modify.98* @private99*/100goog.crypt.Ctr.incrementBigEndianCounter_ = function(counter) {101for (var i = counter.length - 1; i >= 0; i--) {102var currentByte = counter[i];103currentByte = (currentByte + 1) & 0xFF; // Allow wrapping around.104counter[i] = currentByte;105if (currentByte != 0) {106// This iteration hasn't wrapped around, which means there is107// no carry to add to the next byte.108return;109} // else, repeat with next byte.110}111};112113114