⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 twofish.java

📁 一个非常好的ssh客户端实现
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************** * * Copyright (c) 1999-2003 AppGate Network Security AB. All Rights Reserved. *  * This file contains Original Code and/or Modifications of Original Code as * defined in and that are subject to the MindTerm Public Source License, * Version 2.0, (the 'License'). You may not use this file except in compliance * with the License. *  * You should have received a copy of the MindTerm Public Source License * along with this software; see the file LICENSE.  If not, write to * AppGate Network Security AB, Otterhallegatan 2, SE-41118 Goteborg, SWEDEN * *****************************************************************************//* * Author's comment: The contents of this file is heavily based upon * the (free) public implementation from Counterpane Systems found here: * http://www.counterpane.com/download-twofish.html * * Twofish is an AES candidate algorithm. It is a balanced 128-bit Feistel * cipher, consisting of 16 rounds. In each round, a 64-bit S-box value is * computed from 64 bits of the block, and this value is xored into the other * half of the block. The two half-blocks are then exchanged, and the next round * begins. Before the first round, all input bits are xored with key- dependent * "whitening" subkeys, and after the final round the output bits are xored with * other key-dependent whitening subkeys; these subkeys are not used anywhere * else in the algorithm.<p> * * Twofish was submitted by Bruce Schneier, Doug Whiting, John Kelsey, Chris * Hall and David Wagner.<p> */package com.mindbright.security.cipher;import com.mindbright.jca.security.InvalidKeyException;public final class Twofish extends BlockCipher {    private int[] sBox;    private int[] subKeys;    public Twofish() {    }    public int getBlockSize() {	return BLOCK_SIZE;    }    /**     * Expand a user-supplied key material into a session key.     *     * @param key  The 64/128/192/256-bit user-key to use.     * @exception  InvalidKeyException  If the key is invalid.     */    public synchronized void initializeKey(byte[] key)	throws InvalidKeyException    {	if (key == null)	    throw new InvalidKeyException("Empty key");	int length = key.length;	if (!(length == 8 || length == 16 || length == 24 || length == 32))	    throw new InvalidKeyException("Incorrect key length");	int k64Cnt = length / 8;	int subkeyCnt = ROUND_SUBKEYS + 2*ROUNDS;	int[] k32e = new int[4]; // even 32-bit entities	int[] k32o = new int[4]; // odd 32-bit entities	int[] sBoxKey = new int[4];	//	// split user key material into even and odd 32-bit entities and	// compute S-box keys using (12, 8) Reed-Solomon code over GF(256)	//	int i, j, offset = 0;	for (i = 0, j = k64Cnt-1; i < 4 && offset < length; i++, j--) {	    k32e[i] = getIntLSBO(key, offset);	    offset += 4;	    k32o[i] = getIntLSBO(key, offset);	    offset += 4;	    sBoxKey[j] = RS_MDS_Encode( k32e[i], k32o[i] ); // reverse order	}	// compute the round decryption subkeys for PHT. these same subkeys	// will be used in encryption but will be applied in reverse order.	int q, A, B;	subKeys = new int[subkeyCnt];	for (i = q = 0; i < subkeyCnt/2; i++, q += SK_STEP) {	    A = F32( k64Cnt, q        , k32e ); // A uses even key entities	    B = F32( k64Cnt, q+SK_BUMP, k32o ); // B uses odd  key entities	    B = B << 8 | B >>> 24;	    A += B;	    subKeys[2*i    ] = A;               // combine with a PHT	    A += B;	    subKeys[2*i + 1] = A << SK_ROTL | A >>> (32-SK_ROTL);	}	//	// fully expand the table for speed	//	int k0 = sBoxKey[0];	int k1 = sBoxKey[1];	int k2 = sBoxKey[2];	int k3 = sBoxKey[3];	int b0, b1, b2, b3;	sBox = new int[4 * 256];	for (i = 0; i < 256; i++) {	    b0 = b1 = b2 = b3 = i;	    switch (k64Cnt & 3) {	    case 1:		sBox[      2*i  ] = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)];		sBox[      2*i+1] = MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)];		sBox[0x200+2*i  ] = MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)];		sBox[0x200+2*i+1] = MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];		break;	    case 0: // same as 4		b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);		b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);		b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);		b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);	    case 3:		b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);		b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);		b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);		b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);	    case 2: // 128-bit keys		sBox[      2*i  ] = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)];		sBox[      2*i+1] = MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)];		sBox[0x200+2*i  ] = MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)];		sBox[0x200+2*i+1] = MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)];	    }	}    }    /**     * Encrypt exactly one block of plaintext.     *     * @param in         The plaintext.     * @param inOffset   Index of in from which to start considering data.     * @param out        The ciphertext generated from a plaintext.     * @param outOffset  Index of out into which to start putting data.     */    public void blockEncrypt(byte[] in, int inOffset, byte[] out, int outOffset) {	int x0 = getIntLSBO(in, inOffset);	int x1 = getIntLSBO(in, inOffset + 4);	int x2 = getIntLSBO(in, inOffset + 8);	int x3 = getIntLSBO(in, inOffset + 12);	x0 ^= subKeys[INPUT_WHITEN    ];	x1 ^= subKeys[INPUT_WHITEN + 1];	x2 ^= subKeys[INPUT_WHITEN + 2];	x3 ^= subKeys[INPUT_WHITEN + 3];	int t0, t1;	int k = ROUND_SUBKEYS;	for (int R = 0; R < ROUNDS; R += 2) {	    t0 = Fe32( sBox, x0, 0 );	    t1 = Fe32( sBox, x1, 3 );	    x2 ^= t0 + t1 + subKeys[k++];	    x2  = x2 >>> 1 | x2 << 31;	    x3  = x3 << 1 | x3 >>> 31;	    x3 ^= t0 + 2*t1 + subKeys[k++];	    t0 = Fe32( sBox, x2, 0 );	    t1 = Fe32( sBox, x3, 3 );	    x0 ^= t0 + t1 + subKeys[k++];	    x0  = x0 >>> 1 | x0 << 31;	    x1  = x1 << 1 | x1 >>> 31;	    x1 ^= t0 + 2*t1 + subKeys[k++];	}	x2 ^= subKeys[OUTPUT_WHITEN    ];	x3 ^= subKeys[OUTPUT_WHITEN + 1];	x0 ^= subKeys[OUTPUT_WHITEN + 2];	x1 ^= subKeys[OUTPUT_WHITEN + 3];	putIntLSBO(x2, out, outOffset);	putIntLSBO(x3, out, outOffset + 4);	putIntLSBO(x0, out, outOffset + 8);	putIntLSBO(x1, out, outOffset + 12);    }    /**     * Decrypt exactly one block of ciphertext.     *     * @param in        The ciphertext.     * @param inOffset  Index of in from which to start considering data.     * @param out       The plaintext generated from a ciphertext.     * @param outOffset Index of out into which to start putting data.     */    public void blockDecrypt(byte[] in, int inOffset, byte[] out, int outOffset) {	int x2 = getIntLSBO(in, inOffset);	int x3 = getIntLSBO(in, inOffset + 4);	int x0 = getIntLSBO(in, inOffset + 8);	int x1 = getIntLSBO(in, inOffset + 12);	x2 ^= subKeys[OUTPUT_WHITEN    ];	x3 ^= subKeys[OUTPUT_WHITEN + 1];	x0 ^= subKeys[OUTPUT_WHITEN + 2];	x1 ^= subKeys[OUTPUT_WHITEN + 3];	int k = ROUND_SUBKEYS + 2*ROUNDS - 1;	int t0, t1;	for (int R = 0; R < ROUNDS; R += 2) {	    t0 = Fe32( sBox, x2, 0 );	    t1 = Fe32( sBox, x3, 3 );	    x1 ^= t0 + 2*t1 + subKeys[k--];	    x1  = x1 >>> 1 | x1 << 31;	    x0  = x0 << 1 | x0 >>> 31;	    x0 ^= t0 + t1 + subKeys[k--];	    t0 = Fe32( sBox, x0, 0 );	    t1 = Fe32( sBox, x1, 3 );	    x3 ^= t0 + 2*t1 + subKeys[k--];	    x3  = x3 >>> 1 | x3 << 31;	    x2  = x2 << 1 | x2 >>> 31;	    x2 ^= t0 + t1 + subKeys[k--];	}	x0 ^= subKeys[INPUT_WHITEN    ];	x1 ^= subKeys[INPUT_WHITEN + 1];	x2 ^= subKeys[INPUT_WHITEN + 2];	x3 ^= subKeys[INPUT_WHITEN + 3];	putIntLSBO(x0, out, outOffset);	putIntLSBO(x1, out, outOffset + 4);	putIntLSBO(x2, out, outOffset + 8);	putIntLSBO(x3, out, outOffset + 12);    }    //    //    //    private final static int BLOCK_SIZE = 16; // bytes in a data-block    private final static int ROUNDS = 16;    /* Subkey array indices */    private static final int INPUT_WHITEN = 0;    private static final int OUTPUT_WHITEN = INPUT_WHITEN +  BLOCK_SIZE/4;    private static final int ROUND_SUBKEYS = OUTPUT_WHITEN + BLOCK_SIZE/4; // 2*(# rounds)    private static final int SK_STEP = 0x02020202;    private static final int SK_BUMP = 0x01010101;    private static final int SK_ROTL = 9;    /**     * Define the fixed p0/p1 permutations used in keyed S-box lookup.     * By changing the following constant definitions, the S-boxes will     * automatically get changed in the Twofish engine.     */    private static final int P_00 = 1;    private static final int P_01 = 0;    private static final int P_02 = 0;    private static final int P_03 = P_01 ^ 1;    private static final int P_04 = 1;    private static final int P_10 = 0;    private static final int P_11 = 0;    private static final int P_12 = 1;    private static final int P_13 = P_11 ^ 1;    private static final int P_14 = 0;    private static final int P_20 = 1;    private static final int P_21 = 1;    private static final int P_22 = 0;    private static final int P_23 = P_21 ^ 1;    private static final int P_24 = 0;    private static final int P_30 = 0;    private static final int P_31 = 1;    private static final int P_32 = 1;    private static final int P_33 = P_31 ^ 1;    private static final int P_34 = 1;    /** Primitive polynomial for GF(256) */    private static final int GF256_FDBK_2 = 0x169 / 2;    private static final int GF256_FDBK_4 = 0x169 / 4;    /** MDS matrix */    private static final int[][] MDS = new int[4][256]; // blank final    private static final int RS_GF_FDBK = 0x14D; // field generator    /** Fixed 8x8 permutation S-boxes */    private static final byte[][] P = new byte[][] {	{  // p0	    (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,	    (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,	    (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,	    (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,	    (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -