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

📄 twofish.java

📁 面向应用的智能安全代理平台和工具包是一个综合网络应用的安全共性需求而设计和实现的一个通用性的网络信息安全应用支撑平台
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
	 * the result in the provided buffer starting at the given offset.
	 * The input will be an exact multiple of our blocksize.
	 */
	protected int encryptBlock(
		byte[] src,
		int srcIndex,
		int len,
		byte[] dst,
		int dstIndex)
	throws IllegalBlockSizeException
	{
		if (len != TF_BLOCK_SIZE)
		{
			throw new IllegalBlockSizeException("Datasize less than block size.");
		}

		int[] x = new int[TF_BLOCK_SIZE / 4];

		/*
		 * copy in the block, add whitening
		 */
		for (int i = 0; i < TF_BLOCK_SIZE / 4; i++)
		{
			x[i] = src[srcIndex++] & 0xFF
				| (src[srcIndex++] & 0xFF) << 8
				| (src[srcIndex++] & 0xFF) << 16
				| (src[srcIndex++] & 0xFF) << 24;

			x[i] ^= subKeys[INPUT_WHITEN + i];
		}

		/*
		 * main Twofish encryption loop
		 */
		for (int i = 0; i < ROUNDS; i++)
		{
			int t0, t1;

			t0 = f32(x[0], sBoxKeys, k64Cnt);
			t1 = f32(x[1] << 8 | x[1] >>> 24, sBoxKeys, k64Cnt);

			// System.out.println("t0=" + Integer.toHexString(t0) + ".\tt1=" + Integer.toHexString(t1));

			x[3] = x[3] << 1 | x[3] >>> 31;

			// PHT, round keys
			x[2] ^= t0 + t1 + subKeys[ROUND_SUBKEYS+2*i];
			x[3] ^= t0 + 2*t1 + subKeys[ROUND_SUBKEYS+2*i+1];

			x[2] = x[2] << 31 | x[2] >>> 1;

			/* swap for next round */
			if (i < ROUNDS - 1)
			{
				int tmp;
				tmp = x[0]; x[0] = x[2]; x[2] = tmp;
				tmp = x[1]; x[1] = x[3]; x[3] = tmp;
			}
		}

		/*
		 * copy out the block, with whitening
		 */
		for (int i = 0; i < TF_BLOCK_SIZE / 4; i++)
		{
			x[i] ^= subKeys[OUTPUT_WHITEN + i];
			dst[dstIndex++] = (byte)b0(x[i]);
			dst[dstIndex++] = (byte)b1(x[i]);
			dst[dstIndex++] = (byte)b2(x[i]);
			dst[dstIndex++] = (byte)b3(x[i]);
		}

		return TF_BLOCK_SIZE;
	}
	/**
	 * Returns the block size (in bytes).
	 *
	 * @return the block size (in bytes) of the cipher.
	 */
	protected int engineGetBlockSize()
	{
		return TF_BLOCK_SIZE;
	}
	/**
	 * Sets the padding mechanism of this cipher. 
	 *
	 * @param padding	the name of the type of padding to be applied,
	 * 	currently "PKCS7Padding", and "NoPadding" will
	 * 	be accepted.
	 * @exception NoSuchPaddingException if the padding type is unknown.
	 */
	protected void engineSetPadding(
		String padding)
	throws NoSuchPaddingException
	{
		if (padding.equals("PKCS7Padding"))
		{
			paddedStream = true;
		}
		else if (padding.equals("NoPadding"))
		{
			paddedStream = false;
		}
		else
		{
			throw new NoSuchPaddingException(
				"Twofish only supports PKCS7 padding.");
		}
	}
	/**
	 * Run four bytes through keyed S-boxes and apply MDS matrix.
	 *
	 * <p>This function is a keyed 32-bit permutation.  It is the
	 * major building block for the Twofish round function,
	 * including the four keyed 8x8 permutations and the 4x4 MDS
	 * matrix multiply.  This function is used both for generating
	 * round subkeys and within the round function on the block
	 * being encrypted.
	 *
	 * @param x input to f function
	 * @param k32 pointer to key values
	 * @returns The output of the keyed permutation applied to x.
	 */
	final static int f32(
		int x,
		int[] k32,
		int k64len)
	{
		int[] b = new int[4];

		/*
		 * Run each byte thru 8x8 S-boxes, xoring with key byte
		 * at each stage.  Note that each byte goes through a
		 * different combination of S-boxes.
		 */

		/*
		 * make b[0] = LSB, b[3] = MSB
		 */
		b[0] = b0(x);
		b[1] = b1(x);
		b[2] = b2(x);
		b[3] = b3(x);

		// System.out.println(Integer.toHexString(b[0]) + " " + Integer.toHexString(b[1]) + " " + Integer.toHexString(b[2]) + " " + Integer.toHexString(b[3]) + " ");

		switch (k64len & 3)
		{
		case 0:     /* 256 bits of key */
			b[0] = (P[P_04][b[0]] & 0xFF) ^ b0(k32[3]);
			b[1] = (P[P_14][b[1]] & 0xFF) ^ b1(k32[3]);
			b[2] = (P[P_24][b[2]] & 0xFF) ^ b2(k32[3]);
			b[3] = (P[P_34][b[3]] & 0xFF) ^ b3(k32[3]);
			/* fall thru, having pre-processed b[0]..b[3] with k32[3] */
		case 3:     /* 192 bits of key */
			b[0] = (P[P_03][b[0]] & 0xFF) ^ b0(k32[2]);
			b[1] = (P[P_13][b[1]] & 0xFF) ^ b1(k32[2]);
			b[2] = (P[P_23][b[2]] & 0xFF) ^ b2(k32[2]);
			b[3] = (P[P_33][b[3]] & 0xFF) ^ b3(k32[2]);
			/* fall thru, having pre-processed b[0]..b[3] with k32[2] */
		case 2:     /* 128 bits of key */
			b[0] = P[P_00][(P[P_01][(P[P_02][b[0]] ^ b0(k32[1])) & 0xFF] ^ b0(k32[0])) & 0xFF];
			b[1] = P[P_10][(P[P_11][(P[P_12][b[1]] ^ b1(k32[1])) & 0xFF] ^ b1(k32[0])) & 0xFF];
			b[2] = P[P_20][(P[P_21][(P[P_22][b[2]] ^ b2(k32[1])) & 0xFF] ^ b2(k32[0])) & 0xFF];
			b[3] = P[P_30][(P[P_31][(P[P_32][b[3]] ^ b3(k32[1])) & 0xFF] ^ b3(k32[0])) & 0xFF];
		}

		b[0] &= 0xFF;
		b[1] &= 0xFF;
		b[2] &= 0xFF;
		b[3] &= 0xFF;

		// System.out.println(Integer.toHexString(b[0]) + " " + Integer.toHexString(b[1]) + " " + Integer.toHexString(b[2]) + " " + Integer.toHexString(b[3]) + " ");

		/* Now perform the MDS matrix multiply inline. */
		return ((Mx_1(b[0]) ^ Mx_Y(b[1]) ^ Mx_X(b[2]) ^ Mx_X(b[3]))) ^
		((Mx_X(b[0]) ^ Mx_Y(b[1]) ^ Mx_Y(b[2]) ^ Mx_1(b[3])) << 8) ^
		((Mx_Y(b[0]) ^ Mx_X(b[1]) ^ Mx_1(b[2]) ^ Mx_Y(b[3])) <<16) ^
		((Mx_Y(b[0]) ^ Mx_1(b[1]) ^ Mx_Y(b[2]) ^ Mx_X(b[3])) <<24);
	}
	final static int LFSR1(int x)
	{
		return (x >>> 1) ^ ((x & 0x01) != 0 ? GF256_FDBK_2 : 0);
	}
	final static int LFSR2(int x)
	{
		return (x >>> 2) ^
			((x & 0x02) != 0 ? GF256_FDBK_2 : 0) ^
			((x & 0x01) != 0 ? GF256_FDBK_4 : 0);
	}
	final static int Mx_1(int x)
	{
		return x;
	}
	final static int Mx_X(int x)
	{
		return x ^ LFSR2(x);
	} // 5B
	final static int Mx_Y(int x)
	{
		return x ^ LFSR1(x) ^ LFSR2(x);
	} // EF
	//==================================
	// Private Implementation
	//==================================

	/**
	 * Initialise the key schedule from the given key material.
	 *
	 * <p>Here we precompute all the round subkeys, although that is
	 * not actually required.
	 */
	private void prepareKey(byte[] key)
	{
		int[] k32e = new int[MAX_KEY_BITS/64];
		int[] k32o = new int[MAX_KEY_BITS/64];

		/*
		 * key schedule data
		 */
		sBoxKeys = new int[MAX_KEY_BITS/64];
		subKeys = new int[TOTAL_SUBKEYS];

		/*
		 * Round up to next multiple of 64bits
		 *
		 * This assumes the key has been padded out with zeros to
		 * a valid key length
		 */
		k64Cnt = (key.length + 7) / 8;

		// System.out.println("S-box key");
		int offset = 0;
		for (int i = 0; i < k64Cnt; i++)
		{
			k32e[i] = (key[offset++] & 0xFF)
				| (key[offset++] & 0xFF) << 8
				| (key[offset++] & 0xFF) << 16
				| (key[offset++] & 0xFF) << 24;

			k32o[i] = (key[offset++] & 0xFF)
				| (key[offset++] & 0xFF) << 8
				| (key[offset++] & 0xFF) << 16
				| (key[offset++] & 0xFF) << 24;

			// the sbox keys are stored in reverse order
			sBoxKeys[k64Cnt - 1 - i] = RS_MDS_Encode(k32e[i], k32o[i]);

			// System.out.println(Integer.toHexString(sBoxKeys[k64Cnt - 1 - i]));
		}

		// System.out.println("Subkeys");
		/*
		 * compute round subkeys for PHT
		 */
		for (int i = 0; i < TOTAL_SUBKEYS / 2; i++)
		{
			int A = f32(i * SK_STEP, k32e, k64Cnt);
			int B = f32(i * SK_STEP + SK_BUMP, k32o, k64Cnt);

			// System.out.print("A = " + Integer.toHexString(A));
			// System.out.println(" B = " + Integer.toHexString(B));

			B = B << 8 | B >>> 24;

			A += B;
			subKeys[2 * i] = A;
			A += B;
			subKeys[2 * i + 1] = A << SK_ROTL | A >>> (32-SK_ROTL);

			// System.out.println(Integer.toHexString(subKeys[2 * i]) + "\t" + Integer.toHexString(subKeys[2 * i + 1]));
		}
	}
	/**
	 * Use (12,8) Reed-Solomon code over GF(256) to produce a key
	 * S-box dword from two key material integers.
	 *
	 * <p>Since this computation is done only once per reKey per 64
	 * bits of key, the performance impact of this routine is
	 * imperceptible. The RS code chosen has "simple" coefficients
	 * to allow smartcard/hardware implementation without lookup
	 * tables.
	 * @return Remainder polynomial generated using RS code
	 */
	final static int RS_MDS_Encode(int k0, int k1)
	{
		int r = 0;

		for (int i = 0; i < 2; i++)
		{
			// merge in 32 more key bits
			r ^= (i == 0) ? k1 : k0;

			// shift one byte at a time
			for (int j = 0; j < 4; j++)
			{
				/*
				 * Reed-Solomon code parameters: (12,8)
				 * reversible code
				 * g(x) = x**4 + (a + 1/a) x**3
				 *        + a x**2 + (a + 1/a) x + 1
				 * where a = primitive root of field
				 * generator 0x14D
				 */
				int b = b3(r);
				int g2 = ((b << 1) ^ ((b & 0x80) != 0 ? RS_GF_FDBK : 0 )) & 0xFF;
				int g3 = ((b >>> 1) & 0x7F) ^ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0 ) ^ g2;
				r = (r << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b;
			}
		}

		return r;
	}
	/**
	 * Re-key the cipher.  If the provided Key is not compatible
	 * with this cipher the exception should throw an InvalidKeyException.
	 *
	 * @param inKey      the key to be used.
	 * @exception InvalidKeyException if the key is of the wrong type.
	 */
	protected void setKey(Key inKey)
	throws InvalidKeyException
	{
		if (!((inKey instanceof TwofishKey)
				|| (inKey instanceof SecretKeySpec)))
		{
			throw new InvalidKeyException("not a Twofish Key");
		}

		prepareKey(inKey.getEncoded());
	}
}

⌨️ 快捷键说明

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