往返Unicode转换返回不同的Byte []数组

时间:2017-06-07 10:51:06

标签: c# arrays string rsa type-conversion

我正在修改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。

我的问题:为什么,尽管使用相同的编码类型,我会得到不同的字节数组和字符串?这种转换不应该是无损的吗?

1 个答案:

答案 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