433 lines
15 KiB
HTML
433 lines
15 KiB
HTML
<!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-armor.html">armor</a></li><li><a href="module-cleartext.html">cleartext</a></li><li><a href="module-config.html">config</a></li><li><a href="config.html">config/config</a></li><li><a href="localStorage.html">config/localStorage</a></li><li><a href="module-crypto.html">crypto</a></li><li><a href="cfb.html">crypto/cfb</a></li><li><a href="cipher.html">crypto/cipher</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="hash.html">crypto/hash</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="public_key.html">crypto/public_key</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="module-keyid.html">keyid</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-mpi.html">mpi</a></li><li><a href="module-openpgp.html">openpgp</a></li><li><a href="module-packet.html">packet</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="trust.html">packet/trust</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="module-s2k.html">s2k</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="module-util.html">util</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="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></ul>
|
|
</nav>
|
|
|
|
<br clear="both">
|
|
|
|
<footer>
|
|
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.0</a> on Thu Jan 02 2014 13:02:39 GMT-0800 (PST)
|
|
</footer>
|
|
|
|
<script> prettyPrint(); </script>
|
|
<script src="scripts/linenumber.js"> </script>
|
|
</body>
|
|
</html>
|