📄 rijndael.cs
字号:
/* ---------------------------------------------------------------------------
*
* Copyright (c) Routrek Networks, Inc. All Rights Reserved..
*
* This file is a part of the Granados SSH Client Library that is subject to
* the license included in the distributed package.
* You may not use this file except in compliance with the license.
*
* ---------------------------------------------------------------------------
*
* Rijndael was written by <a href="mailto:rijmen@esat.kuleuven.ac.be">Vincent
* Rijmen</a> and <a href="mailto:Joan.Daemen@village.uunet.be">Joan Daemen</a>.
*
* ---------------------------------------------------------------------------
*
* I implemented this algorithm with reference to following products though the algorithm is known publicly.
* * MindTerm ( AppGate Network Security )
*/
using System;
namespace Routrek.Crypto
{
public class Rijndael
{
byte[] _IV;
int[][] _Ke; // encryption round keys
int[][] _Kd; // decryption round keys
private int _rounds;
public Rijndael() {
_IV = new byte[GetBlockSize()];
}
public int GetBlockSize() {
return BLOCK_SIZE;
}
///////////////////////////////////////////////
// set _IV
///////////////////////////////////////////////
public void SetIV(byte[] newiv) {
Array.Copy(newiv, 0, _IV, 0, _IV.Length);
}
///////////////////////////////////////////////
// set KEY
///////////////////////////////////////////////
public void InitializeKey(byte[] key) {
if (key == null)
throw new Exception("Empty key");
//128bit or 192bit or 256bit
if (!(key.Length == 16 || key.Length == 24 || key.Length == 32))
throw new Exception("Incorrect key length");
_rounds = getRounds(key.Length, GetBlockSize());
_Ke = new int[_rounds + 1][];
_Kd = new int[_rounds + 1][];
int i, j;
for(i=0; i<_rounds + 1; i++) {
_Ke[i] = new int[BC];
_Kd[i] = new int[BC];
}
int ROUND_KEY_COUNT = (_rounds + 1) * BC;
int KC = key.Length / 4;
int[] tk = new int[KC];
for (i = 0, j = 0; i < KC; ) {
tk[i++] = (key[j++] & 0xFF) << 24 |
(key[j++] & 0xFF) << 16 |
(key[j++] & 0xFF) << 8 |
(key[j++] & 0xFF);
}
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) {
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++];
}
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++){
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];
}
}
}
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:
return 14;
}
}
public void encryptCBC(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
int block_size = GetBlockSize();
int nBlocks = inputLen / block_size;
for(int bc = 0; bc < nBlocks; bc++) {
CipherUtil.BlockXor(input, inputOffset, block_size, _IV, 0);
blockEncrypt(_IV, 0, output, outputOffset);
Array.Copy(output, outputOffset, _IV, 0, block_size);
inputOffset += block_size;
outputOffset += block_size;
}
}
public void decryptCBC(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
int block_size = GetBlockSize();
byte[] tmpBlk = new byte[block_size];
int nBlocks = inputLen / block_size;
for(int bc = 0; bc < nBlocks; bc++)
{
blockDecrypt(input, inputOffset, tmpBlk, 0);
for(int i = 0; i < block_size; i++)
{
tmpBlk[i] ^= _IV[i];
_IV[i] = input[inputOffset + i];
output[outputOffset + i] = tmpBlk[i];
}
inputOffset += block_size;
outputOffset += block_size;
}
}
public void blockEncrypt(byte[] src, int inOffset, byte[] dst, int outOffset) {
int[] Ker = _Ke[0];
int t0 = ((src[inOffset++] & 0xFF) << 24 |
(src[inOffset++] & 0xFF) << 16 |
(src[inOffset++] & 0xFF) << 8 |
(src[inOffset++] & 0xFF) ) ^ Ker[0];
int t1 = ((src[inOffset++] & 0xFF) << 24 |
(src[inOffset++] & 0xFF) << 16 |
(src[inOffset++] & 0xFF) << 8 |
(src[inOffset++] & 0xFF) ) ^ Ker[1];
int t2 = ((src[inOffset++] & 0xFF) << 24 |
(src[inOffset++] & 0xFF) << 16 |
(src[inOffset++] & 0xFF) << 8 |
(src[inOffset++] & 0xFF) ) ^ Ker[2];
int t3 = ((src[inOffset++] & 0xFF) << 24 |
(src[inOffset++] & 0xFF) << 16 |
(src[inOffset++] & 0xFF) << 8 |
(src[inOffset++] & 0xFF) ) ^ Ker[3];
int a0, a1, a2, a3;
for (int r = 1; r < _rounds; r++) {
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;
}
Ker = _Ke[_rounds];
int tt = Ker[0];
dst[outOffset + 0] = (byte)(S[(t0 >> 24) & 0xFF] ^ (tt >> 24));
dst[outOffset + 1] = (byte)(S[(t1 >> 16) & 0xFF] ^ (tt >> 16));
dst[outOffset + 2] = (byte)(S[(t2 >> 8) & 0xFF] ^ (tt >> 8));
dst[outOffset + 3] = (byte)(S[ t3 & 0xFF] ^ tt );
tt = Ker[1];
dst[outOffset + 4] = (byte)(S[(t1 >> 24) & 0xFF] ^ (tt >> 24));
dst[outOffset + 5] = (byte)(S[(t2 >> 16) & 0xFF] ^ (tt >> 16));
dst[outOffset + 6] = (byte)(S[(t3 >> 8) & 0xFF] ^ (tt >> 8));
dst[outOffset + 7] = (byte)(S[ t0 & 0xFF] ^ tt );
tt = Ker[2];
dst[outOffset + 8] = (byte)(S[(t2 >> 24) & 0xFF] ^ (tt >> 24));
dst[outOffset + 9] = (byte)(S[(t3 >> 16) & 0xFF] ^ (tt >> 16));
dst[outOffset +10] = (byte)(S[(t0 >> 8) & 0xFF] ^ (tt >> 8));
dst[outOffset +11] = (byte)(S[ t1 & 0xFF] ^ tt );
tt = Ker[3];
dst[outOffset +12] = (byte)(S[(t3 >> 24) & 0xFF] ^ (tt >> 24));
dst[outOffset +13] = (byte)(S[(t0 >> 16) & 0xFF] ^ (tt >> 16));
dst[outOffset +14] = (byte)(S[(t1 >> 8) & 0xFF] ^ (tt >> 8));
dst[outOffset +15] = (byte)(S[ t2 & 0xFF] ^ tt );
}
public void blockDecrypt(byte[] src, int inOffset, byte[] dst, int outOffset) {
int[] Kdr = _Kd[0];
int t0 = ((src[inOffset++] & 0xFF) << 24 |
(src[inOffset++] & 0xFF) << 16 |
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -