📄 rijndael.java
字号:
/****************************************************************************** * * 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... * * Rijndael --pronounced Reindaal-- is a variable block-size (128-, 192- and * 256-bit), variable key-size (128-, 192- and 256-bit) symmetric cipher. * * Rijndael was written by Vincent Rijmen and Joan Daemen. * */package com.mindbright.security.cipher;import com.mindbright.jca.security.InvalidKeyException;public final class Rijndael extends BlockCipher { private int[][] Ke; // encryption round keys private int[][] Kd; // decryption round keys private int ROUNDS; public Rijndael() { } public int getBlockSize() { return BLOCK_SIZE; } /** * Expand a user-supplied key material into a session key. * * @param key The 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"); if (!(key.length == 16 || key.length == 24 || key.length == 32)) throw new InvalidKeyException("Incorrect key length"); ROUNDS = getRounds(key.length, BLOCK_SIZE); Ke = new int[ROUNDS + 1][BC]; // encryption round keys Kd = new int[ROUNDS + 1][BC]; // decryption round keys int ROUND_KEY_COUNT = (ROUNDS + 1) * BC; int KC = key.length / 4; int[] tk = new int[KC]; int i, j; // copy user material bytes into temporary ints for (i = 0, j = 0; i < KC; ) tk[i++] = (key[j++] & 0xFF) << 24 | (key[j++] & 0xFF) << 16 | (key[j++] & 0xFF) << 8 | (key[j++] & 0xFF); // copy values into round key arrays int t = 0; 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]; } int tt, rconpointer = 0; while (t < ROUND_KEY_COUNT) { // extrapolate using phi (the round key evolution function) tt = tk[KC - 1]; tk[0] ^= (S[(tt >>> 16) & 0xFF] & 0xFF) << 24 ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 16 ^ (S[ tt & 0xFF] & 0xFF) << 8 ^ (S[(tt >>> 24) & 0xFF] & 0xFF) ^ (rcon[rconpointer++] & 0xFF) << 24; 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]; } } /** * Convenience method to encrypt exactly one block of plaintext, assuming * Rijndael's default block size (128-bit). * * @param in The plaintext. * @param inOffset Index of in from which to start considering data. * @param out The ciphertext. * @param outOffset Index in out where output of ciphertext should start. */ public void blockEncrypt(byte[] in, int inOffset, byte[] out, int outOffset) { int[] Ker = Ke[0]; // plaintext to ints + key int t0 = ((in[inOffset++] & 0xFF) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF) ) ^ Ker[0]; int t1 = ((in[inOffset++] & 0xFF) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF) ) ^ Ker[1]; int t2 = ((in[inOffset++] & 0xFF) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF) ) ^ Ker[2]; int t3 = ((in[inOffset++] & 0xFF) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF) ) ^ Ker[3]; int a0, a1, a2, a3; for (int r = 1; r < ROUNDS; r++) { // apply round transforms Ker = Ke[r]; a0 = (T1[(t0 >>> 24) & 0xFF] ^ T2[(t1 >>> 16) & 0xFF] ^ T3[(t2 >>> 8) & 0xFF] ^ T4[ t3 & 0xFF] ) ^ Ker[0]; a1 = (T1[(t1 >>> 24) & 0xFF] ^ T2[(t2 >>> 16) & 0xFF] ^ T3[(t3 >>> 8) & 0xFF] ^ T4[ t0 & 0xFF] ) ^ Ker[1]; a2 = (T1[(t2 >>> 24) & 0xFF] ^ T2[(t3 >>> 16) & 0xFF] ^ T3[(t0 >>> 8) & 0xFF] ^ T4[ t1 & 0xFF] ) ^ Ker[2]; a3 = (T1[(t3 >>> 24) & 0xFF] ^ T2[(t0 >>> 16) & 0xFF] ^ T3[(t1 >>> 8) & 0xFF] ^ T4[ t2 & 0xFF] ) ^ Ker[3]; t0 = a0; t1 = a1; t2 = a2; t3 = a3; } // last round is special Ker = Ke[ROUNDS]; int tt = Ker[0]; out[outOffset + 0] = (byte)(S[(t0 >>> 24) & 0xFF] ^ (tt >>> 24)); out[outOffset + 1] = (byte)(S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)); out[outOffset + 2] = (byte)(S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)); out[outOffset + 3] = (byte)(S[ t3 & 0xFF] ^ tt ); tt = Ker[1]; out[outOffset + 4] = (byte)(S[(t1 >>> 24) & 0xFF] ^ (tt >>> 24)); out[outOffset + 5] = (byte)(S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)); out[outOffset + 6] = (byte)(S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)); out[outOffset + 7] = (byte)(S[ t0 & 0xFF] ^ tt ); tt = Ker[2]; out[outOffset + 8] = (byte)(S[(t2 >>> 24) & 0xFF] ^ (tt >>> 24)); out[outOffset + 9] = (byte)(S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)); out[outOffset +10] = (byte)(S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)); out[outOffset +11] = (byte)(S[ t1 & 0xFF] ^ tt ); tt = Ker[3]; out[outOffset +12] = (byte)(S[(t3 >>> 24) & 0xFF] ^ (tt >>> 24)); out[outOffset +13] = (byte)(S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)); out[outOffset +14] = (byte)(S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)); out[outOffset +15] = (byte)(S[ t2 & 0xFF] ^ tt ); } /** * Convenience method to decrypt exactly one block of plaintext, assuming * Rijndael's default block size (128-bit). * * @param in The ciphertext. * @param inOffset Index of in from which to start considering data. * @param out The plaintext. * @param inOffset Index in out where output of plaintext should start. */ public void blockDecrypt(byte[] in, int inOffset, byte[] out, int outOffset) { int[] Kdr = Kd[0]; // ciphertext to ints + key int t0 = ((in[inOffset++] & 0xFF) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF) ) ^ Kdr[0]; int t1 = ((in[inOffset++] & 0xFF) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF) ) ^ Kdr[1]; int t2 = ((in[inOffset++] & 0xFF) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF) ) ^ Kdr[2]; int t3 = ((in[inOffset++] & 0xFF) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF) ) ^ Kdr[3]; int a0, a1, a2, a3; for (int r = 1; r < ROUNDS; r++) { // apply round transforms Kdr = Kd[r]; a0 = (T5[(t0 >>> 24) & 0xFF] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[ t1 & 0xFF] ) ^ Kdr[0]; a1 = (T5[(t1 >>> 24) & 0xFF] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[ t2 & 0xFF] ) ^ Kdr[1]; a2 = (T5[(t2 >>> 24) & 0xFF] ^
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -