我正在修改RSA数据签名。
我使用明文字符串,我将其转换为字节数组。然后我生成私有证书,签署字节数组,然后生成公钥。
接下来我使用相同的字节数组来验证签名。
但是我想在两个步骤之间将签名转换为字符串 - 想法是稍后将其附加到正在签名的文件上。
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也会返回不同的尺寸 256 vs 679
ASCII和Unicode都返回256和256之间的正确大小。
我尝试过使用
var sb = new StringBuilder();
for (int i = 0; i < signature.Length; i++)
{
sb.Append(signature[i].ToString("x2"));
}
获取字符串。我然后使用Encoding.UTF8.GetBytes()方法
这次我得到的尺寸为: 256 vs 512 如果我从toString()中删除格式我得到: 256 vs 670
签名验证alwayas失败。 如果我使用&#39;签名&#39;它可以正常工作而不是roundtripSignature。
我的问题:为什么,尽管使用相同的编码类型,我会得到不同的字节数组和字符串?这种转换不应该是无损的吗?
答案 0 :(得分:0)
Unicode不是一个不错的选择,因为,至少,\ 0,CR,LF,&lt; delete&gt;,&lt; backspace&gt; (以及其余的控制代码)可以搞砸了。 (有关详细信息,请参阅an answer about this for Encrypt/Decrypt。)
正如@JamesKPolk所说,你需要使用合适的二进制文本编码。 Base64和hex / Base16是最常见的,但有plenty of other viable choices。