caesar-salad

API Docs for: v2.0.1
Show:

File: vigenere.js

'use strict';

const SubstitutionCipher = require('./substitution-cipher');
const Caesar = require('./caesar');
const Password = require('./password');

class Vigenere extends SubstitutionCipher {
	/**
	 * The _Vigenere Cipher_ is a polylphabetic substitution cipher rotating `A..Z` and `a..z` characters:
	 *
	 * Examples using static factory methods:
	 *
	 *     Vigenere.Cipher('abc').crypt('ABAB');   // returns: 'ACCB'
	 *
	 *     var cipher = Vigenere.Cipher('abc');
	 *     cipher.crypt('AB');                     // returns: 'AC'
	 *     cipher.crypt('AB');                     // returns: 'CB'
	 *
	 *     Vigenere.Decipher('abc').crypt('ACCB'); // returns 'ABAB'
	 *
	 * Examples using constructors:
	 *
	 *     new Vigenere([0, 1, 2]).crypt('ABAB');  // returns: 'ACCB'
	 *     new Vigenere([0,-1,-2]).crypt('ACCB');  // returns: 'ABAB'
	 *     new Vigenere([0,25,24]).crypt('ACCB');  // returns: 'ABAB'
	 *
	 * See <a class="external" href="https://en.wikipedia.org/wiki/Vigenere_cipher">Wikipedia</a> for details.
	 *
	 * @class Vigenere
	 * @extends SubstitutionCipher
	 * @constructor
	 * @param {[Number]} shiftArray The array of numbers used to rotate the charCodes `mod 26` and therefore the password of the Vigenere Cipher.
	 */
	constructor(shiftArray) {
		super();

		this._shiftArray = shiftArray.map(shift => ((shift % 26) + 26) % 26);
		this._shiftIndex = -1;

		/**
		 * Substitutes only charCodes of `A..Z` and `a..z` characters.
		 *
		 * @protected
		 * @method _substituteCharCode
		 * @param {Number} charCode the charCode to substitute.
		 * @return {Number} The substituted charCode.
		 */
		this._substituteCharCode = Caesar.prototype._substituteCharCode;
	}

	/**
	 * Return the rotated charCode.
	 *
	 * @protected
	 * @method _rotate
	 * @param {Number} charCode the charCode to rotate
	 * @return {Number} `(charCode + shift) % 26`
	 */
	_rotate(charCode) {
		this._shiftIndex = (this._shiftIndex + 1) % this._shiftArray.length;

		return (charCode + this._shiftArray[this._shiftIndex]) % 26;
	}
}

/**
 * Static factory method to create cipher instances.
 *
 * @method Cipher
 * @static
 * @param {[Number]|String} password The password to use, see {{#crossLink "Password"}}{{/crossLink}} for valid formats.
 * @return {Vigenere} The Cipher.
 */
Vigenere.Cipher = function (password) {
	return new Vigenere(new Password(password).to.shiftArray());
};

/**
 * Static factory method to create decipher instances.
 *
 * @method Decipher
 * @static
 * @param {[Number]|String} password The password to use, see {{#crossLink "Password"}}{{/crossLink}} for valid formats.
 * @return {Vigenere} The Decipher.
 */
Vigenere.Decipher = function (password) {
	return new Vigenere(new Password(password).forDecryption.to.shiftArray());
};

module.exports = Vigenere;