Расшифровка C# дает неверный результат [Обновление 1]
В моей программе происходит следующее.
Произвольная строка генерируется и шифруется.Это процедура шифрования:
private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c }; //TODO: The SALT needs to be derived and unique for each user! internal byte[] Encrypt(byte[] plain) { string password = Properties.Settings.Default.PasswordOne; MemoryStream memoryStream; CryptoStream cryptoStream; Rijndael rijndael = Rijndael.Create(); rijndael.Padding = PaddingMode.Zeros; Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT); rijndael.Key = pdb.GetBytes(32); rijndael.IV = pdb.GetBytes(16); memoryStream = new MemoryStream(); cryptoStream = new CryptoStream(memoryStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write); cryptoStream.Write(plain, 0, plain.Length); cryptoStream.Close(); return memoryStream.ToArray(); }
Эта зашифрованная строка сохраняется в файле с именем DEFT.Это процедура сохранения:
private void CreateDeft2(FileSystemEncryption fse, string Deft2FileName, string drive) { if (DrivesLog != null) DrivesLog("Creating DEFT2"); FileStream fs = null; StreamWriter sw = null; string location = Path.Combine(drive, Deft2FileName); try { fs = new FileStream(location, FileMode.CreateNew, FileAccess.Write, FileShare.None); sw = new StreamWriter(fs, Encoding.Unicode); if (DrivesLog != null) DrivesLog("Creating Random Contents"); string fakeContents = CreateRandomString(1024000); // Create the fake contents if (DrivesLog != null) DrivesLog("Converting Random Contents to Bytes"); byte[] bFakeContents = GetBytes(fakeContents); // Convert to bytes if (DrivesLog != null) DrivesLog("Encrypting Random Content Bytes"); byte[] ebFakeContents = fse.Encrypt(bFakeContents); // Encrypt if (DrivesLog != null) DrivesLog("Converting Encrypted Bytes to String"); string sedFakeContents = GetString(ebFakeContents); // Convert to string if (DrivesLog != null) DrivesLog("Writing DEFT2"); sw.Write(sedFakeContents); // Write it out fs.Flush(); // Flush the buffer sw.Close(); fs.Close(); if (DrivesLog != null) DrivesLog("Successfully Created DEFT2"); } catch (Exception ex) { if (DrivesLog != null) DrivesLog("Failed to Create DEFT2 " + ex.Message); sw.Close(); fs.Close(); } }
В определенном месте в файле DEFT создается и сохраняется другая строка из 32 символов.Вот код для этого:
private void InsertDEFT2NameLength(FileSystemEncryption fse, FileStream fs, StreamWriter sw) { if (DrivesLog != null) DrivesLog("Inserting DEFT2 Name"); string deft2NameLength = "0"; // init the length if (DrivesLog != null) DrivesLog("Converting DEFT2 Name to Bytes"); if (fDEFT2Name.Length < 32) { for (int idx = fDEFT2Name.Length; idx < 32; idx++) { fDEFT2Name = fDEFT2Name + "!"; } } byte[] bdeft2Name = GetBytes(fDEFT2Name); // convert filename to bytes if (DrivesLog != null) DrivesLog("Encrypting DEFT2 Name"); byte[] ebdeft2Name = fse.Encrypt(bdeft2Name); // Encrypt if (DrivesLog != null) DrivesLog("Getting Length of Encrypted DEFT2 Name"); long ebdeft2NameLength = ebdeft2Name.LongLength; // Get Length of the Encrypted Bytes as a long if (DrivesLog != null) DrivesLog("Converting DEFT2 Name Length to String"); string sebdeft2NameLength = ebdeft2NameLength.ToString(); // Convert Length to string Add Shebang so we know when we have read the full length if (DrivesLog != null) DrivesLog("Converting DEFT2 Name Length to Bytes"); byte[] bsebdeft2NameLength = GetBytes(sebdeft2NameLength); // Convert length string to bytes if (DrivesLog != null) DrivesLog("Encrypting DEFT2 Name Length"); byte[] ebsebdeft2NameLength = fse.Encrypt(bsebdeft2NameLength); // Encrypt if (DrivesLog != null) DrivesLog("Converting Encrypted DEFT2 Name Length to String"); deft2NameLength = GetString(ebsebdeft2NameLength); // Convert to string if (DrivesLog != null) DrivesLog("Seeking to Correct Location"); long startPos = GenerateDEFT2LengthStartPosition(); fs.Seek(startPos, SeekOrigin.Current); // Seek to correct location if (DrivesLog != null) DrivesLog("New Position " + startPos.ToString("N0")); if (DrivesLog != null) DrivesLog("Writing Encrypted Name Length to New Position"); sw.Write(deft2NameLength); // Write the Encrypted length fs.Flush(); // Flush the buffer immediately }
Затем я пытаюсь расшифровать эту новую строку. Это расшифровывает строку (или, по крайней мере, так должно быть!)
private long ReadDEFT2Len (строка DEFT, long lenPos, FileSystemEncryption fse) { if (DrivesLog!= null) DrivesLog("Чтение длины имени DEFT2"); StringBuilder sb = new StringBuilder();
FileStream fs = null; StreamReader sr = null; try { fs = new FileStream(DEFT, FileMode.Open, FileAccess.Read, FileShare.Read); sr = new StreamReader(fs, Encoding.Unicode); char[] C = new char[32]; fs.Seek(lenPos, SeekOrigin.Begin); sr.Read(C, 0, 32); string sC = new string(C); byte[] bsC = GetBytes(sC); byte[] dRes = fse.Decrypt(bsC); string sbdRes = GetString(dRes); foreach (char ic in sbdRes) { if (ic == '!') break; sb.Append(ic.ToString()); } sr.Close(); fs.Close(); if (DrivesLog != null) DrivesLog("DEFT2 Name Length = " + sb.ToString()); return long.Parse(sb.ToString()); } catch (Exception ex) { if (DrivesLog != null) DrivesLog("ERROR Reading DEFT2 Name Length " + ex.Message); if (sr != null) sr.Close(); if (fs != null) fs.Close(); return -1; } }
Извините за форматирование - он просто не будет играть хорошо!
Процедура дешифрования не дешифрует исходную строку - она просто возвращает непонятный текст. Расшифровка маршрутизации здесь:
internal byte[] Decrypt(byte[] cipher)
{
string password = Properties.Settings.Default.PasswordOne;
MemoryStream memoryStream;
CryptoStream cryptoStream;
Rijndael rijndael = Rijndael.Create();
rijndael.Padding = PaddingMode.Zeros;
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
rijndael.Key = pdb.GetBytes(32);
rijndael.IV = pdb.GetBytes(16);
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write);
cryptoStream.Write(cipher, 0, cipher.Length);
cryptoStream.FlushFinalBlock();
cryptoStream.Close();
return memoryStream.ToArray();
}
Он использует ту же соль, что и шифратор. Пароль тот же, а количество прочитанных байтов одинаковое и из правильного места в файле. Итак, есть идеи, почему это так?
ОБНОВЛЕНИЕ 1:
Этот код предоставляет мне место, куда я вставлю в ранее созданный зашифрованный файл DEFT новый фрагмент информации.
private long GenerateDEFT2LengthStartPosition()
{
if (DrivesLog != null) DrivesLog("Generating DEFT2 Length Start Position");
return long.Parse((Properties.Settings.Default.PasswordOne.Length * Properties.Settings.Default.PasswordOne.Length).ToString());
}
Пока я использую тот же пароль, который он будет использовать при сохранении (для целей тестирования), он будет возвращать то же место, чтобы вставить вновь зашифрованный текст. В этом случае всегда возвращается 100.
Однако в шестнадцатеричном редакторе, использующем десятичные дроби для смещений, он показывает, что вновь зашифрованный текст сохраняется со смещением 418.
Зачем сохранять текст так:
long startPos = GenerateDEFT2LengthStartPosition();
fs.Seek(startPos, SeekOrigin.Current); // Seek to correct location
sw.Write(deft2NameLength);
и загружаем это так:
long lenPos = GenerateDEFT2LengthStartPosition();
char[] C = new char[32];
fs.Seek(lenPos, SeekOrigin.Begin);
sr.Read(C, 0, 32);
поместить меня в совершенно другое положение в файле?
Итак, Вопрос: Почему используется одно и то же значение 100 для записи и чтения зашифрованного текста в файле, помещая текст в другое место, откуда он читается?