311 lines
11 KiB
C#
311 lines
11 KiB
C#
using System;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
using Org.BouncyCastle.Crypto.Utilities;
|
|
using Org.BouncyCastle.Utilities;
|
|
|
|
namespace Org.BouncyCastle.Crypto.Engines;
|
|
|
|
public class DesEngine : IBlockCipher
|
|
{
|
|
internal const int BLOCK_SIZE = 8;
|
|
|
|
private int[] workingKey;
|
|
|
|
private static readonly short[] bytebit = new short[8] { 128, 64, 32, 16, 8, 4, 2, 1 };
|
|
|
|
private static readonly int[] bigbyte = new int[24]
|
|
{
|
|
8388608, 4194304, 2097152, 1048576, 524288, 262144, 131072, 65536, 32768, 16384,
|
|
8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16,
|
|
8, 4, 2, 1
|
|
};
|
|
|
|
private static readonly byte[] pc1 = new byte[56]
|
|
{
|
|
56, 48, 40, 32, 24, 16, 8, 0, 57, 49,
|
|
41, 33, 25, 17, 9, 1, 58, 50, 42, 34,
|
|
26, 18, 10, 2, 59, 51, 43, 35, 62, 54,
|
|
46, 38, 30, 22, 14, 6, 61, 53, 45, 37,
|
|
29, 21, 13, 5, 60, 52, 44, 36, 28, 20,
|
|
12, 4, 27, 19, 11, 3
|
|
};
|
|
|
|
private static readonly byte[] totrot = new byte[16]
|
|
{
|
|
1, 2, 4, 6, 8, 10, 12, 14, 15, 17,
|
|
19, 21, 23, 25, 27, 28
|
|
};
|
|
|
|
private static readonly byte[] pc2 = new byte[48]
|
|
{
|
|
13, 16, 10, 23, 0, 4, 2, 27, 14, 5,
|
|
20, 9, 22, 18, 11, 3, 25, 7, 15, 6,
|
|
26, 19, 12, 1, 40, 51, 30, 36, 46, 54,
|
|
29, 39, 50, 44, 32, 47, 43, 48, 38, 55,
|
|
33, 52, 45, 41, 49, 35, 28, 31
|
|
};
|
|
|
|
private static readonly uint[] SP1 = new uint[64]
|
|
{
|
|
16843776u, 0u, 65536u, 16843780u, 16842756u, 66564u, 4u, 65536u, 1024u, 16843776u,
|
|
16843780u, 1024u, 16778244u, 16842756u, 16777216u, 4u, 1028u, 16778240u, 16778240u, 66560u,
|
|
66560u, 16842752u, 16842752u, 16778244u, 65540u, 16777220u, 16777220u, 65540u, 0u, 1028u,
|
|
66564u, 16777216u, 65536u, 16843780u, 4u, 16842752u, 16843776u, 16777216u, 16777216u, 1024u,
|
|
16842756u, 65536u, 66560u, 16777220u, 1024u, 4u, 16778244u, 66564u, 16843780u, 65540u,
|
|
16842752u, 16778244u, 16777220u, 1028u, 66564u, 16843776u, 1028u, 16778240u, 16778240u, 0u,
|
|
65540u, 66560u, 0u, 16842756u
|
|
};
|
|
|
|
private static readonly uint[] SP2 = new uint[64]
|
|
{
|
|
2148565024u, 2147516416u, 32768u, 1081376u, 1048576u, 32u, 2148532256u, 2147516448u, 2147483680u, 2148565024u,
|
|
2148564992u, 2147483648u, 2147516416u, 1048576u, 32u, 2148532256u, 1081344u, 1048608u, 2147516448u, 0u,
|
|
2147483648u, 32768u, 1081376u, 2148532224u, 1048608u, 2147483680u, 0u, 1081344u, 32800u, 2148564992u,
|
|
2148532224u, 32800u, 0u, 1081376u, 2148532256u, 1048576u, 2147516448u, 2148532224u, 2148564992u, 32768u,
|
|
2148532224u, 2147516416u, 32u, 2148565024u, 1081376u, 32u, 32768u, 2147483648u, 32800u, 2148564992u,
|
|
1048576u, 2147483680u, 1048608u, 2147516448u, 2147483680u, 1048608u, 1081344u, 0u, 2147516416u, 32800u,
|
|
2147483648u, 2148532256u, 2148565024u, 1081344u
|
|
};
|
|
|
|
private static readonly uint[] SP3 = new uint[64]
|
|
{
|
|
520u, 134349312u, 0u, 134348808u, 134218240u, 0u, 131592u, 134218240u, 131080u, 134217736u,
|
|
134217736u, 131072u, 134349320u, 131080u, 134348800u, 520u, 134217728u, 8u, 134349312u, 512u,
|
|
131584u, 134348800u, 134348808u, 131592u, 134218248u, 131584u, 131072u, 134218248u, 8u, 134349320u,
|
|
512u, 134217728u, 134349312u, 134217728u, 131080u, 520u, 131072u, 134349312u, 134218240u, 0u,
|
|
512u, 131080u, 134349320u, 134218240u, 134217736u, 512u, 0u, 134348808u, 134218248u, 131072u,
|
|
134217728u, 134349320u, 8u, 131592u, 131584u, 134217736u, 134348800u, 134218248u, 520u, 134348800u,
|
|
131592u, 8u, 134348808u, 131584u
|
|
};
|
|
|
|
private static readonly uint[] SP4 = new uint[64]
|
|
{
|
|
8396801u, 8321u, 8321u, 128u, 8396928u, 8388737u, 8388609u, 8193u, 0u, 8396800u,
|
|
8396800u, 8396929u, 129u, 0u, 8388736u, 8388609u, 1u, 8192u, 8388608u, 8396801u,
|
|
128u, 8388608u, 8193u, 8320u, 8388737u, 1u, 8320u, 8388736u, 8192u, 8396928u,
|
|
8396929u, 129u, 8388736u, 8388609u, 8396800u, 8396929u, 129u, 0u, 0u, 8396800u,
|
|
8320u, 8388736u, 8388737u, 1u, 8396801u, 8321u, 8321u, 128u, 8396929u, 129u,
|
|
1u, 8192u, 8388609u, 8193u, 8396928u, 8388737u, 8193u, 8320u, 8388608u, 8396801u,
|
|
128u, 8388608u, 8192u, 8396928u
|
|
};
|
|
|
|
private static readonly uint[] SP5 = new uint[64]
|
|
{
|
|
256u, 34078976u, 34078720u, 1107296512u, 524288u, 256u, 1073741824u, 34078720u, 1074266368u, 524288u,
|
|
33554688u, 1074266368u, 1107296512u, 1107820544u, 524544u, 1073741824u, 33554432u, 1074266112u, 1074266112u, 0u,
|
|
1073742080u, 1107820800u, 1107820800u, 33554688u, 1107820544u, 1073742080u, 0u, 1107296256u, 34078976u, 33554432u,
|
|
1107296256u, 524544u, 524288u, 1107296512u, 256u, 33554432u, 1073741824u, 34078720u, 1107296512u, 1074266368u,
|
|
33554688u, 1073741824u, 1107820544u, 34078976u, 1074266368u, 256u, 33554432u, 1107820544u, 1107820800u, 524544u,
|
|
1107296256u, 1107820800u, 34078720u, 0u, 1074266112u, 1107296256u, 524544u, 33554688u, 1073742080u, 524288u,
|
|
0u, 1074266112u, 34078976u, 1073742080u
|
|
};
|
|
|
|
private static readonly uint[] SP6 = new uint[64]
|
|
{
|
|
536870928u, 541065216u, 16384u, 541081616u, 541065216u, 16u, 541081616u, 4194304u, 536887296u, 4210704u,
|
|
4194304u, 536870928u, 4194320u, 536887296u, 536870912u, 16400u, 0u, 4194320u, 536887312u, 16384u,
|
|
4210688u, 536887312u, 16u, 541065232u, 541065232u, 0u, 4210704u, 541081600u, 16400u, 4210688u,
|
|
541081600u, 536870912u, 536887296u, 16u, 541065232u, 4210688u, 541081616u, 4194304u, 16400u, 536870928u,
|
|
4194304u, 536887296u, 536870912u, 16400u, 536870928u, 541081616u, 4210688u, 541065216u, 4210704u, 541081600u,
|
|
0u, 541065232u, 16u, 16384u, 541065216u, 4210704u, 16384u, 4194320u, 536887312u, 0u,
|
|
541081600u, 536870912u, 4194320u, 536887312u
|
|
};
|
|
|
|
private static readonly uint[] SP7 = new uint[64]
|
|
{
|
|
2097152u, 69206018u, 67110914u, 0u, 2048u, 67110914u, 2099202u, 69208064u, 69208066u, 2097152u,
|
|
0u, 67108866u, 2u, 67108864u, 69206018u, 2050u, 67110912u, 2099202u, 2097154u, 67110912u,
|
|
67108866u, 69206016u, 69208064u, 2097154u, 69206016u, 2048u, 2050u, 69208066u, 2099200u, 2u,
|
|
67108864u, 2099200u, 67108864u, 2099200u, 2097152u, 67110914u, 67110914u, 69206018u, 69206018u, 2u,
|
|
2097154u, 67108864u, 67110912u, 2097152u, 69208064u, 2050u, 2099202u, 69208064u, 2050u, 67108866u,
|
|
69208066u, 69206016u, 2099200u, 0u, 2u, 69208066u, 0u, 2099202u, 69206016u, 2048u,
|
|
67108866u, 67110912u, 2048u, 2097154u
|
|
};
|
|
|
|
private static readonly uint[] SP8 = new uint[64]
|
|
{
|
|
268439616u, 4096u, 262144u, 268701760u, 268435456u, 268439616u, 64u, 268435456u, 262208u, 268697600u,
|
|
268701760u, 266240u, 268701696u, 266304u, 4096u, 64u, 268697600u, 268435520u, 268439552u, 4160u,
|
|
266240u, 262208u, 268697664u, 268701696u, 4160u, 0u, 0u, 268697664u, 268435520u, 268439552u,
|
|
266304u, 262144u, 266304u, 262144u, 268701696u, 4096u, 64u, 268697664u, 4096u, 266304u,
|
|
268439552u, 64u, 268435520u, 268697600u, 268697664u, 268435456u, 262144u, 268439616u, 0u, 268701760u,
|
|
262208u, 268435520u, 268697600u, 268439552u, 268439616u, 0u, 268701760u, 266240u, 266240u, 4160u,
|
|
4160u, 262208u, 268435456u, 268701696u
|
|
};
|
|
|
|
public virtual string AlgorithmName => "DES";
|
|
|
|
public virtual bool IsPartialBlockOkay => false;
|
|
|
|
public virtual int[] GetWorkingKey()
|
|
{
|
|
return workingKey;
|
|
}
|
|
|
|
public virtual void Init(bool forEncryption, ICipherParameters parameters)
|
|
{
|
|
if (!(parameters is KeyParameter))
|
|
{
|
|
throw new ArgumentException("invalid parameter passed to DES init - " + Platform.GetTypeName(parameters));
|
|
}
|
|
workingKey = GenerateWorkingKey(forEncryption, ((KeyParameter)parameters).GetKey());
|
|
}
|
|
|
|
public virtual int GetBlockSize()
|
|
{
|
|
return 8;
|
|
}
|
|
|
|
public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
|
|
{
|
|
if (workingKey == null)
|
|
{
|
|
throw new InvalidOperationException("DES engine not initialised");
|
|
}
|
|
Check.DataLength(input, inOff, 8, "input buffer too short");
|
|
Check.OutputLength(output, outOff, 8, "output buffer too short");
|
|
DesFunc(workingKey, input, inOff, output, outOff);
|
|
return 8;
|
|
}
|
|
|
|
public virtual void Reset()
|
|
{
|
|
}
|
|
|
|
protected static int[] GenerateWorkingKey(bool encrypting, byte[] key)
|
|
{
|
|
int[] array = new int[32];
|
|
bool[] array2 = new bool[56];
|
|
bool[] array3 = new bool[56];
|
|
for (int i = 0; i < 56; i++)
|
|
{
|
|
int num = pc1[i];
|
|
array2[i] = (key[num >>> 3] & bytebit[num & 7]) != 0;
|
|
}
|
|
for (int j = 0; j < 16; j++)
|
|
{
|
|
int num2 = ((!encrypting) ? (15 - j << 1) : (j << 1));
|
|
int num3 = num2 + 1;
|
|
array[num2] = (array[num3] = 0);
|
|
for (int k = 0; k < 28; k++)
|
|
{
|
|
int num4 = k + totrot[j];
|
|
if (num4 < 28)
|
|
{
|
|
array3[k] = array2[num4];
|
|
}
|
|
else
|
|
{
|
|
array3[k] = array2[num4 - 28];
|
|
}
|
|
}
|
|
for (int l = 28; l < 56; l++)
|
|
{
|
|
int num4 = l + totrot[j];
|
|
if (num4 < 56)
|
|
{
|
|
array3[l] = array2[num4];
|
|
}
|
|
else
|
|
{
|
|
array3[l] = array2[num4 - 28];
|
|
}
|
|
}
|
|
for (int m = 0; m < 24; m++)
|
|
{
|
|
if (array3[pc2[m]])
|
|
{
|
|
int[] array5;
|
|
int[] array4 = (array5 = array);
|
|
nint num5 = num2;
|
|
array4[num2] = array5[num5] | bigbyte[m];
|
|
}
|
|
if (array3[pc2[m + 24]])
|
|
{
|
|
int[] array5;
|
|
int[] array6 = (array5 = array);
|
|
nint num5 = num3;
|
|
array6[num3] = array5[num5] | bigbyte[m];
|
|
}
|
|
}
|
|
}
|
|
for (int n = 0; n != 32; n += 2)
|
|
{
|
|
int num6 = array[n];
|
|
int num7 = array[n + 1];
|
|
array[n] = ((num6 & 0xFC0000) << 6) | ((num6 & 0xFC0) << 10) | ((num7 & 0xFC0000) >>> 10) | ((num7 & 0xFC0) >>> 6);
|
|
array[n + 1] = ((num6 & 0x3F000) << 12) | ((num6 & 0x3F) << 16) | ((num7 & 0x3F000) >>> 4) | (num7 & 0x3F);
|
|
}
|
|
return array;
|
|
}
|
|
|
|
internal static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outBytes, int outOff)
|
|
{
|
|
uint num = Pack.BE_To_UInt32(input, inOff);
|
|
uint num2 = Pack.BE_To_UInt32(input, inOff + 4);
|
|
uint num3 = ((num >> 4) ^ num2) & 0xF0F0F0F;
|
|
num2 ^= num3;
|
|
num ^= num3 << 4;
|
|
num3 = ((num >> 16) ^ num2) & 0xFFFF;
|
|
num2 ^= num3;
|
|
num ^= num3 << 16;
|
|
num3 = ((num2 >> 2) ^ num) & 0x33333333;
|
|
num ^= num3;
|
|
num2 ^= num3 << 2;
|
|
num3 = ((num2 >> 8) ^ num) & 0xFF00FF;
|
|
num ^= num3;
|
|
num2 ^= num3 << 8;
|
|
num2 = (num2 << 1) | (num2 >> 31);
|
|
num3 = (num ^ num2) & 0xAAAAAAAAu;
|
|
num ^= num3;
|
|
num2 ^= num3;
|
|
num = (num << 1) | (num >> 31);
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
num3 = (num2 << 28) | (num2 >> 4);
|
|
num3 ^= (uint)wKey[i * 4];
|
|
uint num4 = SP7[num3 & 0x3F];
|
|
num4 |= SP5[(num3 >> 8) & 0x3F];
|
|
num4 |= SP3[(num3 >> 16) & 0x3F];
|
|
num4 |= SP1[(num3 >> 24) & 0x3F];
|
|
num3 = num2 ^ (uint)wKey[i * 4 + 1];
|
|
num4 |= SP8[num3 & 0x3F];
|
|
num4 |= SP6[(num3 >> 8) & 0x3F];
|
|
num4 |= SP4[(num3 >> 16) & 0x3F];
|
|
num4 |= SP2[(num3 >> 24) & 0x3F];
|
|
num ^= num4;
|
|
num3 = (num << 28) | (num >> 4);
|
|
num3 ^= (uint)wKey[i * 4 + 2];
|
|
num4 = SP7[num3 & 0x3F];
|
|
num4 |= SP5[(num3 >> 8) & 0x3F];
|
|
num4 |= SP3[(num3 >> 16) & 0x3F];
|
|
num4 |= SP1[(num3 >> 24) & 0x3F];
|
|
num3 = num ^ (uint)wKey[i * 4 + 3];
|
|
num4 |= SP8[num3 & 0x3F];
|
|
num4 |= SP6[(num3 >> 8) & 0x3F];
|
|
num4 |= SP4[(num3 >> 16) & 0x3F];
|
|
num4 |= SP2[(num3 >> 24) & 0x3F];
|
|
num2 ^= num4;
|
|
}
|
|
num2 = (num2 << 31) | (num2 >> 1);
|
|
num3 = (num ^ num2) & 0xAAAAAAAAu;
|
|
num ^= num3;
|
|
num2 ^= num3;
|
|
num = (num << 31) | (num >> 1);
|
|
num3 = ((num >> 8) ^ num2) & 0xFF00FF;
|
|
num2 ^= num3;
|
|
num ^= num3 << 8;
|
|
num3 = ((num >> 2) ^ num2) & 0x33333333;
|
|
num2 ^= num3;
|
|
num ^= num3 << 2;
|
|
num3 = ((num2 >> 16) ^ num) & 0xFFFF;
|
|
num ^= num3;
|
|
num2 ^= num3 << 16;
|
|
num3 = ((num2 >> 4) ^ num) & 0xF0F0F0F;
|
|
num ^= num3;
|
|
num2 ^= num3 << 4;
|
|
Pack.UInt32_To_BE(num2, outBytes, outOff);
|
|
Pack.UInt32_To_BE(num, outBytes, outOff + 4);
|
|
}
|
|
}
|