Code Monkey home page Code Monkey logo

cowcrypt's People

Contributors

rubbingalcoholic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

cowcrypt's Issues

WebGL crypto

Check this out: https://github.com/fantapsody/webgl-aes

Might be worth building AES/Twofish in CowCrypt as GL shaders for hardware acceleration (with fallback to normal JS).

Not sure about the security implications, ie if the app <--> GL <--> video card bus is protected or not. If it is, this would give the perfect system: Javascript for high-level logic and data manipulation, and the video card for low-level bit fiddling/parallel operations.

Just a thought.

Twofish failed

Hi!

I've tested some Twofish known answers from file ecb_ival.txt and I couldn't get the results back.
I will try to see if I can solve, but maybe you could find first.

Thanks!
Weber Kai

I've tried these from libgcrypt / twofish.c:

  static  byte plaintext[16] = {
    0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E,
    0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19
  };
  static byte key[16] = {
    0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,
    0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A
  };
  static const byte ciphertext[16] = {
    0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85,
    0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3
  };
  static byte plaintext_256[16] = {
    0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F,
    0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6
  };
  static byte key_256[32] = {
    0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46,
    0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
    0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B,
    0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F
  };
  static const byte ciphertext_256[16] = {
    0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97,
    0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA
  };

Add these in test function in twofish.js:

		this._do_test(
			'9F589F5CF6122C32B6BFEC2F2AE8C35A',
			'D491DB16E7B1C39E86CB086B789F5419',
			'019F9809DE1711858FAAC3A3BA20FBC3'
		);
		this._do_test(
			'D43BB7556EA32E46F2A282B7D45B4E0D57FF739D4DC92C1BD7FC01700CC8216F',
			'90AFE91BB288544F2C32DC239B2635E6',
			'6CB4561C40BF0A9705931CB6D408E7FA'
		);

CTR mode

Hi!

Thanks for your work! It's great!

I think I've implemented CTR mode at block_cipher.js.
I've created a NoPadding pad mode, and "keep_size_mode" and "original_size" for truncating text with this CTR mode.

Here it goes...

Thank you!
Weber Kai

/*
 *	Symmetric block cipher support classes
 *	Copyright (c) 2013, Jeff Lyon. (http://rubbingalcoholic.com)
 * 
 *	Licensed under The MIT License. (http://www.opensource.org/licenses/mit-license.php)
 *	Redistributions of files must retain the above copyright notice.
 */
 /**
 *	@abstract
 *	@class
 *	@classdesc		Abstract class which provides base functionality used by all symmetric block cipher subclasses
 *	@desc			NOTE: you can't instantiate this class directly. Instead, create instances of a subclass, such as {@link AES} or {@link Twofish}.
 *	@requires		convert
 */
var BlockCipher = new Class(
/** @lends BlockCipher.prototype */
{
	/**
	 *	The block cipher mode of operation (see {@link https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation})
	 *	@type {BlockCipherMode}
	 *	@private
	 */
	block_mode: 	null,

	/**
	 *	The block byte padding mode (see {@link http://en.wikipedia.org/wiki/Padding_%28cryptography%29})
	 *	@type {PaddingMode}
	 *	@private
	 */
	pad_mode: 		null,

	/**
	 *	Try to keep the original size mode. Truncate or ciphertext stealing (see {@link https://en.wikipedia.org/wiki/Ciphertext_stealing})
	 *  @type {boolean}
	 *	@private
	 */
	keep_size_mode: 		false,

	/**
	 *	Original length for use with keep the original size mode
	 *  @type {numeric}
	 *	@private
	 */
	original_length: 		null,
	
	/**
	 *	Initial vector for non-ECB block cipher modes
	 *	@private
	 */
	iv: 			'',

	/**
	 *	Passphrase, stored temporarily before key derivation
	 *	@private
	 */
	passphrase: 	'',

	/**
	 *	Salt used for passphrase based key derivation
	 *	@private
	 */
	salt: 			'',

	/**
	 *	Toggles OpenSSL mode. 
	 *	@private
	 */
	openssl_mode: 	false,

	/**
	 *	Turn this on to enable the {@link BlockCipher#debug_write} method to log debug output to the console.
	 *
	 *	@type {Boolean}
	 *  @default false
	 */
	debug_mode: true,

	/**
	 *	Invoked during subclass initialization. All properties needed to initialize the class must be passed in.
	 *
	 *	@param {Object} data									A list of properties used to initialize the class.
	 *	@param {string} [data.key]								A binary string containing the symmetric key. Required if a passphrase is not specified.
	 *															Must match a key length supported by the subclass.
	 *	@param {BlockCipherMode} [data.block_mode={@link CBC}]	The block cipher mode of operation to use for *cryption
	 *	@param {PaddingMode} [data.pad_mode={@link NoPadding}]	The block byte padding mode
	 *	@param {string} [data.passphrase]						A passphrase to derive a key from. Required if a key is not explicitly specified.
	 *	@param {string} [data.salt]								A binary string containing the cryptographic salt used for key derivation.
	 *	@param {boolean} [data.openssl_mode=false]				Toggles OpenSSL interoperability mode. This prepends salt data to the encryption output, and
	 *															uses the prepended salt data during decryption to derive a key (in combination with a
	 *															passphrase), if needed.
	 *	@return {BlockCipher}
	 */
	initialize: function(data)
	{
		data || (data = {});
		
		for (var attr in data)
			this[attr] = data[attr];

		if (!data.block_mode)
			this.block_mode = CBC;

		if (!data.pad_mode)
			this.pad_mode = NoPadding;

		if (data.passphrase && this.openssl_mode == false)
			this._derive_key_from_passphrase();

		return this;
	},

	/**
	 *	Encrypts a string using the padding and block cipher mode of operation specificed on initialization.
	 *
	 *	@param {String} plaintext	An ASCII string to encrypt. Can be binary or plaintext.
	 *								For plaintext, be sure to use {@link convert.utf8.encode} to encode any UTF characters.
	 *	@return {String}			Decrypted data
	 */
	encrypt: function(plaintext)
	{
		if (this.openssl_mode && this.get_key().length == 0)
			this._derive_key_from_passphrase();

		if (this.keep_size_mode) {
			this.original_length = plaintext.length;
		}
		
		plaintext		= new this.pad_mode({ cipher: this }).do_pad(plaintext);

		var plaintext 	= convert.to_words(plaintext);
		var operator	= new this.block_mode({ cipher: this });
		var ciphertext	= operator.encrypt_blocks(plaintext);

		ciphertext		= convert.words_to_binstring(ciphertext);
		
		if (this.keep_size_mode) {
			ciphertext = ciphertext.substring(0, this.original_length);
		}
		
		if (this.openssl_mode && this.get_salt())
			ciphertext	= 'Salted__' + this.get_salt() + ciphertext;

		return ciphertext;
	},

	/**
	 *	Decrypts a string.
	 *
	 *	@param {String} ciphertext	An ASCII string to decrypt.
	 *	@return {String}			Encrypted data
	 */
	decrypt: function(ciphertext)
	{
		if (this.keep_size_mode) {
			this.original_length = ciphertext.length;
		}
		
		if (this.openssl_mode && ciphertext.substr(0, 8) == 'Salted__')
		{
			if (this.get_key().length == 0)
			{
				this.salt	= ciphertext.substr(8, 8);
				this._derive_key_from_passphrase();
			}
			ciphertext		= ciphertext.substr(16);
		}

		var ciphertext 		= convert.to_words(ciphertext);
		var operator		= new this.block_mode({ cipher: this });
		var plaintext		= convert.words_to_binstring(operator.decrypt_blocks(ciphertext));

		plaintext			= new this.pad_mode({ cipher: this }).undo_pad(plaintext);

		if (this.keep_size_mode) {
			plaintext = plaintext.substring(0, this.original_length);
		}

		return plaintext;
	},

	/**
	 *	Gets the salt used for any passphrase-based key derivation.
	 *	@return {String}
	 */
	get_salt: function()
	{
		return this.salt;
	},

	/**
	 *	Writes debug information to the console if {@link BlockCipher#debug_mode} is turned on.
	 *	@param {...mixed} arguments The variables to write to console
	 */
	debug_write: function()
	{
		if (this.debug_mode) console.log.apply(console, arguments);
	},

	/**
	 *	Derives a key from a passphrase.
	 *	@private
	 */
	_derive_key_from_passphrase: function()
	{
		var key_bytes		= (this.get_key_length() / 8);
		var block_bytes		= (this.get_block_size() / 8);

		if (this.openssl_mode)
		{
			if (!this.get_salt())
				this.salt	= this._random_salt();

			var key			= new EVPKDF({key_size: (key_bytes+block_bytes)}).compute(this.passphrase, this.get_salt().substr(0, 8));
		}
		else
			var key			= new PBKDF2({key_size: (key_bytes+block_bytes)}).compute(this.passphrase, this.get_salt());
		
		this.iv				= key.substr(key_bytes);
		this.passphrase		= '';

		this.set_key(key.substr(0, key_bytes));
	},

	/**
	 *	Generates a random salt
	 *	@private
	 */
	_random_salt: function()
	{
		var rb = function () { return String.fromCharCode(Math.floor(Math.random() * 256)); }
		return rb() + rb() + rb() + rb() + rb() + rb() + rb() + rb();
	}
});

/**
 *	@abstract
 *	@class
 *	@classdesc		Abstract class which provides base functionality for block cipher mode operator subclasses
 *	@desc			NOTE: you can't instantiate this class directly. Instead, create instances of a subclass, such as {@link CBC} or {@link ECB}.
 *	@requires		convert
 */
var BlockCipherMode = new Class(
/** @lends BlockCipherMode.prototype */
{
	/**
     *	Stores a reference to the BlockCipher subclass instance used for *cryption
     *	@type {BlockCipher}
     *	@private
     */
	cipher: null,

	/**
	 *	Invoked during subclass initialization. All properties needed to initialize the class must be passed in.
	 *
	 *	@param {Object} data				A list of properties used to initialize the class.
	 *	@param {BlockCipher} data.cipher	A reference to a BlockCipher subclass instance. Used to actually *crypt any given block.
	 *	@param {string} [data.iv]			ASCII string containing Initial Vector (IV). Not required for {@link ECB}
	 *	@return {BlockCipherMode}
	 */
	initialize: function(data)
	{
		for (var attr in data)
			this[attr] = data[attr];

		return this;
	},

	/**
	 *	Invoked during subclass initialize when an Initial Vector is required.
	 *	Converts any supplied Initial Vector to an array of 32-bit words and does a length check.
	 *	@private
	 *	@throws Throws an error if the Initial Vector length doesn't match the block length.
	 */
	init_iv: function()
	{
		var iv = convert.to_words(this.cipher.iv);

		if (iv.length != this.get_words_per_block())
			throw new Error('Initial vector size must match block size!');

		this.iv = iv;
	},

	/**
	 *	Convenience function to get the number of 32-bit words required for each block
	 *	@return {number}
	 */
	get_words_per_block: function()
	{
		return this.cipher.get_block_size() / 32;
	},

	/**
	 *	XORs two blocks together. (A block is an array of 32-bit words of the correct length)
	 *	@private
	 *	@param {Array} block1	The first block
	 *	@param {Array} block2	The second block
	 *	@return {Array}			The result of XOR'ing the two blocks together
	 */
	xor_block: function(block1, block2)
	{
		for (var i=0; i < block1.length; i++) block1[i] ^= block2[i];		
		return block1;
	}

});

/**
 *	@class
 *	@classdesc				Implements ECB block cipher mode. Used internally during symmetric *cryption.
 *	@extends				BlockCipherMode
 *	@requires				convert
 *
 *	@desc					Creates a new ECB block cipher mode instance
 *	@param {Object} data	Initialization options for the class, passed automatically into {@link ECB#initialize}
 */
var ECB = new Class(
/** @lends ECB.prototype */
{
	
	Extends: BlockCipherMode,

	/**
	 *	Called automatically on class instantiation.
	 *	Invokes {@link BlockCipherMode#initialize}.
	 *
	 *	@override
	 *	@param {Object} data See {@link BlockCipherMode#initialize} for a list of supported properties.
	 *	@return {ECB}
	 */
	initialize: function(data)
	{
		this.parent(data);
		return this;
	},

	/**
	 *	Encrypts blocks.
	 *
	 *	@param {Array} words	An array of 32-bit words whose length must be an integer multiple of {@link ECB#get_words_per_block}
	 *	@return {Array}			Encrypted blocks
	 */
	encrypt_blocks: function(words)
	{
		var ciphertext 		= [];
		var words_per_block	= this.get_words_per_block();

		for (var i = 0; i < words.length; i += words_per_block)
		{
			var block = words.slice(i, i+words_per_block);
			ciphertext = ciphertext.concat(this.cipher.block_encrypt(block));
		}

		return ciphertext;
	},

	/**
	 *	Decrypt blocks.
	 *
	 *	@param {Array} words	An array of 32-bit words whose length must be an integer multiple of {@link ECB#get_words_per_block}
	 *	@return {Array}			Decrypted blocks
	 */
	decrypt_blocks: function(words)
	{
		var plaintext 		= [];
		var words_per_block	= this.get_words_per_block();

		for (var i = 0; i < words.length; i += words_per_block)
		{
			var block = words.slice(i, i+words_per_block);
			plaintext = plaintext.concat(this.cipher.block_decrypt(block));
		}
	
		console.log(plaintext);
		return plaintext;
	},
	
});

/**
 *	@class
 *	@classdesc				Implements CBC block cipher mode. Used internally during symmetric *cryption.
 *	@extends				BlockCipherMode
 *	@requires				convert
 *
 *	@desc					Creates a new CBC block cipher mode instance
 *	@param {Object} data	Initialization options for the class, passed automatically into {@link CBC#initialize}
 */
var CBC = new Class(
/** @lends CBC.prototype */
{
	Extends: BlockCipherMode,
	
	/**
	 *	Array of 32-bit words for the Initial Vector (IV)
	 *	@private
	 */
	iv: [],

	/**
	 *	Called automatically on class instantiation.
	 *	Invokes {@link BlockCipherMode#initialize} before handling class-specific functionality.
	 *
	 *	@override
	 *	@param {Object} data See {@link BlockCipherMode#initialize} for a list of supported properties.
	 *	@return {CBC}
	 */
	initialize: function(data)
	{
		this.parent(data);
		this.init_iv();		
		return this;
	},

	/**
	 *	Encrypts blocks.
	 *
	 *	@param {Array} words	An array of 32-bit words whose length must be an integer multiple of {@link CBC#get_words_per_block}
	 *	@return {Array}			Encrypted blocks
	 */
	encrypt_blocks: function(words)
	{
		var ciphertext 		= [];
		var words_per_block	= this.get_words_per_block();
		var _prev_block		= this.iv;

		for (var i = 0; i < words.length; i += words_per_block)
		{
			var block			= words.slice(i, i+words_per_block);
			var xor_block		= this.xor_block(block, _prev_block);
			var cipher_block	= this.cipher.block_encrypt(xor_block)
			ciphertext 			= ciphertext.concat(cipher_block);
			_prev_block			= cipher_block;
		}

		return ciphertext;
	},

	/**
	 *	Decrypt blocks.
	 *
	 *	@param {Array} words	An array of 32-bit words whose length must be an integer multiple of {@link CBC#get_words_per_block}
	 *	@return {Array}			Decrypted blocks
	 */
	decrypt_blocks: function(words)
	{
		var plaintext 		= [];
		var words_per_block	= this.get_words_per_block();
		var _prev_block		= this.iv;

		for (var i = 0; i < words.length; i += words_per_block)
		{
			var block 			= words.slice(i, i+words_per_block);
			var decrypted 		= this.cipher.block_decrypt(block);
			var xor_decrypted	= this.xor_block(decrypted, _prev_block);
			plaintext 			= plaintext.concat(xor_decrypted);
			_prev_block			= block;
		}

		return plaintext;
	},
	
});

/**
 *	@class
 *	@classdesc				Implements CFB block cipher mode. Used internally during symmetric *cryption.
 *	@extends				BlockCipherMode
 *	@requires				convert
 *
 *	@desc					Creates a new CFB block cipher mode instance
 *	@param {Object} data	Initialization options for the class, passed automatically into {@link CFB#initialize}
 */
var CFB = new Class(
/** @lends CFB.prototype */
{
	
	Extends: BlockCipherMode,

	/**
	 *	Array of 32-bit words for the Initial Vector (IV)
	 *	@private
	 */
	iv: [],

	/**
	 *	Called automatically on class instantiation.
	 *	Invokes {@link BlockCipherMode#initialize} before handling class-specific functionality.
	 *
	 *	@override
	 *	@param {Object} data See {@link BlockCipherMode#initialize} for a list of supported properties.
	 *	@return {CFB}
	 */
	initialize: function(data)
	{
		this.parent(data);
		this.init_iv();
		return this;
	},

	/**
	 *	Encrypts blocks.
	 *
	 *	@param {Array} words	An array of 32-bit words whose length must be an integer multiple of {@link CFB#get_words_per_block}
	 *	@return {Array}			Encrypted blocks
	 */
	encrypt_blocks: function(words)
	{
		var ciphertext 		= [];
		var words_per_block	= this.get_words_per_block();
		var _prev_block		= this.iv;

		for (var i = 0; i < words.length; i += words_per_block)
		{
			var cipher_block	= this.cipher.block_encrypt(_prev_block)
			var block			= words.slice(i, i+words_per_block);
			var xor_block		= this.xor_block(block, cipher_block);
			ciphertext 			= ciphertext.concat(xor_block);
			_prev_block			= xor_block;
		}

		return ciphertext;
	},

	/**
	 *	Decrypt blocks.
	 *
	 *	@param {Array} words	An array of 32-bit words whose length must be an integer multiple of {@link CFB#get_words_per_block}
	 *	@return {Array}			Decrypted blocks
	 */
	decrypt_blocks: function(words)
	{
		var plaintext 		= [];
		var words_per_block	= this.get_words_per_block();
		var _prev_block		= this.iv;

		for (var i = 0; i < words.length; i += words_per_block)
		{
			var cipher_block	= this.cipher.block_encrypt(_prev_block)
			var block 			= words.slice(i, i+words_per_block);
			var xor_decrypted	= this.xor_block(cipher_block, block);
			plaintext 			= plaintext.concat(xor_decrypted);
			_prev_block			= block;
		}

		return plaintext;
	},
});

/**
 *	@class
 *	@classdesc				Implements CTR block cipher mode. Used internally during symmetric *cryption.
 *	@extends				BlockCipherMode
 *	@requires				convert
 *
 *	@desc					Creates a new CTR block cipher mode instance
 *	@param {Object} data	Initialization options for the class, passed automatically into {@link CTR#initialize}
 */
var CTR = new Class(
/** @lends CTR.prototype */
{
	
	Extends: BlockCipherMode,

	/**
	 *	Array of 32-bit words for the counter (counter)
	 *	@private
	 */
	counter: [],

	/**
	 *	Called automatically on class instantiation.
	 *	Invokes {@link BlockCipherMode#initialize} before handling class-specific functionality.
	 *
	 *	@override
	 *	@param {Object} data See {@link BlockCipherMode#initialize} for a list of supported properties.
	 *	@return {CTR}
	 */
	initialize: function(data)
	{
		this.parent(data);
		this.init_counter();
		return this;
	},

	/**
	 *	Invoked during subclass initialize.
	 *	Converts number 0 to an array of 32-bit words and does a length check.
	 *	@private
	 *	@throws Throws an error if the counter length doesn't match 128 bits size.
	 */
	init_counter: function()
	{
		var counter = convert.to_words(this.cipher.counter, null);

		if (counter.length != 4)
			throw new Error('Counter size must match 128 bits!');

		this.counter = counter;
	},
	
	/**
	 *	Invoked during encryption to increase counter for next block.
	 *	@private
	 *	@throws Throws an error if overflow.
	 */
	increase_counter: function()
	{
		var counter = convert.words_to_bytes(this.counter);
		for (var i = counter.length; i > 0 ; i--) {
			counter[i-1]++;
			if (counter[i-1] != 0)
				break;
			if (i == 1)
				throw new Error('Counter overflowed!');
		}

		this.counter = convert.to_words(counter);
	},
  	
	/**
	 *	Encrypts blocks.
	 *
	 *	@param {Array} words	An array of 32-bit words whose length must be an integer multiple of {@link CTR#get_words_per_block}
	 *	@return {Array}			Encrypted blocks
	 */
	encrypt_blocks: function(words)
	{
		var ciphertext 		= [];
		var words_per_block	= this.get_words_per_block();
		var plaintext_size_bytes = this.cipher.original_length;
		var block_size_bytes = this.cipher.get_block_size() / 8;
		var last_block_size_bytes = plaintext_size_bytes % block_size_bytes == 0 ? 0 : plaintext_size_bytes % block_size_bytes;
		//console.log(last_block_size_bytes);
	
		for (var i = 0; i < words.length; i += words_per_block)
		{
			var cipher_block	= this.cipher.block_encrypt(this.counter)
			this.increase_counter();
			var block			= words.slice(i, i+words_per_block);
			var xor_block		= this.xor_block(block, cipher_block);
			ciphertext 			= ciphertext.concat(xor_block);
		}

		return ciphertext;
	},

	/**
	 *	Decrypt blocks.
	 *
	 *	@param {Array} words	An array of 32-bit words whose length must be an integer multiple of {@link CTR#get_words_per_block}
	 *	@return {Array}			Decrypted blocks
	 */
	decrypt_blocks: function(words)
	{
		var plaintext 		= [];
		var words_per_block	= this.get_words_per_block();
		var plaintext_size_bytes = this.cipher.original_length;
		var block_size_bytes = this.cipher.get_block_size() / 8;
		var last_block_size_bytes = plaintext_size_bytes % block_size_bytes == 0 ? 0 : plaintext_size_bytes % block_size_bytes;

		for (var i = 0; i < words.length; i += words_per_block)
		{
			var cipher_block	= this.cipher.block_encrypt(this.counter)
			this.increase_counter();
			var block 			= words.slice(i, i+words_per_block);
			var xor_decrypted	= this.xor_block(cipher_block, block);
			plaintext 			= plaintext.concat(xor_decrypted);
		}

		return plaintext;
	},
});

/**
 *	@abstract
 *	@class
 *	@classdesc		Abstract class which provides base functionality for byte padding subclasses
 *	@desc			NOTE: you can't instantiate this class directly. Instead, create instances of a subclass, such as {@link ZeroPadding} or {@link PKCS7}.
 */
var PaddingMode = new Class(
/** @lends PaddingMode.prototype */
{
	/**
     *	Stores a reference to the BlockCipher subclass instance (used to get data about the block size)
     *	@type {BlockCipher}
     *	@private
     */
	cipher: null,

	/**
	 *	Invoked during subclass instantiation. All properties needed to initialize the class must be passed in.
	 *
	 *	@param {Object} data				A list of properties used to initialize the class.
	 *	@param {BlockCipher} data.cipher	A reference to a BlockCipher subclass instance. Used to get information about the block size.
	 *	@return {PaddingMode}
	 */
	initialize: function(data)
	{
		for (var attr in data)
			this[attr] = data[attr];

		return this;
	}
});

/**
 *	@class
 *	@classdesc				Implements Zero Padding functionality. Data is padded to the correct block length multiple with zero bytes.
 *	@extends				PaddingMode
 *
 *	@desc					Creates a new ZeroPadding padding mode instance
 *	@param {Object} data	Initialization options for the class, passed automatically into {@link ZeroPadding#initialize}
 */
var ZeroPadding = new Class(
/** @lends ZeroPadding.prototype */
{
	Extends: PaddingMode,

	/**
	 *	Perform the padding on the data.
	 *
	 *	@param {string} data	A binary data string (ASCII)
	 *	@return {string} 		Padded data
	 */
	do_pad: function(data)
	{
		if ((data.length * 8) % this.cipher.get_block_size() != 0)
			for (var i=0; data.length % (this.cipher.get_block_size() / 8) != 0; i++)
				data += String.fromCharCode(0);

		return data;
	},

	/**
	 *	There is no safe way to undo zero padding. Simply returns the input string.
	 *
	 *	@param {string} data	A binary data string (ASCII)
	 *	@return {string} 		The exact same string that was passed in.
	 */
	undo_pad: function(data)
	{
		return data;
	}
});

/**
 *	@class
 *	@classdesc				Implements ANSI X.923 Padding functionality.
 *							Data is padded with zeros until the last byte, which is then set to the number of padded bytes.
 *							If the data length is already a "clean" multiple of the block length, it is still padded out
 *							to another block, so we can safely undo the padding afterwards.
 *	@extends				PaddingMode
 *
 *	@desc					Creates a new AnsiX923 padding mode instance
 *	@param {Object} data	Initialization options for the class, passed automatically into {@link AnsiX923#initialize}
 */
var AnsiX923 = new Class(
/** @lends AnsiX923.prototype */
{
	Extends: PaddingMode,

	/**
	 *	Perform the padding on the data.
	 *
	 *	@param {string} data	A binary data string (ASCII)
	 *	@return {string} 		Padded data
	 */
	do_pad: function(data)
	{
		// Pad the block out with zeros
		for (var i=0; i == 0 || data.length % (this.cipher.get_block_size() / 8) != 0; i++)
			data += String.fromCharCode(0);

		// Slice off the last byte and replace with our count
		data = data.substr(0, data.length - 1);
		data += String.fromCharCode(i);

		return data;
	},

	/**
	 *	Undo padding on padded data.
	 *
	 *	@param {string} data	A binary data string (ASCII)
	 *	@return {string} 		A binary string with the padding data stripped off the end.
	 */
	undo_pad: function(data)
	{
		var pad_length = data.charCodeAt(data.length-1);
		return data.substr(0, data.length - pad_length);
	}
});

/**
 *	@class
 *	@classdesc				Implements PKCS7 Padding functionality.
 *							The byte value we pad with is the number total number of bytes being padded onto the data.
 *							If the data length is already a "clean" multiple of the block length, it is still padded out
 *							to another block, so we can safely undo the padding afterwards.
 *	@extends				PaddingMode
 *
 *	@desc					Creates a new PKCS7 padding mode instance
 *	@param {Object} data	Initialization options for the class, passed automatically into {@link PKCS7#initialize}
 */
var PKCS7 = new Class(
/** @lends PKCS7.prototype */
{
	Extends: PaddingMode,

	/**
	 *	Perform the padding on the data.
	 *
	 *	@param {string} data	A binary data string (ASCII)
	 *	@return {string} 		Padded data
	 */
	do_pad: function(data)
	{
		var block_bytes	= (this.cipher.get_block_size() / 8);

		var pad_count	= data.length % block_bytes != 0 ? block_bytes - (data.length % block_bytes) : block_bytes;

		for (var i=0; i == 0 || data.length % (this.cipher.get_block_size() / 8) != 0; i++)
			data += String.fromCharCode(pad_count);

		return data;
	},

	/**
	 *	Undo padding on padded data.
	 *
	 *	@param {string} data	A binary data string (ASCII)
	 *	@return {string} 		A binary string with the padding data stripped off the end.
	 */
	undo_pad: function(data)
	{
		var pad_length = data.charCodeAt(data.length-1);
		return data.substr(0, data.length - pad_length);
	}
});

/**
 *	@class
 *	@classdesc				Implements No Padding functionality.
 *	@extends				PaddingMode
 *
 *	@desc					Creates a new NoPadding padding mode instance
 *	@param {Object} data	Initialization options for the class, passed automatically into {@link NoPadding#initialize}
 */
var NoPadding = new Class(
/** @lends NoPadding.prototype */
{
	Extends: PaddingMode,

	/**
	 *	Perform the padding on the data.
	 *
	 *	@param {string} data	A binary data string (ASCII)
	 *	@return {string} 		Padded data
	 */
	do_pad: function(data)
	{
		return data;
	},

	/**
	 *	Undo padding on padded data.
	 *
	 *	@param {string} data	A binary data string (ASCII)
	 *	@return {string} 		A binary string with the padding data stripped off the end.
	 */
	undo_pad: function(data)
	{
		return data;
	}
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.