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

📄 rijndael_algorithm.java

📁 用JAVA编写的rijndael工具
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
			if (KC != 8)
				for (i = 1, j = 0; i < KC;)
					tk[i++] ^= tk[j++];
			else {
				for (i = 1, j = 0; i < KC / 2;)
					tk[i++] ^= tk[j++];
				tt = tk[KC / 2 - 1];
				tk[KC / 2] ^= (S[tt & 0xFF] & 0xFF)
						^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 8
						^ (S[(tt >>> 16) & 0xFF] & 0xFF) << 16
						^ (S[(tt >>> 24) & 0xFF] & 0xFF) << 24;
				for (j = KC / 2, i = j + 1; i < KC;)
					tk[i++] ^= tk[j++];
			}
			// copy values into round key arrays
			for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) {
				Ke[t / BC][t % BC] = tk[j];
				Kd[ROUNDS - (t / BC)][t % BC] = tk[j];
			}
		}
		for (int r = 1; r < ROUNDS; r++)
			// inverse MixColumn where needed
			for (j = 0; j < BC; j++) {
				tt = Kd[r][j];
				Kd[r][j] = U1[(tt >>> 24) & 0xFF] ^ U2[(tt >>> 16) & 0xFF]
						^ U3[(tt >>> 8) & 0xFF] ^ U4[tt & 0xFF];
			}
		// assemble the encryption (Ke) and decryption (Kd) round keys into
		// one sessionKey object
		Object[] sessionKey = new Object[] { Ke, Kd };
		if (DEBUG)
			trace(OUT, "makeKey()");
		return sessionKey;
	}

	/**
	 * Encrypt exactly one block of plaintext.
	 * 
	 * @param in
	 *            The plaintext.
	 * @param inOffset
	 *            Index of in from which to start considering data.
	 * @param sessionKey
	 *            The session key to use for encryption.
	 * @param blockSize
	 *            The block size in bytes of this Rijndael.
	 * @return The ciphertext generated from a plaintext using the session key.
	 */
	public static byte[] blockEncrypt(byte[] in, int inOffset,
			Object sessionKey, int blockSize) {
		if (blockSize == BLOCK_SIZE)
			return blockEncrypt(in, inOffset, sessionKey);
		if (DEBUG)
			trace(IN, "blockEncrypt(" + in + ", " + inOffset + ", "
					+ sessionKey + ", " + blockSize + ")");
		Object[] sKey = (Object[]) sessionKey; // extract encryption round keys
		int[][] Ke = (int[][]) sKey[0];

		int BC = blockSize / 4;
		int ROUNDS = Ke.length - 1;
		int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
		int s1 = shifts[SC][1][0];
		int s2 = shifts[SC][2][0];
		int s3 = shifts[SC][3][0];
		int[] a = new int[BC];
		int[] t = new int[BC]; // temporary work array
		int i;
		byte[] result = new byte[blockSize]; // the resulting ciphertext
		int j = 0, tt;

		for (i = 0; i < BC; i++)
			// plaintext to ints + key
			t[i] = ((in[inOffset++] & 0xFF) << 24
					| (in[inOffset++] & 0xFF) << 16
					| (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
					^ Ke[0][i];
		for (int r = 1; r < ROUNDS; r++) { // apply round transforms
			for (i = 0; i < BC; i++)
				a[i] = (T1[(t[i] >>> 24) & 0xFF]
						^ T2[(t[(i + s1) % BC] >>> 16) & 0xFF]
						^ T3[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ T4[t[(i + s3)
						% BC] & 0xFF])
						^ Ke[r][i];
			System.arraycopy(a, 0, t, 0, BC);
			if (DEBUG && debuglevel > 6)
				System.out.println("CT" + r + "=" + toString(t));
		}
		for (i = 0; i < BC; i++) { // last round is special
			tt = Ke[ROUNDS][i];
			result[j++] = (byte) (S[(t[i] >>> 24) & 0xFF] ^ (tt >>> 24));
			result[j++] = (byte) (S[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16));
			result[j++] = (byte) (S[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8));
			result[j++] = (byte) (S[t[(i + s3) % BC] & 0xFF] ^ tt);
		}
		if (DEBUG && debuglevel > 6) {
			System.out.println("CT=" + toString(result));
			System.out.println();
		}
		if (DEBUG)
			trace(OUT, "blockEncrypt()");
		return result;
	}

	/**
	 * Decrypt exactly one block of ciphertext.
	 * 
	 * @param in
	 *            The ciphertext.
	 * @param inOffset
	 *            Index of in from which to start considering data.
	 * @param sessionKey
	 *            The session key to use for decryption.
	 * @param blockSize
	 *            The block size in bytes of this Rijndael.
	 * @return The plaintext generated from a ciphertext using the session key.
	 */
	public static byte[] blockDecrypt(byte[] in, int inOffset,
			Object sessionKey, int blockSize) {
		if (blockSize == BLOCK_SIZE)
			return blockDecrypt(in, inOffset, sessionKey);
		if (DEBUG)
			trace(IN, "blockDecrypt(" + in + ", " + inOffset + ", "
					+ sessionKey + ", " + blockSize + ")");
		Object[] sKey = (Object[]) sessionKey; // extract decryption round keys
		int[][] Kd = (int[][]) sKey[1];

		int BC = blockSize / 4;
		int ROUNDS = Kd.length - 1;
		int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
		int s1 = shifts[SC][1][1];
		int s2 = shifts[SC][2][1];
		int s3 = shifts[SC][3][1];
		int[] a = new int[BC];
		int[] t = new int[BC]; // temporary work array
		int i;
		byte[] result = new byte[blockSize]; // the resulting plaintext
		int j = 0, tt;

		for (i = 0; i < BC; i++)
			// ciphertext to ints + key
			t[i] = ((in[inOffset++] & 0xFF) << 24
					| (in[inOffset++] & 0xFF) << 16
					| (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
					^ Kd[0][i];
		for (int r = 1; r < ROUNDS; r++) { // apply round transforms
			for (i = 0; i < BC; i++)
				a[i] = (T5[(t[i] >>> 24) & 0xFF]
						^ T6[(t[(i + s1) % BC] >>> 16) & 0xFF]
						^ T7[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ T8[t[(i + s3)
						% BC] & 0xFF])
						^ Kd[r][i];
			System.arraycopy(a, 0, t, 0, BC);
			if (DEBUG && debuglevel > 6)
				System.out.println("PT" + r + "=" + toString(t));
		}
		for (i = 0; i < BC; i++) { // last round is special
			tt = Kd[ROUNDS][i];
			result[j++] = (byte) (Si[(t[i] >>> 24) & 0xFF] ^ (tt >>> 24));
			result[j++] = (byte) (Si[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16));
			result[j++] = (byte) (Si[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8));
			result[j++] = (byte) (Si[t[(i + s3) % BC] & 0xFF] ^ tt);
		}
		if (DEBUG && debuglevel > 6) {
			System.out.println("PT=" + toString(result));
			System.out.println();
		}
		if (DEBUG)
			trace(OUT, "blockDecrypt()");
		return result;
	}

	/** A basic symmetric encryption/decryption test for a given key size. */
	private static boolean self_test(int keysize) {
		if (DEBUG)
			trace(IN, "self_test(" + keysize + ")");
		boolean ok = false;
		try {
			byte[] kb = new byte[keysize];
			byte[] pt = new byte[BLOCK_SIZE];
			int i;

			for (i = 0; i < keysize; i++)
				kb[i] = (byte) i;
			for (i = 0; i < BLOCK_SIZE; i++)
				pt[i] = (byte) i;

			if (DEBUG && debuglevel > 6) {
				System.out.println("==========");
				System.out.println();
				System.out.println("KEYSIZE=" + (8 * keysize));
				System.out.println("KEY=" + toString(kb));
				System.out.println();
			}
			Object key = makeKey(kb, BLOCK_SIZE);

			if (DEBUG && debuglevel > 6) {
				System.out
						.println("Intermediate Ciphertext Values (Encryption)");
				System.out.println();
				System.out.println("PT=" + toString(pt));
			}
			byte[] ct = blockEncrypt(pt, 0, key, BLOCK_SIZE);

			if (DEBUG && debuglevel > 6) {
				System.out
						.println("Intermediate Plaintext Values (Decryption)");
				System.out.println();
				System.out.println("CT=" + toString(ct));
			}
			byte[] cpt = blockDecrypt(ct, 0, key, BLOCK_SIZE);

			ok = areEqual(pt, cpt);
			if (!ok)
				throw new RuntimeException("Symmetric operation failed");
		} catch (Exception x) {
			if (DEBUG && debuglevel > 0) {
				debug("Exception encountered during self-test: "
						+ x.getMessage());
				x.printStackTrace();
			}
		}
		if (DEBUG && debuglevel > 0)
			debug("Self-test OK? " + ok);
		if (DEBUG)
			trace(OUT, "self_test()");
		return ok;
	}

	/**
	 * Return The number of rounds for a given Rijndael's key and block sizes.
	 * 
	 * @param keySize
	 *            The size of the user key material in bytes.
	 * @param blockSize
	 *            The desired block size in bytes.
	 * @return The number of rounds for a given Rijndael's key and block sizes.
	 */
	public static int getRounds(int keySize, int blockSize) {
		switch (keySize) {
		case 16:
			return blockSize == 16 ? 10 : (blockSize == 24 ? 12 : 14);
		case 24:
			return blockSize != 32 ? 12 : 14;
		default: // 32 bytes = 256 bits
			return 14;
		}
	}

	// utility static methods (from cryptix.util.core ArrayUtil and Hex classes)
	// ...........................................................................

	/**
	 * Compares two byte arrays for equality.
	 * 
	 * @return true if the arrays have identical contents
	 */
	private static boolean areEqual(byte[] a, byte[] b) {
		int aLength = a.length;
		if (aLength != b.length)
			return false;
		for (int i = 0; i < aLength; i++)
			if (a[i] != b[i])
				return false;
		return true;
	}

	/**
	 * Returns a string of 2 hexadecimal digits (most significant digit first)
	 * corresponding to the lowest 8 bits of <i>n</i>.
	 */
	private static String byteToString(int n) {
		char[] buf = { HEX_DIGITS[(n >>> 4) & 0x0F], HEX_DIGITS[n & 0x0F] };
		return new String(buf);
	}

	/**
	 * Returns a string of 8 hexadecimal digits (most significant digit first)
	 * corresponding to the integer <i>n</i>, which is treated as unsigned.
	 */
	private static String intToString(int n) {
		char[] buf = new char[8];
		for (int i = 7; i >= 0; i--) {
			buf[i] = HEX_DIGITS[n & 0x0F];
			n >>>= 4;
		}
		return new String(buf);
	}

	/**
	 * Returns a string of hexadecimal digits from a byte array. Each byte is
	 * converted to 2 hex symbols.
	 */
	private static String toString(byte[] ba) {
		int length = ba.length;
		char[] buf = new char[length * 2];
		for (int i = 0, j = 0, k; i < length;) {
			k = ba[i++];
			buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
			buf[j++] = HEX_DIGITS[k & 0x0F];
		}
		return new String(buf);
	}

	/**
	 * Returns a string of hexadecimal digits from an integer array. Each int is
	 * converted to 4 hex symbols.
	 */
	private static String toString(int[] ia) {
		int length = ia.length;
		char[] buf = new char[length * 8];
		for (int i = 0, j = 0, k; i < length; i++) {
			k = ia[i];
			buf[j++] = HEX_DIGITS[(k >>> 28) & 0x0F];
			buf[j++] = HEX_DIGITS[(k >>> 24) & 0x0F];
			buf[j++] = HEX_DIGITS[(k >>> 20) & 0x0F];
			buf[j++] = HEX_DIGITS[(k >>> 16) & 0x0F];
			buf[j++] = HEX_DIGITS[(k >>> 12) & 0x0F];
			buf[j++] = HEX_DIGITS[(k >>> 8) & 0x0F];
			buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
			buf[j++] = HEX_DIGITS[k & 0x0F];
		}
		return new String(buf);
	}

	// main(): use to generate the Intermediate Values KAT
	// ...........................................................................

	public static void main(String[] args) {
		self_test(16);
		self_test(24);
		self_test(32);
	}
}

⌨️ 快捷键说明

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