在 .NET C# 中将 RSA 算法的字节数组签名转换为字符串并再次返回字节数组

Convert byte array signature of RSA algorithm to string and back to byte array again in .NET C#

我正在开发 .NET 项目。我对一些敏感数据进行加密。我正在为此使用 RSA 算法。我可以使用私钥、public 密钥和签名成功验证哈希消息。

但是我在将 RSA 算法生成的字节数组签名转换为字符串并将该字符串转换回字节数组以进行验证时遇到问题。但是,如果我使用从签名字符串转换回来的字节数组验证签名,则验证失败。我的场景如下。

这是我使用 RSA 算法

完成的密码学class
public class Cryptograph:ICryptograph
    {
        private string RsaHashAlgorithm { get; set; }

        public Cryptograph()
        {
            this.RsaHashAlgorithm = "SHA256";
        }

        public RSAParameters[] GenarateRSAKeyPairs()
        {
            using (var rsa = new RSACryptoServiceProvider(2048))
            {
                rsa.PersistKeyInCsp = false;
                RSAParameters publicKey = rsa.ExportParameters(false);
                RSAParameters privateKey = rsa.ExportParameters(true);
                return new RSAParameters[]{ privateKey , publicKey };
            }
        }

        public byte[] SignRsaHashData(RSAParameters privateKey,byte[]hashOfDataToSign)
        {
            using (var rsa = new RSACryptoServiceProvider(2048))
            {
                rsa.PersistKeyInCsp = false;
                rsa.ImportParameters(privateKey);

                var rsaFormatter = new RSAPKCS1SignatureFormatter(rsa);
                rsaFormatter.SetHashAlgorithm(RsaHashAlgorithm);

                return rsaFormatter.CreateSignature(hashOfDataToSign);
            }
        }

        public bool VerifyRsaSignature(RSAParameters publicKey,byte[]hashOfDataToSign, byte[] signature)
        {
            using (var rsa = new RSACryptoServiceProvider(2048))
            {
                rsa.ImportParameters(publicKey);

                var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
                rsaDeformatter.SetHashAlgorithm(RsaHashAlgorithm);

                return rsaDeformatter.VerifySignature(hashOfDataToSign, signature);
            }
        }

    }

我测试验证。下面是工作代码并成功验证

[TestMethod]
        public void VerifyRsaEncryptionSign()
        {
            var document = Encoding.UTF8.GetBytes("test message");
            byte[] hashedDocument;
            using (var sha256 = SHA256.Create())
            {
                hashedDocument = sha256.ComputeHash(document);
            }

            Cryptograph crypto = new Cryptograph();
            RSAParameters[] keys = crypto.GenarateRSAKeyPairs();
            RSAParameters privateKey = keys[0];
            RSAParameters publicKey = keys[1];

            byte[] signature = crypto.SignRsaHashData(privateKey, hashedDocument);       
            bool verified = crypto.VerifyRsaSignature(publicKey, hashedDocument, signature);
            Assert.IsTrue(verified);
        }

以上代码,单元测试通过,验证成功

但我想要的是转换签名字节数组并将该字符串转换回字节数组以进行验证,如下面的代码所示。

[TestMethod]
        public void VerifyRsaEncryptionSign()
        {
            var document = Encoding.UTF8.GetBytes("test message");
            byte[] hashedDocument;
            using (var sha256 = SHA256.Create())
            {
                hashedDocument = sha256.ComputeHash(document);
            }

            Cryptograph crypto = new Cryptograph();
            RSAParameters[] keys = crypto.GenarateRSAKeyPairs();
            RSAParameters privateKey = keys[0];
            RSAParameters publicKey = keys[1];

            byte[] signature = crypto.SignRsaHashData(privateKey, hashedDocument);
            string stringSignature = Encoding.UTF8.GetString(signature);// Converted byte array to string
            signature = Encoding.UTF8.GetBytes(stringSignature);//convert string back to byte array
            bool verified = crypto.VerifyRsaSignature(publicKey, hashedDocument, signature);
            Assert.IsTrue(verified);
        }

当我运行单元测试时,验证失败。我的代码有什么问题?我怎样才能成功转换它?我也想问额外的问题。是否可以将散列消息转换回原始字符串?

使用base 64。签名由随机字节组成;然而,并非所有随机字节在解码时都代表有效字符。

基本上你应该只解码之前编码的字符串。