<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: crypto/cipher/twofish.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: crypto/cipher/twofish.js</h1> <section> <article> <pre class="prettyprint source"><code>/* Modified by Recurity Labs GmbH * * Cipher.js * A block-cipher algorithm implementation on JavaScript * See Cipher.readme.txt for further information. * * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] * This script file is distributed under the LGPL * * ACKNOWLEDGMENT * * The main subroutines are written by Michiel van Everdingen. * * Michiel van Everdingen * http://home.versatel.nl/MAvanEverdingen/index.html * * All rights for these routines are reserved to Michiel van Everdingen. * */ /** @module crypto/cipher/twofish */ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Math //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var MAXINT = 0xFFFFFFFF; function rotb(b, n) { return (b << n | b >>> (8 - n)) & 0xFF; } function rotw(w, n) { return (w << n | w >>> (32 - n)) & MAXINT; } function getW(a, i) { return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; } function setW(a, i, w) { a.splice(i, 4, w & 0xFF, (w >>> 8) & 0xFF, (w >>> 16) & 0xFF, (w >>> 24) & 0xFF); } function setWInv(a, i, w) { a.splice(i, 4, (w >>> 24) & 0xFF, (w >>> 16) & 0xFF, (w >>> 8) & 0xFF, w & 0xFF); } function getB(x, n) { return (x >>> (n * 8)) & 0xFF; } function getNrBits(i) { var n = 0; while (i > 0) { n++; i >>>= 1; } return n; } function getMask(n) { return (1 << n) - 1; } //added 2008/11/13 XXX MUST USE ONE-WAY HASH FUNCTION FOR SECURITY REASON function randByte() { return Math.floor(Math.random() * 256); } // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Twofish // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function createTwofish() { // var keyBytes = null; var dataBytes = null; var dataOffset = -1; // var dataLength = -1; var algorithmName = null; // var idx2 = -1; // algorithmName = "twofish"; var tfsKey = []; var tfsM = [ [], [], [], [] ]; function tfsInit(key) { keyBytes = key; var i, a, b, c, d, meKey = [], moKey = [], inKey = []; var kLen; var sKey = []; var f01, f5b, fef; var q0 = [ [8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5] ]; var q1 = [ [14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8] ]; var q2 = [ [11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15] ]; var q3 = [ [13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10] ]; var ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; var ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; var q = [ [], [] ]; var m = [ [], [], [], [] ]; function ffm5b(x) { return x ^ (x >> 2) ^ [0, 90, 180, 238][x & 3]; } function ffmEf(x) { return x ^ (x >> 1) ^ (x >> 2) ^ [0, 238, 180, 90][x & 3]; } function mdsRem(p, q) { var i, t, u; for (i = 0; i < 8; i++) { t = q >>> 24; q = ((q << 8) & MAXINT) | p >>> 24; p = (p << 8) & MAXINT; u = t << 1; if (t & 128) { u ^= 333; } q ^= t ^ (u << 16); u ^= t >>> 1; if (t & 1) { u ^= 166; } q ^= u << 24 | u << 8; } return q; } function qp(n, x) { var a, b, c, d; a = x >> 4; b = x & 15; c = q0[n][a ^ b]; d = q1[n][ror4[b] ^ ashx[a]]; return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; } function hFun(x, key) { var a = getB(x, 0), b = getB(x, 1), c = getB(x, 2), d = getB(x, 3); switch (kLen) { case 4: a = q[1][a] ^ getB(key[3], 0); b = q[0][b] ^ getB(key[3], 1); c = q[0][c] ^ getB(key[3], 2); d = q[1][d] ^ getB(key[3], 3); case 3: a = q[1][a] ^ getB(key[2], 0); b = q[1][b] ^ getB(key[2], 1); c = q[0][c] ^ getB(key[2], 2); d = q[0][d] ^ getB(key[2], 3); case 2: a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); } return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; } keyBytes = keyBytes.slice(0, 32); i = keyBytes.length; while (i != 16 && i != 24 && i != 32) keyBytes[i++] = 0; for (i = 0; i < keyBytes.length; i += 4) { inKey[i >> 2] = getW(keyBytes, i); } for (i = 0; i < 256; i++) { q[0][i] = qp(0, i); q[1][i] = qp(1, i); } for (i = 0; i < 256; i++) { f01 = q[1][i]; f5b = ffm5b(f01); fef = ffmEf(f01); m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); f01 = q[0][i]; f5b = ffm5b(f01); fef = ffmEf(f01); m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); } kLen = inKey.length / 2; for (i = 0; i < kLen; i++) { a = inKey[i + i]; meKey[i] = a; b = inKey[i + i + 1]; moKey[i] = b; sKey[kLen - i - 1] = mdsRem(a, b); } for (i = 0; i < 40; i += 2) { a = 0x1010101 * i; b = a + 0x1010101; a = hFun(a, meKey); b = rotw(hFun(b, moKey), 8); tfsKey[i] = (a + b) & MAXINT; tfsKey[i + 1] = rotw(a + 2 * b, 9); } for (i = 0; i < 256; i++) { a = b = c = d = i; switch (kLen) { case 4: a = q[1][a] ^ getB(sKey[3], 0); b = q[0][b] ^ getB(sKey[3], 1); c = q[0][c] ^ getB(sKey[3], 2); d = q[1][d] ^ getB(sKey[3], 3); case 3: a = q[1][a] ^ getB(sKey[2], 0); b = q[1][b] ^ getB(sKey[2], 1); c = q[0][c] ^ getB(sKey[2], 2); d = q[0][d] ^ getB(sKey[2], 3); case 2: tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; } } } function tfsG0(x) { return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; } function tfsG1(x) { return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; } function tfsFrnd(r, blk) { var a = tfsG0(blk[0]); var b = tfsG1(blk[1]); blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31); blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT; a = tfsG0(blk[2]); b = tfsG1(blk[3]); blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31); blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT; } function tfsIrnd(i, blk) { var a = tfsG0(blk[0]); var b = tfsG1(blk[1]); blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT; blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31); a = tfsG0(blk[2]); b = tfsG1(blk[3]); blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT; blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31); } function tfsClose() { tfsKey = []; tfsM = [ [], [], [], [] ]; } function tfsEncrypt(data, offset) { dataBytes = data; dataOffset = offset; var blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], getW(dataBytes, dataOffset + 4) ^ tfsKey[1], getW(dataBytes, dataOffset + 8) ^ tfsKey[2], getW(dataBytes, dataOffset + 12) ^ tfsKey[3] ]; for (var j = 0; j < 8; j++) { tfsFrnd(j, blk); } setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); dataOffset += 16; return dataBytes; } function tfsDecrypt(data, offset) { dataBytes = data; dataOffset = offset; var blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], getW(dataBytes, dataOffset + 4) ^ tfsKey[5], getW(dataBytes, dataOffset + 8) ^ tfsKey[6], getW(dataBytes, dataOffset + 12) ^ tfsKey[7] ]; for (var j = 7; j >= 0; j--) { tfsIrnd(j, blk); } setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); dataOffset += 16; } // added by Recurity Labs function tfsFinal() { return dataBytes; } return { name: "twofish", blocksize: 128 / 8, open: tfsInit, close: tfsClose, encrypt: tfsEncrypt, decrypt: tfsDecrypt, // added by Recurity Labs finalize: tfsFinal }; } var util = require('../../util'); // added by Recurity Labs function TFencrypt(block, key) { var block_copy = [].concat(block); var tf = createTwofish(); tf.open(util.str2bin(key), 0); var result = tf.encrypt(block_copy, 0); tf.close(); return result; } function TF(key) { this.tf = createTwofish(); this.tf.open(util.str2bin(key), 0); this.encrypt = function(block) { return this.tf.encrypt([].concat(block), 0); } } module.exports = TF; module.exports.keySize = TF.prototype.keySize = 32; module.exports.blockSize = TF.prototype.blockSize = 16; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-cleartext.html">cleartext</a></li><li><a href="config.html">config/config</a></li><li><a href="config_localStorage.html">config/config_localStorage</a></li><li><a href="cfb.html">crypto/cfb</a></li><li><a href="aes.html">crypto/cipher/aes</a></li><li><a href="blowfish.html">crypto/cipher/blowfish</a></li><li><a href="cast5.html">crypto/cipher/cast5</a></li><li><a href="des.html">crypto/cipher/des</a></li><li><a href="twofish.html">crypto/cipher/twofish</a></li><li><a href="crypto.html">crypto/crypto</a></li><li><a href="md5.html">crypto/hash/md5</a></li><li><a href="ripe-md.html">crypto/hash/ripe-md</a></li><li><a href="sha.html">crypto/hash/sha</a></li><li><a href="pkcs1.html">crypto/pkcs1</a></li><li><a href="dsa.html">crypto/public_key/dsa</a></li><li><a href="elgamal.html">crypto/public_key/elgamal</a></li><li><a href="jsbn.html">crypto/public_key/jsbn</a></li><li><a href="rsa.html">crypto/public_key/rsa</a></li><li><a href="random.html">crypto/random</a></li><li><a href="signature.html">crypto/signature</a></li><li><a href="armor.html">encoding/armor</a></li><li><a href="base64.html">encoding/base64</a></li><li><a href="module-enums.html">enums</a></li><li><a href="module-key.html">key</a></li><li><a href="keyring.html">keyring/keyring</a></li><li><a href="localstore.html">keyring/localstore</a></li><li><a href="module-message.html">message</a></li><li><a href="module-openpgp.html">openpgp</a></li><li><a href="compressed.html">packet/compressed</a></li><li><a href="literal.html">packet/literal</a></li><li><a href="marker.html">packet/marker</a></li><li><a href="one_pass_signature.html">packet/one_pass_signature</a></li><li><a href="packet.html">packet/packet</a></li><li><a href="packetlist.html">packet/packetlist</a></li><li><a href="public_key.html">packet/public_key</a></li><li><a href="public_key_encrypted_session_key.html">packet/public_key_encrypted_session_key</a></li><li><a href="public_subkey.html">packet/public_subkey</a></li><li><a href="secret_key.html">packet/secret_key</a></li><li><a href="secret_subkey.html">packet/secret_subkey</a></li><li><a href="signature_.html">packet/signature</a></li><li><a href="sym_encrypted_integrity_protected.html">packet/sym_encrypted_integrity_protected</a></li><li><a href="sym_encrypted_session_key.html">packet/sym_encrypted_session_key</a></li><li><a href="symmetrically_encrypted.html">packet/symmetrically_encrypted</a></li><li><a href="user_attribute.html">packet/user_attribute</a></li><li><a href="userid.html">packet/userid</a></li><li><a href="keyid.html">type/keyid</a></li><li><a href="mpi.html">type/mpi</a></li><li><a href="s2k.html">type/s2k</a></li><li><a href="util.html">util/util</a></li></ul><h3>Classes</h3><ul><li><a href="JXG.Util.html">Util</a></li><li><a href="module-cleartext-CleartextMessage.html">CleartextMessage</a></li><li><a href="config-config.html">config</a></li><li><a href="module-key-Key.html">Key</a></li><li><a href="module-key-SubKey.html">SubKey</a></li><li><a href="module-key-User.html">User</a></li><li><a href="module-message-Message.html">Message</a></li><li><a href="util-Util.html">Util</a></li></ul><h3><a href="global.html">Global</a></h3> </nav> <br clear="both"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-alpha2</a> on Sun Dec 22 2013 23:43:09 GMT-0800 (PST) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>