往返 Unicode 转换 returns 个不同的 Byte[] 数组
Roundtrip Unicode conversion returns different Byte[] array
我正在修改数据的 RSA 签名。
我使用的是纯文本字符串,我将其转换为字节数组。然后我生成私人证书,签署字节数组,然后生成 public 密钥。
接下来我将使用相同的字节数组来验证签名。
但我想在步骤之间将签名转换为字符串 - 我的想法是稍后将其附加到正在签名的文件中。
static void TestSigning(string privateKey)
{
string data = "TEST_TEST-TEST+test+TEst";
Console.WriteLine("==MESSAGE==");
Console.WriteLine(data);
byte[] dataByte = Encoding.Unicode.GetBytes(data);
using (var rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(privateKey);
var publicKey = rsa.ToXmlString(false);
byte[] signature = rsa.SignData(dataByte, CryptoConfig.MapNameToOID("SHA512"));
string signatureString = Encoding.Unicode.GetString(signature);
byte[] roundtripSignature = Encoding.Unicode.GetBytes(signatureString);
Console.WriteLine("==TEST==");
Console.WriteLine(signature.Length.ToString());
Console.WriteLine(roundtripSignature.Length.ToString());
using (var checkRSA = new RSACryptoServiceProvider())
{
checkRSA.FromXmlString(publicKey);
bool verification = checkRSA.VerifyData(
dataByte,
CryptoConfig.MapNameToOID("SHA512"),
roundtripSignature);
Console.WriteLine("==Verification==");
Console.WriteLine(verification.ToString());
Console.ReadKey();
}
}
}
现在是有趣的部分
如果我使用 UTF8 编码,我会得到不同长度的字节数组
256为原尺寸
484 是往返
UTF7 returns 大小也不同
256 比 679
ASCII 和 Unicode return 正确大小 256 与 256。
我试过使用
var sb = new StringBuilder();
for (int i = 0; i < signature.Length; i++)
{
sb.Append(signature[i].ToString("x2"));
}
获取字符串。然后我使用 Encoding.UTF8.GetBytes() 方法
这次我得到了尺寸:
256 对 512
如果我从 toString() 中删除格式,我会得到:
256 对 670
签名验证总是失败。
如果我使用 'signature' 而不是 roundtripSignature,它工作正常。
我的问题:为什么尽管使用相同的编码类型我得到不同的字节数组和字符串?这种转换不应该是无损的吗?
Unicode 不是一个好的选择,因为至少,\0、CR、LF、、(以及其他控制代码)可能会把事情搞砸。 (有关更多信息,请参阅 )。
正如@JamesKPolk 所说,您需要使用合适的二进制到文本编码。 Base64和hex/Base16最常见,但也有plenty of other viable choices.
我正在修改数据的 RSA 签名。
我使用的是纯文本字符串,我将其转换为字节数组。然后我生成私人证书,签署字节数组,然后生成 public 密钥。
接下来我将使用相同的字节数组来验证签名。
但我想在步骤之间将签名转换为字符串 - 我的想法是稍后将其附加到正在签名的文件中。
static void TestSigning(string privateKey)
{
string data = "TEST_TEST-TEST+test+TEst";
Console.WriteLine("==MESSAGE==");
Console.WriteLine(data);
byte[] dataByte = Encoding.Unicode.GetBytes(data);
using (var rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(privateKey);
var publicKey = rsa.ToXmlString(false);
byte[] signature = rsa.SignData(dataByte, CryptoConfig.MapNameToOID("SHA512"));
string signatureString = Encoding.Unicode.GetString(signature);
byte[] roundtripSignature = Encoding.Unicode.GetBytes(signatureString);
Console.WriteLine("==TEST==");
Console.WriteLine(signature.Length.ToString());
Console.WriteLine(roundtripSignature.Length.ToString());
using (var checkRSA = new RSACryptoServiceProvider())
{
checkRSA.FromXmlString(publicKey);
bool verification = checkRSA.VerifyData(
dataByte,
CryptoConfig.MapNameToOID("SHA512"),
roundtripSignature);
Console.WriteLine("==Verification==");
Console.WriteLine(verification.ToString());
Console.ReadKey();
}
}
}
现在是有趣的部分 如果我使用 UTF8 编码,我会得到不同长度的字节数组
256为原尺寸
484 是往返
UTF7 returns 大小也不同 256 比 679
ASCII 和 Unicode return 正确大小 256 与 256。
我试过使用
var sb = new StringBuilder();
for (int i = 0; i < signature.Length; i++)
{
sb.Append(signature[i].ToString("x2"));
}
获取字符串。然后我使用 Encoding.UTF8.GetBytes() 方法
这次我得到了尺寸: 256 对 512 如果我从 toString() 中删除格式,我会得到: 256 对 670
签名验证总是失败。 如果我使用 'signature' 而不是 roundtripSignature,它工作正常。
我的问题:为什么尽管使用相同的编码类型我得到不同的字节数组和字符串?这种转换不应该是无损的吗?
Unicode 不是一个好的选择,因为至少,\0、CR、LF、
正如@JamesKPolk 所说,您需要使用合适的二进制到文本编码。 Base64和hex/Base16最常见,但也有plenty of other viable choices.