C# 要解密的数据长度无效
C# Length of data to decrypt is invalid
SO 上有很多类似的问题,但 "none" 符合我的问题。
我正在创建一个充满加密随机字节的文件。然后在这个文件中的特定位置我写了一些加密字节。当我尝试读取那部分字节时,我得到 "Length of data to decrypt is invalid".
这是加密和解密方法(在 SO 的某个时间点找到)
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();
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();
}
internal byte[] Decrypt(byte[] cipher)
{
string password = Properties.Settings.Default.PasswordOne;
MemoryStream memoryStream;
CryptoStream cryptoStream;
Rijndael rijndael = Rijndael.Create();
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.Close();
return memoryStream.ToArray();
}
我使用这个
将新数据保存在第一个文件中
private void InsertDEFT2NameLength(FileSystemEncryption fse, string Deft2FileName, FileStream fs, StreamWriter sw)
{
string deft2NameLength = "0"; // init the length
if (DrivesLog != null) DrivesLog("Converting DEFT2 Name to Bytes");
byte[] bdeft2Name = GetBytes(Deft2FileName); // 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 Exclamation 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("Reading DEFT2 Name Length");
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[101];
fs.Seek(lenPos, SeekOrigin.Begin);
sr.Read(C, 0, 100);
string sC = new string(C);
byte[] bsC = GetBytes(sC);
byte[] dRes = fse.Decrypt(bsC); // This is where the Exception is thrown.
foreach(char ic in GetString(dRes))
{
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;
}
}
我已经使用 Unicode 编码保存和加载,所以这不是问题。.关于为什么抛出这个异常以及如何解决它有什么想法吗?
Rijndael 密码仅适用于特定的块大小(16、24 或 32 字节)。你在这里得到一个例外,因为你正在解密的数据长度不是块大小的精确倍数。
SO 上有很多类似的问题,但 "none" 符合我的问题。
我正在创建一个充满加密随机字节的文件。然后在这个文件中的特定位置我写了一些加密字节。当我尝试读取那部分字节时,我得到 "Length of data to decrypt is invalid".
这是加密和解密方法(在 SO 的某个时间点找到)
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();
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();
}
internal byte[] Decrypt(byte[] cipher)
{
string password = Properties.Settings.Default.PasswordOne;
MemoryStream memoryStream;
CryptoStream cryptoStream;
Rijndael rijndael = Rijndael.Create();
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.Close();
return memoryStream.ToArray();
}
我使用这个
将新数据保存在第一个文件中 private void InsertDEFT2NameLength(FileSystemEncryption fse, string Deft2FileName, FileStream fs, StreamWriter sw)
{
string deft2NameLength = "0"; // init the length
if (DrivesLog != null) DrivesLog("Converting DEFT2 Name to Bytes");
byte[] bdeft2Name = GetBytes(Deft2FileName); // 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 Exclamation 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("Reading DEFT2 Name Length");
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[101];
fs.Seek(lenPos, SeekOrigin.Begin);
sr.Read(C, 0, 100);
string sC = new string(C);
byte[] bsC = GetBytes(sC);
byte[] dRes = fse.Decrypt(bsC); // This is where the Exception is thrown.
foreach(char ic in GetString(dRes))
{
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;
}
}
我已经使用 Unicode 编码保存和加载,所以这不是问题。.关于为什么抛出这个异常以及如何解决它有什么想法吗?
Rijndael 密码仅适用于特定的块大小(16、24 或 32 字节)。你在这里得到一个例外,因为你正在解密的数据长度不是块大小的精确倍数。