DES 加密仅适用于硬编码的位数组,但在读取文件时.txt失败
本文关键字:读取 文件 失败 txt 数组 适用于 加密 编码 DES | 更新日期: 2023-09-27 18:35:46
我知道这似乎是一个模糊的问题,但我需要了解DES en c#的人的帮助。
我有一个手动执行 DES 加密的项目,而无需使用 .NET 框架中的任何内置库。这非常重要,所以我不需要任何建议,例如使用该扩展的库:)
我一直在关注这个例子:DES 算法图解,一切正常,经过 16 次迭代后,我得到了该站点上所示的结果。
我认为问题在于我从String
到List<BitArray>
的转换,因为在遵循站点示例时,我将消息和键值硬编码为BitArray
。尽管在创建以byte
作为值的新BitArray
时,它会将值转过来,这意味着最高有效位在左侧,但我的所有代码都已调整为此。
我知道这是很多代码,但请记住,如果我使用此站点上的硬编码位,此代码确实有效。
以下是我获得List<BitArray>
的方式:
private List<BitArray> splitFileIntoBlocksOf8Bytes()
{
String bericht; //Nog niet van toepassing, maar legt het principe van feedback weer ;)
List<BitArray> lstByteBlocks = splitByteArray8(Streamers.getFileInBytes(strPathForSourceFile));
if (lstByteBlocks.Count == 0)
bericht = "Het bestand dat u gekozen heeft is een leeg bestand";
return lstByteBlocks;
}
//NOTICE how I turn each byte array around and revers the BitArray so it matches the logic found on the site!
private List<BitArray> splitByteArray8(byte[] arrBytes)
{
List<BitArray> lstChunks = new List<BitArray>();
byte[] chunkOfBytes = new byte[8];
try
{
for (int byteAdded = 0; byteAdded < arrBytes.Length; byteAdded += 8)
{
Array.Copy(arrBytes, 0 + byteAdded, chunkOfBytes, 0, 8);
Array.Reverse(chunkOfBytes);
lstChunks.Add(Arrays.ReverseBitArray(new BitArray(chunkOfBytes)));
}
}
catch (ArgumentException)
{
BitArray addedBits = new BitArray(64);
chunkOfBytes = new byte[8];
int bitsToAdd = (int) Convert.ToInt32(64 - (Math.Ceiling(arrBytes.Length % 8.0) * 8));
for (int bitAdded = 0; bitAdded < (arrBytes.Length * 8 - bitsToAdd); bitAdded++)
{
addedBits[bitAdded] = true;
}
Array.Copy(arrBytes, (arrBytes.Length - ((64 - bitsToAdd) / 8)), chunkOfBytes, 0, ((64 - bitsToAdd) / 8));
lstChunks.Add(new BitArray(chunkOfBytes));
lstChunks.Add(addedBits);
}
return lstChunks;
}
这是迭代代码(每个块都经过这个函数:
//lstEncodedFile = new List<byte[]>();
BitArray arrBlock = (BitArray)((object[]) args)[0];
BitArray arrPremutedBlock = initialPremutation(arrBlock, Arrays.InitielePremutatieArray);
BitArray arrLeftBits = new BitArray(32);
BitArray arrRightBits = new BitArray(32);
BitArray arrTempLeft;
for (int bitCounter = 0; bitCounter < 32; bitCounter++)
{
arrLeftBits.Set(bitCounter, arrPremutedBlock.Get(bitCounter));
arrRightBits.Set(bitCounter, arrPremutedBlock.Get(bitCounter + 32));
}
int intStartIteratie = 0, intStopIteratie = 16, intStapIteratie = 1;
if (cryptType == CryptType.DECRYPT)
{
intStartIteratie = 15;
intStopIteratie = -1;
intStapIteratie = -1;
}
for (int intIteratie = intStartIteratie; intIteratie != intStopIteratie; intIteratie += intStapIteratie) // 15 iteraties
{
arrTempLeft = arrLeftBits;
arrLeftBits = arrRightBits; //Li = R(i-1)
arrRightBits = arrTempLeft.Xor(feistel.getFeistelResult(Arrays.ExpandBitArray(arrRightBits), intIteratie)); // Ri = L(i-1) XOR f(Ri, K(i+1))
}
BitArray arrIterationResult = new BitArray(64);
for (int bitCounter = 0; bitCounter < 32; bitCounter++)
{
arrIterationResult.Set(bitCounter, arrRightBits.Get(bitCounter));
arrIterationResult.Set(bitCounter + 32, arrLeftBits.Get(bitCounter));
}
byte[] byteResult = new byte[8];
BitArray arrResult = initialPremutation(arrIterationResult, Arrays.LaatstePremutatieArray);
arrResult.CopyTo(byteResult, 0);
lstCodedFile.Insert(intBlockCounter++, byteResult);
如果您还无法发现任何错误,这里是 feistel 函数:
public BitArray getFeistelResult(BitArray arrHalfBlock, int indexSubSleutel)
{
BitArray Subkey = lijstSubkeys[indexSubSleutel];
BitArray XoredHalfBlockAndSubkey = arrHalfBlock.Xor(Subkey);
BitArray Result = Sboxen(XoredHalfBlockAndSubkey);
return Result;
}
和 Sboxen 函数:
private BitArray Sboxen(BitArray array)
{
List<int> lijsStartIndex = new List<int>();
int sbox1Startindex = 5;
int sbox2Startindex = 11;
int sbox3Startindex = 17;
int sbox4Startindex = 23;
int sbox5Startindex = 29;
int sbox6Startindex = 35;
int sbox7Startindex = 41;
int sbox8Startindex = 47;
#region SBOXEN genereren
//haal telkens de waarde uit de array van 48 bits en maak telkens een sbox ervan
BitArray Sbox1 = GenerateSbox(array.Get(sbox1Startindex),
array.Get(sbox1Startindex - 1),
array.Get(sbox1Startindex - 2),
array.Get(sbox1Startindex - 3),
array.Get(sbox1Startindex - 4),
array.Get(sbox1Startindex - 5));
BitArray Sbox2 = GenerateSbox(array.Get(sbox2Startindex),
array.Get(sbox2Startindex - 1),
array.Get(sbox2Startindex - 2),
array.Get(sbox2Startindex - 3),
array.Get(sbox2Startindex - 4),
array.Get(sbox2Startindex - 5));
BitArray Sbox3 = GenerateSbox(array.Get(sbox3Startindex),
array.Get(sbox3Startindex - 1),
array.Get(sbox3Startindex - 2),
array.Get(sbox3Startindex - 3),
array.Get(sbox3Startindex - 4),
array.Get(sbox3Startindex - 5));
BitArray Sbox4 = GenerateSbox(array.Get(sbox4Startindex),
array.Get(sbox4Startindex - 1),
array.Get(sbox4Startindex - 2),
array.Get(sbox4Startindex - 3),
array.Get(sbox4Startindex - 4),
array.Get(sbox4Startindex - 5));
BitArray Sbox5 = GenerateSbox(array.Get(sbox5Startindex),
array.Get(sbox5Startindex - 1),
array.Get(sbox5Startindex - 2),
array.Get(sbox5Startindex - 3),
array.Get(sbox5Startindex - 4),
array.Get(sbox5Startindex - 5));
BitArray Sbox6 = GenerateSbox(array.Get(sbox6Startindex),
array.Get(sbox6Startindex - 1),
array.Get(sbox6Startindex - 2),
array.Get(sbox6Startindex - 3),
array.Get(sbox6Startindex - 4),
array.Get(sbox6Startindex - 5));
BitArray Sbox7 = GenerateSbox(array.Get(sbox7Startindex),
array.Get(sbox7Startindex - 1),
array.Get(sbox7Startindex - 2),
array.Get(sbox7Startindex - 3),
array.Get(sbox7Startindex - 4),
array.Get(sbox7Startindex - 5));
BitArray Sbox8 = GenerateSbox(array.Get(sbox8Startindex),
array.Get(sbox8Startindex - 1),
array.Get(sbox8Startindex - 2),
array.Get(sbox8Startindex - 3),
array.Get(sbox8Startindex - 4),
array.Get(sbox8Startindex - 5));
#endregion SBOXEN genereren
//deze functie gaat de int waarde ophalen uit Arrays.SBoxArrays
BitArray sbox1Value = new BitArray(getValueFromSbox(Sbox1, 0));
BitArray sbox2Value = new BitArray(getValueFromSbox(Sbox2, 1));
BitArray sbox3Value = new BitArray(getValueFromSbox(Sbox3, 2));
BitArray sbox4Value = new BitArray(getValueFromSbox(Sbox4, 3));
BitArray sbox5Value = new BitArray(getValueFromSbox(Sbox5, 4));
BitArray sbox6Value = new BitArray(getValueFromSbox(Sbox6, 5));
BitArray sbox7Value = new BitArray(getValueFromSbox(Sbox7, 6));
BitArray sbox8Value = new BitArray(getValueFromSbox(Sbox8, 7));
bool[] CombinedSboxen = new bool[32];
sbox1Value.CopyTo(CombinedSboxen, 0);
sbox2Value.CopyTo(CombinedSboxen, 4);
sbox3Value.CopyTo(CombinedSboxen, 8);
sbox4Value.CopyTo(CombinedSboxen, 12);
sbox5Value.CopyTo(CombinedSboxen, 16);
sbox6Value.CopyTo(CombinedSboxen, 20);
sbox7Value.CopyTo(CombinedSboxen, 24);
sbox8Value.CopyTo(CombinedSboxen, 28);
return Arrays.SBoxPremutatie(CombinedSboxen);
}
下面是getValueFromSbox函数:
private BitArray getValueFromSbox(BitArray array, int WichSbox)
{
BitArray arrayRow = new BitArray(2);
BitArray arrayColumn = new BitArray(4);
arrayRow.Set(0, array.Get(0)); //de eerste en de laatste bit nemen voor de rij
arrayRow.Set(1, array.Get(5));
arrayColumn.Set(0, array.Get(1)); //de overige 4 bits voor de kolom
arrayColumn.Set(1, array.Get(2));
arrayColumn.Set(2, array.Get(3));
arrayColumn.Set(3, array.Get(4));
int Row = CalculateToInteger(Arrays.ReverseBitArray(arrayRow)); //lengte 2
int column = CalculateToInteger(Arrays.ReverseBitArray(arrayColumn)); // lengte 4
Byte b = Arrays.SBoxArrays[WichSbox, Row, column];
BitArray bit = new BitArray(BitConverter.GetBytes(b).ToArray());
BitArray SboxValue = new BitArray(4);
SboxValue.Set(0, bit.Get(3));
SboxValue.Set(1, bit.Get(2));
SboxValue.Set(2, bit.Get(1));
SboxValue.Set(3, bit.Get(0));
return SboxValue;
}
最后是 CalculateToInteger 函数:
private int CalculateToInteger(BitArray array)
{
double result = 0;
for (int counter = 0; counter < array.Count; counter++)
{
if (array[array.Length - 1 - counter] == true)
result += Math.Pow(2, counter);
}
return Convert.ToInt32(result);
}
编辑:加密0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
会导致加密后10000101 11101000 00010011 01010100 00001111 00001010 10110100 00000101
,这就是我想要的,
加密 8 字节字符串时Testjeuh
我得到Ô§”'YDÕ¸
结果,这不是我想要的。
这不是一个答案,但写一些单元测试(我知道我在滥用这个词)。 您的第一个测试应该是这样的:
BitArray inputData = BitarrayFromRandomData();
var encryptedBits = DesEncryptor.Encrypt(inputData, key);
BitArray outputData = DesEncryptor.Decrypt(outputData, key);
如果outputData
的内容与inputData
的内容匹配,则问题不在 DES 实现中。 下一个测试是查看在字节和位之间转换的代码
byte[] inputData = ByteArrayFromRandomData();
BitArray intermediateData = BitarrayHelpers.FromByteArray(inputData);
byte[] outputData = BitArrayHelpers.ToByteArray(intermediateData);
请注意,这里没有加密步骤,因为我们在第一次测试中已经排除了这一点。 为字符串和字节数组之间的转换编写一个类似的测试,并编写一个涵盖整个事情的最终测试,一旦前三个通过,最后一个也应该通过。
这将允许您将注意力(和 SO 问题)集中在损坏的代码上,而不是整个 DES 实现上。