gpt4 book ai didi

C# Rijndael 解密返回额外的问号字符

转载 作者:行者123 更新时间:2023-11-30 13:45:37 27 4
gpt4 key购买 nike

我正在一个类中组织一些非常基本的对称加密/解密代码以供将来使用。我能够成功加密和解密...只是有一个小问题。

这是我从一个流中读入并加密/解密到另一个流的代码:

public void Encrypt(Stream input, Stream output) {
byte[] key = Encoding.UTF8.GetBytes(_pw);
byte[] iv = Encoding.UTF8.GetBytes(GenerateInitVector());
RijndaelManaged rm = new RijndaelManaged();
CryptoStream cs = new CryptoStream(
output,
rm.CreateEncryptor(key, iv),
CryptoStreamMode.Write);
int data;
while ((data = input.ReadByte()) != -1)
cs.WriteByte((byte) data);
cs.Close();
}

public void Decrypt(Stream input, Stream output) {
byte[] key = Encoding.UTF8.GetBytes(_pw);
byte[] iv = Encoding.UTF8.GetBytes(GenerateInitVector());
RijndaelManaged rm = new RijndaelManaged();
CryptoStream cs = new CryptoStream(
input,
rm.CreateDecryptor(key, iv),
CryptoStreamMode.Read);
int data;
while ((data = cs.ReadByte()) != -1)
output.WriteByte((byte) data);
cs.Close();
}

请注意,GenerateInitVector() 方法始终返回相同的值。

这是我的测试文件。

hello
world
this
is
a
word
list

当我尝试从 FileStream 加密/解密到 FileStream 时,一切正常,使用这些方法:

public void Encrypt(string inputPath, string outputPath) {
FileStream input = new FileStream(inputPath, FileMode.Open);
FileStream output = new FileStream(outputPath, FileMode.Create);
Encrypt(input, output);
output.Close();
input.Close();
}

public void Decrypt(string inputPath, string outputPath) {
FileStream input = new FileStream(inputPath, FileMode.Open);
FileStream output = new FileStream(outputPath, FileMode.Create);
Decrypt(input, output);
output.Close();
input.Close();
}

当我尝试将文件解密到 MemoryStream 中,然后将字节转换为字符的数组加载到 StringBuilder 中,最后将其作为字符串打印到控制台时,我进入了控制台:

?hello
world
this
is
a
word
list

我所有的文字前面都多了一个问号。这是我的解密方法:

public StringBuilder Decrypt(string inputPath) {
FileStream input = new FileStream(inputPath, FileMode.Open);
byte[] buffer = new byte[4096];
MemoryStream output = new MemoryStream(buffer);
Decrypt(input, output);
StringBuilder sb = new StringBuilder(4096);
sb.Append(Encoding.UTF8.GetChars(buffer, 0, (int) output.Position));
input.Close();
output.Close();
return sb;
}

我在这里读过一些关于 BOM 和 C# 的类似内容字符:

Result of RSA encryption/decryption has 3 question marks

因此,我加倍确定我使用的是 UTF-8 编码。尽管如此,我还是看到了这个额外的问号。为了完整起见,我还写了这个方法来将StringBuilder中的内容加密到文件中:

public void Encrypt(string outputPath, StringBuilder builder) {
char[] buffer = new char[builder.Length];
builder.CopyTo(0, buffer, 0, builder.Length);
byte[] buf = Encoding.UTF8.GetBytes(buffer);
MemoryStream input = new MemoryStream(buf);
FileStream output = new FileStream(outputPath, FileMode.Create);
Encrypt(input, output);
output.Close();
input.Close();
}

然后我通过做交叉检查:

var builder = new StringBuilder();
builder.Append("Hello world.");
Encrypt("test.txt.enc", builder);
Decrypt("test.txt.enc", "test.txt");
builder = Decrypt("test.txt.enc");
Console.WriteLine(builder.ToString());

对于文件 test.txt,一切正常。奇怪的是,对于打印在控制台上的文本,我在前面得到NO额外的问号:

Hello world.

整个过程有什么问题?

最佳答案

问号是 BOM UTF8的(Byte Order Mark)是0xef 0xbb 0xbf此字节写入以 UTF8 编码的文件的开头。

因为 FileStream 以字节形式读取文件并且不将其解释为 UTF8 文本文件,所以 BOM 包含在您的加密中,因此如果您解密它并将其保存到文件中,它在 TextEditor 中看起来一切正常,但如果您转储它以控制 BOM也被打印出来,因为控制台不知道它是某种控制序列/标记

编辑:这是获取没有 BOM 的字符串的解决方案。

    public static string Decrypt(string inputPath)
{
FileStream input = new FileStream(inputPath, FileMode.Open);
MemoryStream output = new MemoryStream();
Decrypt(input, output);
StreamReader reader = new StreamReader(output, new UTF8Encoding()); //Read with encoding
output.Seek(0, SeekOrigin.Begin); //Set stream Position to beginning
string result = reader.ReadToEnd(); //read to string
reader.Close();
input.Close();
output.Close();
return result;
}

关于C# Rijndael 解密返回额外的问号字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28230144/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com