📄 des.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.
*
* ---------------------------------------------------------------------------
*
* I implemented this algorithm with reference to following products or books though the algorithm is known publicly.
* * MindTerm ( AppGate Network Security )
* * Applied Cryptography ( Bruce Schneier )
*
*/
using System;
namespace Routrek.Crypto
{
public class DES
{
private const int BLOCK_SIZE = 8; // bytes in a data-block
uint[] _key;
byte[] _iv;
byte[] _temp;
public DES() {
_key = new uint[32];
_iv = new byte[8];
_temp = new byte[8];
}
public void SetIV(byte[] newiv) {
Array.Copy(newiv, 0, _iv, 0, _iv.Length);
}
public void SetIV(byte[] newiv, int offset) {
Array.Copy(newiv, offset, _iv, 0, _iv.Length);
}
public void InitializeKey(byte[] key, int offset)
{
uint i, c, d, t, s, shifts;
c = CipherUtil.GetIntLE(key, offset+0);
d = CipherUtil.GetIntLE(key, offset+4);
t = ((d >> 4) ^ c) & 0x0f0f0f0f;
c ^= t;
d ^= t << 4;
t = (((c << (16 - (-2))) ^ c) & 0xcccc0000);
c = c ^ t ^ (t >> (16 - (-2)));
t = (((d << (16 - (-2))) ^ d) & 0xcccc0000);
d = d ^ t ^ (t >> (16 - (-2)));
t = ((d >> 1) ^ c) & 0x55555555;
c ^= t;
d ^= t << 1;
t = ((c >> 8) ^ d) & 0x00ff00ff;
d ^= t;
c ^= t << 8;
t = ((d >> 1) ^ c) & 0x55555555;
c ^= t;
d ^= t << 1;
d = ((d & 0xff) << 16) | (d & 0xff00) |
((d >> 16) & 0xff) | ((c >> 4) & 0xf000000);
c &= 0x0fffffff;
shifts = 0x7efc;
for(i = 0; i < 16; i++) {
if((shifts & 1) != 0) {
c = ((c >> 2) | (c << 26));
d = ((d >> 2) | (d << 26));
} else {
c = ((c >> 1) | (c << 27));
d = ((d >> 1) | (d << 27));
}
shifts >>= 1;
c &= 0x0fffffff;
d &= 0x0fffffff;
s = SKB[0, (c) & 0x3f] |
SKB[1, ((c >> 6 ) & 0x03)|((c >> 7 ) & 0x3c)] |
SKB[2, ((c >> 13) & 0x0f)|((c >> 14) & 0x30)] |
SKB[3, ((c >> 20) & 0x01)|((c >> 21) & 0x06) | ((c >> 22) & 0x38)];
t = SKB[4, (d) & 0x3f] |
SKB[5, ((d >> 7 ) & 0x03) | ((d >> 8 ) & 0x3c)] |
SKB[6, (d >> 15) & 0x3f ] |
SKB[7, ((d >> 21) & 0x0f) | ((d >> 22) & 0x30)];
_key[i * 2] = ((t << 16) | (s & 0xffff));
s = ((s >> 16) | (t & 0xffff0000));
_key[(i * 2) + 1] = (s << 4) | (s >> 28);
}
}
public void BlockEncrypt(byte[] input, int inOffset, byte[] output, int outOffset) {
uint t;
int i;
uint[] lr = new uint[2];
lr[0] = CipherUtil.GetIntLE(input, inOffset);
lr[1] = CipherUtil.GetIntLE(input, inOffset + 4);
initPerm(lr);
t = (lr[1] << 1) | (lr[1] >> 31);
lr[1] = (lr[0] << 1) | (lr[0] >> 31);
lr[0] = t;
for (i = 0; i < 32; i += 4) {
desCipher1(lr, i);
desCipher2(lr, i + 2);
}
lr[0] = (lr[0] >> 1) | (lr[0] << 31);
lr[1] = (lr[1] >> 1) | (lr[1] << 31);
finalPerm(lr);
CipherUtil.PutIntLE(lr[0], output, outOffset);
CipherUtil.PutIntLE(lr[1], output, outOffset + 4);
}
public void BlockDecrypt(byte[] input, int inOffset, byte[] output, int outOffset) {
uint t;
int i;
uint[] lr = new uint[2];
lr[0] = CipherUtil.GetIntLE(input, inOffset);
lr[1] = CipherUtil.GetIntLE(input, inOffset + 4);
initPerm(lr);
t = (lr[1] << 1) | (lr[1] >> 31);
lr[1] = (lr[0] << 1) | (lr[0] >> 31);
lr[0] = t;
for (i = 30; i > 0; i -= 4) {
desCipher1(lr, i);
desCipher2(lr, i - 2);
}
lr[0] = (lr[0] >> 1) | (lr[0] << 31);
lr[1] = (lr[1] >> 1) | (lr[1] << 31);
finalPerm(lr);
CipherUtil.PutIntLE(lr[0], output, outOffset);
CipherUtil.PutIntLE(lr[1], output, outOffset + 4);
}
private void desCipher1(uint[] lr, int i) {
uint u = lr[1] ^ _key[i ];
uint t = lr[1] ^ _key[i + 1];
t = ((t >> 4) + (t << 28));
lr[0] ^= (SPTRANS[1, (t ) & 0x3f] |
SPTRANS[3, (t >> 8 ) & 0x3f] |
SPTRANS[5, (t >> 16) & 0x3f] |
SPTRANS[7, (t >> 24) & 0x3f] |
SPTRANS[0, (u ) & 0x3f] |
SPTRANS[2, (u >> 8 ) & 0x3f] |
SPTRANS[4, (u >> 16) & 0x3f] |
SPTRANS[6, (u >> 24) & 0x3f]);
}
private void desCipher2(uint[] lr, int i) {
uint u = lr[0] ^ _key[i ];
uint t = lr[0] ^ _key[i + 1];
t = ((t >> 4) + (t << 28));
lr[1] ^= (SPTRANS[1, (t ) & 0x3f] |
SPTRANS[3, (t >> 8 ) & 0x3f] |
SPTRANS[5, (t >> 16) & 0x3f] |
SPTRANS[7, (t >> 24) & 0x3f] |
SPTRANS[0, (u ) & 0x3f] |
SPTRANS[2, (u >> 8 ) & 0x3f] |
SPTRANS[4, (u >> 16) & 0x3f] |
SPTRANS[6, (u >> 24) & 0x3f]);
}
private static void initPerm(uint[] lr) {
uint t = ((lr[1] >> 4) ^ lr[0]) & 0x0f0f0f0f;
lr[0] ^= t;
lr[1] ^= t << 4;
t = ((lr[0] >> 16) ^ lr[1]) & 0x0000ffff;
lr[1] ^= t;
lr[0] ^= t << 16;
t = ((lr[1] >> 2) ^ lr[0]) & 0x33333333;
lr[0] ^= t;
lr[1] ^= t << 2;
t = ((lr[0] >> 8) ^ lr[1]) & 0x00ff00ff;
lr[1] ^= t;
lr[0] ^= t << 8;
t = ((lr[1] >> 1) ^ lr[0]) & 0x55555555;
lr[0] ^= t;
lr[1] ^= t << 1;
}
private static void finalPerm(uint[] lr) {
uint t = ((lr[1] >> 1) ^ lr[0]) & 0x55555555;
lr[0] ^= t;
lr[1] ^= t << 1;
t = ((lr[0] >> 8) ^ lr[1]) & 0x00ff00ff;
lr[1] ^= t;
lr[0] ^= t << 8;
t = ((lr[1] >> 2) ^ lr[0]) & 0x33333333;
lr[0] ^= t;
lr[1] ^= t << 2;
t = ((lr[0] >> 16) ^ lr[1]) & 0x0000ffff;
lr[1] ^= t;
lr[0] ^= t << 16;
t = ((lr[1] >> 4) ^ lr[0]) & 0x0f0f0f0f;
lr[0] ^= t;
lr[1] ^= t << 4;
}
public void EncryptCBC(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
int nBlocks = inputLen / 8;
for(int bc = 0; bc < nBlocks; bc++) {
CipherUtil.BlockXor(input, inputOffset, 8, _iv, 0);
BlockEncrypt(_iv, 0, output, outputOffset);
Array.Copy(output, outputOffset, _iv, 0, 8);
inputOffset += 8;
outputOffset += 8;
}
}
public void DecryptCBC(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
int nBlocks = inputLen / 8;
for(int bc = 0; bc < nBlocks; bc++) {
BlockDecrypt(input, inputOffset, _temp, 0);
for(int i = 0; i < 8; i++) {
_temp[i] ^= _iv[i];
_iv[i] = input[inputOffset + i];
output[outputOffset + i] = _temp[i];
}
inputOffset += 8;
outputOffset += 8;
}
}
/*
* Copyright (C) 1993 Eric Young
*/
private static readonly uint[,] SKB = new uint[,] {
/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
{ 0x00000000,0x00000010,0x20000000,0x20000010,
0x00010000,0x00010010,0x20010000,0x20010010,
0x00000800,0x00000810,0x20000800,0x20000810,
0x00010800,0x00010810,0x20010800,0x20010810,
0x00000020,0x00000030,0x20000020,0x20000030,
0x00010020,0x00010030,0x20010020,0x20010030,
0x00000820,0x00000830,0x20000820,0x20000830,
0x00010820,0x00010830,0x20010820,0x20010830,
0x00080000,0x00080010,0x20080000,0x20080010,
0x00090000,0x00090010,0x20090000,0x20090010,
0x00080800,0x00080810,0x20080800,0x20080810,
0x00090800,0x00090810,0x20090800,0x20090810,
0x00080020,0x00080030,0x20080020,0x20080030,
0x00090020,0x00090030,0x20090020,0x20090030,
0x00080820,0x00080830,0x20080820,0x20080830,
0x00090820,0x00090830,0x20090820,0x20090830 },
/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
{ 0x00000000,0x02000000,0x00002000,0x02002000,
0x00200000,0x02200000,0x00202000,0x02202000,
0x00000004,0x02000004,0x00002004,0x02002004,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -