在我的程序中会发生以下情况。
生成并加密随机字符串 这是加密例程:
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(string DEFT,long lenPos,FileSystemEncryption fse) { if(DrivesLog!= null)DrivesLog(&#34;读取DEFT2名称长度&#34;); 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返回。
但是,在Hex编辑器中使用Decimals作为偏移量时,它显示新加密的文本存储在偏移量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来编写和读取 文件中的加密文本,将文本放在不同的位置 从哪里读取?