c#中大数据的RSA加密

本文关键字:RSA 加密 数据 | 更新日期: 2023-09-27 18:17:20

这是我的第一篇文章,希望我没有错过什么重要的东西。我正在c#中做一个项目,我需要使用公钥/私钥加密来加密消息,然后通过SSL连接发送。

我选择使用RSACryptoService,因为根据文档,这是唯一用于加密数据的非对称加密方案。问题是我对此有很多问题。(我想做对称加密,但这不是我老师想让我做的,根据他的说法,确定块大小应该很容易,然后它应该为你做所有的工作。)好吧,到目前为止还没有运气,我尝试了一些不同的方法,但现在我回到了基础,再次尝试,这是我当前的代码:

    public string[] GenerateKeysToStrings(string uniqueIdentifier)
    {
        string[] keys;
        using (var rsa = new RSACryptoServiceProvider(4096))
        {
            try
            {
                string privateKey = rsa.ToXmlString(true);
                string publicKey = rsa.ToXmlString(false);
                this.pki.StoreKey(publicKey, uniqueIdentifier);
                keys = new string[2];
                keys[0] = privateKey;
                keys[1] = publicKey;
            }
            finally
            {
                //// Clear the RSA key container, deleting generated keys.
                rsa.PersistKeyInCsp = false;
            }
        }
        return keys;
    }

如您所见,我生成了密钥,并通过将公钥发送给存储它的简单类来模拟PKI,然后将私钥写入文件(请注意,我也有另一个方法,做同样的事情,但将其存储到一个数组,而不是因为我想测试和简化的事情,因为我得到No such key exceptions,有时加密异常,当我这样做在示例中所示的方式,所以我想通过简单地存储rsa.ToXmlString字符串来简化它,作为一个数组中的字符串,但没有运气。)

现在我有一个加密和解密的方法如下:

    public string Encrypt(string keyString, string message)
    {
        string encryptedMessage;
        using (var rsa = new RSACryptoServiceProvider())
        {
            try
            {
                //// Load the key from the specified path
                var encryptKey = new XmlDocument();
                encryptKey.Load(@"C:'Test'PrivateKeyInfo.xml");
                rsa.FromXmlString(encryptKey.OuterXml);

                //// Conver the string message to a byte array for encryption
                //// var encoder = new UTF8Encoding();
                ASCIIEncoding byteConverter = new ASCIIEncoding();
                byte[] dataToEncrypt = byteConverter.GetBytes(message);
                byte[] encryptedData = rsa.Encrypt(dataToEncrypt, false);
                //// Convert the byte array back to a string message
                encryptedMessage = byteConverter.GetString(encryptedData);
            }
            finally
            {
                //// Clear the RSA key container, deleting generated keys.
                rsa.PersistKeyInCsp = false;
            }
        }
        return encryptedMessage;
    }

解密:

    public string Decrypt(string keyString, string message)
    {
        string decryptedText;
        using (var rsa = new RSACryptoServiceProvider())
        {
            try
            {
                //// Loads the keyinfo into the rsa parameters from the keyfile
                /*
                var privateKey = new XmlDocument();
                privateKey.Load(keyString);
                 */
                rsa.FromXmlString(keyString);
                //// Convert the text from string to byte array for decryption
                ASCIIEncoding byteConverter = new ASCIIEncoding();
                var encryptedBytes = byteConverter.GetBytes(message);
                //// Create an aux array to store all the encrypted bytes
                byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, false);
                decryptedText = byteConverter.GetString(decryptedBytes);
            }
            finally
            {
                //// Clear the RSA key container, deleting generated keys.
                rsa.PersistKeyInCsp = false;
            }
        }
        return decryptedText;
    }

我知道这是一堵文字墙,但我希望你能帮助我,因为我已经把我的头撞在墙上很长时间了,现在这并不好笑:)

问题是,我如何使用RSA(或任何其他公钥/私钥加密)加密消息

下面是测试客户端:
    public static void Main(string[] args)
    {
        PublicKeyInfrastructure pki = new PublicKeyInfrastructure();
        Cryptograph crypto = new Cryptograph();
        string[] keys = crypto.GenerateKeysToStrings("simonlanghoff@gmail.com");

        string plainText = "Hello play with me, please";
        string publicKey = crypto.GetPublicKey("simonlanghoff@gmail.com");
        string encryptedText = crypto.Encrypt(keys[0], plainText);

        string decryptedText = crypto.Decrypt(keys[1], encryptedText);
    }

正如我所提到的,字符串数组的存在是因为我想消除XML文档中的糟糕解析错误…

当我运行测试客户端时,如果我使用私钥加密和公钥解密,我得到一个"密钥不存在异常",如果我这样做,我得到一个坏数据异常。

请帮助我,如果你知道任何好的指南,或者可以告诉我如何在字符串消息上直接实现公钥/私钥加密,请帮助我。

谢谢你的帮助。

c#中大数据的RSA加密

这不是RSA加密应该做的。

RSA是关于数学的。你加密的是一个数字,所以它的长度必须是有限的,并且与你使用的RSA密钥对长度相匹配。进一步的长度限制由所使用的填充(pkcs# 1或OAEP)施加。

如果你想用RSA加密大数据,你需要间接地这样做——即使用对称密钥加密大数据,并使用RSA公钥加密该密钥。

你可以在我的博客上读到如何实现这个。

好了,我终于想出了一个解决我在原来的帖子中提到的问题的办法。这是我还没有彻底测试过的东西,但我从一个小小的试验和错误过程中发现了一些东西。

下面是我的当前代码:

    public static string Encrypt(string dataToEncrypt, RSAParameters publicKeyInfo)
    {
        //// Our bytearray to hold all of our data after the encryption
        byte[] encryptedBytes = new byte[0];
        using (var RSA = new RSACryptoServiceProvider())
        {
            try
            {
                //Create a new instance of RSACryptoServiceProvider.
                UTF8Encoding encoder = new UTF8Encoding();
                byte[] encryptThis = encoder.GetBytes(dataToEncrypt);
                //// Importing the public key
                RSA.ImportParameters(publicKeyInfo);
                int blockSize = (RSA.KeySize / 8) - 32;
                //// buffer to write byte sequence of the given block_size
                byte[] buffer = new byte[blockSize];
                byte[] encryptedBuffer = new byte[blockSize];
                //// Initializing our encryptedBytes array to a suitable size, depending on the size of data to be encrypted
                encryptedBytes = new byte[encryptThis.Length + blockSize - (encryptThis.Length % blockSize) + 32];
                for (int i = 0; i < encryptThis.Length; i += blockSize)
                {
                    //// If there is extra info to be parsed, but not enough to fill out a complete bytearray, fit array for last bit of data
                    if (2 * i > encryptThis.Length && ((encryptThis.Length - i) % blockSize != 0))
                    {
                        buffer = new byte[encryptThis.Length - i];
                        blockSize = encryptThis.Length - i;
                    }
                    //// If the amount of bytes we need to decrypt isn't enough to fill out a block, only decrypt part of it
                    if (encryptThis.Length < blockSize)
                    {
                        buffer = new byte[encryptThis.Length];
                        blockSize = encryptThis.Length;
                    }
                    //// encrypt the specified size of data, then add to final array.
                    Buffer.BlockCopy(encryptThis, i, buffer, 0, blockSize);
                    encryptedBuffer = RSA.Encrypt(buffer, false);
                    encryptedBuffer.CopyTo(encryptedBytes, i);
                }
            }
            catch (CryptographicException e)
            {
                Console.Write(e);
            }
            finally
            {
                //// Clear the RSA key container, deleting generated keys.
                RSA.PersistKeyInCsp = false;
            }
        }
        //// Convert the byteArray using Base64 and returns as an encrypted string
        return Convert.ToBase64String(encryptedBytes);
    }
    /// <summary>
    /// Decrypt this message using this key
    /// </summary>
    /// <param name="dataToDecrypt">
    /// The data To decrypt.
    /// </param>
    /// <param name="privateKeyInfo">
    /// The private Key Info.
    /// </param>
    /// <returns>
    /// The decrypted data.
    /// </returns>
    public static string Decrypt(string dataToDecrypt, RSAParameters privateKeyInfo)
    {
        //// The bytearray to hold all of our data after decryption
        byte[] decryptedBytes;
        //Create a new instance of RSACryptoServiceProvider.
        using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
        {
            try
            {
                byte[] bytesToDecrypt = Convert.FromBase64String(dataToDecrypt);
                //// Import the private key info
                RSA.ImportParameters(privateKeyInfo);
                //// No need to subtract padding size when decrypting (OR do I?)
                int blockSize = RSA.KeySize / 8;
                //// buffer to write byte sequence of the given block_size
                byte[] buffer = new byte[blockSize];
                //// buffer containing decrypted information
                byte[] decryptedBuffer = new byte[blockSize];
                //// Initializes our array to make sure it can hold at least the amount needed to decrypt.
                decryptedBytes = new byte[dataToDecrypt.Length];
                for (int i = 0; i < bytesToDecrypt.Length; i += blockSize)
                {
                    if (2 * i > bytesToDecrypt.Length && ((bytesToDecrypt.Length - i) % blockSize != 0))
                    {
                        buffer = new byte[bytesToDecrypt.Length - i];
                        blockSize = bytesToDecrypt.Length - i;
                    }
                    //// If the amount of bytes we need to decrypt isn't enough to fill out a block, only decrypt part of it
                    if (bytesToDecrypt.Length < blockSize)
                    {
                        buffer = new byte[bytesToDecrypt.Length];
                        blockSize = bytesToDecrypt.Length;
                    }
                    Buffer.BlockCopy(bytesToDecrypt, i, buffer, 0, blockSize);
                    decryptedBuffer = RSA.Decrypt(buffer, false);
                    decryptedBuffer.CopyTo(decryptedBytes, i);
                }
            }
            finally
            {
                //// Clear the RSA key container, deleting generated keys.
                RSA.PersistKeyInCsp = false;
            }
        }
        //// We encode each byte with UTF8 and then write to a string while trimming off the extra empty data created by the overhead.
        var encoder = new UTF8Encoding();
        return encoder.GetString(decryptedBytes).TrimEnd(new[] { ''0' });
    }

正如我所说的,我没有测试过它,除了低于,等于和高于块大小的大小,但它似乎正在做它应该做的事情。我仍然是一个新手,所以我真的希望你仔细检查我的代码:)

也许我错过了一些东西,但看起来您的Encrypt()函数不使用keyString参数或encryptKey的内容。