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

📄 blowfish.cs

📁 Granados是一个基于.NET的SSH客户端库。同时支持SSH1和SSH2。实现了AES, Blowfish, TripleDES, RSA, DSA等加密验证算法。实现TCP协议连接。
💻 CS
📖 第 1 页 / 共 2 页
字号:
/* ---------------------------------------------------------------------------
 *
 * 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.
 * 
 * ---------------------------------------------------------------------------
 * 
 * I implemented this algorithm with reference to following products and books though the algorithm is known publicly.
 *   * MindTerm ( AppGate Network Security )
 *   * Applied Cryptography ( Bruce Schneier )
 */

using System;

namespace Routrek.Crypto {

	public class Blowfish {
		byte[] IV;
		byte[] enc;
		byte[] dec;

		private const int BLOCK_SIZE = 8; // bytes in a data-block

		protected uint[] S0;
		protected uint[] S1;
		protected uint[] S2;
		protected uint[] S3;
		protected uint[] P;

		public Blowfish() {
			S0 = new uint[256];
			S1 = new uint[256];
			S2 = new uint[256];
			S3 = new uint[256];
			P  = new uint[18];
			IV = new byte[8];
			enc = new byte[8];
			dec = new byte[8];
		}
		public void SetIV(byte[] newiv) {
			Array.Copy(newiv, 0, IV, 0, IV.Length);
		}

		public void initializeKey(byte[] key) {
			int i, j, len = key.Length;
			uint temp;
		
			Array.Copy(blowfish_pbox, 0,   P,  0, 18);
			Array.Copy(blowfish_sbox, 0,   S0, 0, 256);
			Array.Copy(blowfish_sbox, 256, S1, 0, 256);
			Array.Copy(blowfish_sbox, 512, S2, 0, 256);
			Array.Copy(blowfish_sbox, 768, S3, 0, 256);

			for(j = 0, i = 0; i < 16 + 2; i++) {
				temp = (((uint)(key[j            ]) << 24) |
					((uint)(key[(j + 1) % len]) << 16) |
					((uint)(key[(j + 2) % len]) << 8) |
					((uint)(key[(j + 3) % len])));
				P[i] = P[i] ^ temp;
				j = (j + 4) % len;
			}

			byte[] LR = new byte[8];

			for(i = 0; i < 16 + 2; i += 2) {
				blockEncrypt(LR, 0, LR, 0);
				P[i]     = CipherUtil.GetIntBE(LR, 0);
				P[i + 1] = CipherUtil.GetIntBE(LR, 4);
			}

			for(j = 0; j < 256; j += 2) {
				blockEncrypt(LR, 0, LR, 0);
				S0[j]     = CipherUtil.GetIntBE(LR, 0);
				S0[j + 1] = CipherUtil.GetIntBE(LR, 4);
			}
			for(j = 0; j < 256; j += 2) {
				blockEncrypt(LR, 0, LR, 0);
				S1[j]     = CipherUtil.GetIntBE(LR, 0);
				S1[j + 1] = CipherUtil.GetIntBE(LR, 4);
			}
			for(j = 0; j < 256; j += 2) {
				blockEncrypt(LR, 0, LR, 0);
				S2[j]     = CipherUtil.GetIntBE(LR, 0);
				S2[j + 1] = CipherUtil.GetIntBE(LR, 4);
			}
			for(j = 0; j < 256; j += 2) {
				blockEncrypt(LR, 0, LR, 0);
				S3[j]     = CipherUtil.GetIntBE(LR, 0);
				S3[j + 1] = CipherUtil.GetIntBE(LR, 4);
			}
		}


		public void blockEncrypt(byte[] input, int inOffset, byte[] output, int outOffset) {
			uint L, R;

			L = CipherUtil.GetIntBE(input, inOffset);
			R = CipherUtil.GetIntBE(input, inOffset + 4);

			L ^= P[0];
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[1]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[2]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[3]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[4]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[5]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[6]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[7]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[8]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[9]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[10]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[11]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[12]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[13]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[14]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[15]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[16]);
			R ^= P[17];

			CipherUtil.PutIntBE(R, output, outOffset);
			CipherUtil.PutIntBE(L, output, outOffset + 4);
		}

		public void blockDecrypt(byte[] input, int inOffset, byte[] output, int outOffset) {
			uint L, R;

			L = CipherUtil.GetIntBE(input, inOffset);
			R = CipherUtil.GetIntBE(input, inOffset + 4);

			L ^= P[17];
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[16]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[15]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[14]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[13]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[12]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[11]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[10]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[9]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[8]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[7]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[6]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[5]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[4]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[3]);
			R ^= ((((S0[(int)((L >> 24) & 0xff)] + S1[(int)((L >> 16) & 0xff)]) ^
				S2[(int)((L >> 8) & 0xff)]) + S3[(int)(L & 0xff)]) ^ P[2]);
			L ^= ((((S0[(int)((R >> 24) & 0xff)] + S1[(int)((R >> 16) & 0xff)]) ^
				S2[(int)((R >> 8) & 0xff)]) + S3[(int)(R & 0xff)]) ^ P[1]);
			R ^= P[0];

			CipherUtil.PutIntBE(R, output, outOffset);
			CipherUtil.PutIntBE(L, output, outOffset + 4);
		}

		public void encryptSSH1Style(byte[] src, int srcOff, int len, byte[] dest, int destOff) {
			int end = srcOff + len;
			int i, j;

			for(int si = srcOff, di = destOff; si < end; si += 8, di += 8) {
				for(i = 0; i < 4; i++) {
					j = 3 - i;
					IV[i]     ^= src[si + j];
					IV[i + 4] ^= src[si + 4 + j];
				}
				blockEncrypt(IV, 0, IV, 0);
				for(i = 0; i < 4; i++) {
					j = 3 - i;
					dest[di + i]     = IV[j];
					dest[di + i + 4] = IV[4 + j];
				}
			}
		}
	
		public void decryptSSH1Style(byte[] src, int srcOff, int len, byte[] dest, int destOff) {
			int    end = srcOff + len;
			int    i, j;

			for(int si = srcOff, di = destOff; si < end; si += 8, di += 8) {
				for(i = 0; i < 4; i++) {
					j = (3 - i);
					enc[i]     = src[si + j];
					enc[i + 4] = src[si + 4 + j];
				}
				blockDecrypt(enc, 0, dec, 0);
				for(i = 0; i < 4; i++) {
					j = 3 - i;
					dest[di + i] = (byte)((IV[j] ^ dec[j]) & 0xff);
					IV[j] = enc[j];
					dest[di + i + 4] = (byte)((IV[4 + j] ^ dec[4 + j]) & 0xff);
					IV[4 + j] = enc[4 + j];
				}
			}
		}

		public void encryptCBC(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
			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) {
			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;
			}
		}


		private static readonly uint[] blowfish_pbox = new uint[] {
		0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
		0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
		0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
		0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
		0x9216d5d9, 0x8979fb1b
	};

		private static readonly uint[] blowfish_sbox = new uint[] {
		0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,

⌨️ 快捷键说明

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