blob: bcc4911e9712f926a2e36535ffb02e95ac88d9f5 [file] [log] [blame]
// 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.
//
////////////////////////////////////////////////////////////////////////////////
goog.module('tink.subtle.purejs.AesCtr');
const Aes = goog.require('goog.crypt.Aes');
const Bytes = goog.require('tink.subtle.Bytes');
const Ctr = goog.require('goog.crypt.Ctr');
const IndCpaCipher = goog.require('tink.subtle.IndCpaCipher');
const Random = goog.require('tink.subtle.Random');
const SecurityException = goog.require('tink.exception.SecurityException');
const Validators = goog.require('tink.subtle.Validators');
/**
* AES block size.
*
* @const {number}
*/
const AES_BLOCK_SIZE_IN_BYTES = 16;
/**
* Implementation of AES-CTR.
*
* @implements {IndCpaCipher}
* @protected
* @final
*/
class AesCtr {
/**
* @param {!Uint8Array} key
* @param {number} ivSize the size of the IV
*/
constructor(key, ivSize) {
/** @const @private {number} */
this.ivSize_ = ivSize;
/** @const @private {Ctr} */
this.ctr_ = new Ctr(new Aes(Array.from(key)));
}
/**
* @override
*/
async encrypt(plaintext) {
Validators.requireUint8Array(plaintext);
const iv = Random.randBytes(this.ivSize_);
const counter = new Uint8Array(AES_BLOCK_SIZE_IN_BYTES);
counter.set(iv);
return Bytes.concat(
iv, new Uint8Array(this.ctr_.encrypt(plaintext, counter)));
}
/**
* @override
*/
async decrypt(ciphertext) {
Validators.requireUint8Array(ciphertext);
if (ciphertext.length < this.ivSize_) {
throw new SecurityException('ciphertext too short');
}
const counter = new Uint8Array(AES_BLOCK_SIZE_IN_BYTES);
counter.set(ciphertext.subarray(0, this.ivSize_));
return new Uint8Array(
this.ctr_.decrypt(ciphertext.subarray(this.ivSize_), counter));
}
}
exports = AesCtr;