往返 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.