C# RSA 非对称加密算法

2023年4月25日 1184点热度 0人点赞 0条评论
内容纲要

注意,
C# RSA 只能导入导出 PKCS1 的公钥,不能处理 PKCS8 的。否则会报错。
C# RSA 可以导出导入 PCKS8 的私钥,可以按照 pem 格式处理,也可以按照文本格式处理,

示例如下:

using Newtonsoft.Json;

void Main()
{
    var keySize = 2048;

    var rsaCryptoServiceProvider = new RSACryptoServiceProvider(keySize);

    // 打印私钥、公钥
    Convert.ToBase64String(rsaCryptoServiceProvider.ExportPkcs8PrivateKey()).Dump();
    Convert.ToBase64String(rsaCryptoServiceProvider.ExportRSAPublicKey()).Dump();

    var parameters = rsaCryptoServiceProvider.ExportParameters(true);
    // 加密后的字符串
    var cipherText = Encrypt("hello world", parameters);

    // 解密后的字符串
    var plainText = Decrypt(cipherText, parameters);
    Console.WriteLine(plainText);

}

// 加密
public string Encrypt(string data, RSAParameters key)
{

    using (var rsa = new RSACryptoServiceProvider())
    {
        rsa.ImportParameters(key);
        var byteData = Encoding.UTF8.GetBytes(data);
        var encryptData = rsa.Encrypt(byteData, false);
        return Convert.ToBase64String(encryptData);
    }
}

// 解密
public string Decrypt(string cipherText, RSAParameters key)
{

    using (var rsa = new RSACryptoServiceProvider())
    {
        var cipherByteData = Convert.FromBase64String(cipherText);
        rsa.ImportParameters(key);

        var encryptData = rsa.Decrypt(cipherByteData, false);
        return Encoding.UTF8.GetString(encryptData);
    }
}

导出导入公钥:


        /// <summary>
        /// 导入公钥
        /// </summary>
        /// <param name="rsa"></param>
        /// <param name="publicKey"></param>
        /// <returns></returns>
        private static RSACryptoServiceProvider ImportPublicKeyFromPEM(RSACryptoServiceProvider rsa, string publicKey)
        {
            publicKey = publicKey
            .Replace("-----BEGIN RSA PUBLIC KEY-----", "")
            .Replace("-----END RSA PUBLIC KEY-----", "")
            .Replace("-----BEGIN PUBLIC KEY-----", "")
            .Replace("-----END PUBLIC KEY-----", "")
                .Replace("\r", "")
                .Replace("\n", "");
            rsa.ImportRSAPublicKey(Convert.FromBase64String(publicKey), out var bytesRead);
            return rsa;
        }

        /// <summary>
        /// 导出公钥
        /// </summary>
        /// <param name="rsa"></param>
        /// <returns></returns>
        public static string ExportPublicKeyToPEM(RSACryptoServiceProvider rsa)
        {
            return rsa.ExportRSAPublicKeyPem();
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="encryptedMessage"></param>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string Encrypt(byte[] encryptedMessage, out byte[] bytes)
        {
            // Decrypt the message using the public key  
            byte[] decryptedMessage = RsaPublic.Encrypt(encryptedMessage, false);
            bytes = decryptedMessage;
            string decryptedMessageString = Encoding.UTF8.GetString(decryptedMessage);
            return decryptedMessageString;
        }
        public static string Encrypt(string encryptedMessage)
        {
            // Decrypt the message using the public key  
            byte[] decryptedMessage = RsaPublic.Encrypt(Encoding.UTF8.GetBytes(encryptedMessage), false);

            string decryptedMessageString = Encoding.UTF8.GetString(decryptedMessage);
            return decryptedMessageString;
        }

        /// <summary>
        /// 解码
        /// </summary>
        /// <param name="encryptedMessage"></param>
        /// <returns></returns>
        public static string Decrypt(string encryptedMessage)
        {
            // Decrypt the message using the public key  
            byte[] decryptedMessage = RsaPublic.Decrypt(Encoding.ASCII.GetBytes(encryptedMessage), false);

            string decryptedMessageString = Encoding.UTF8.GetString(decryptedMessage);
            return decryptedMessageString;
        }
        /// <summary>
        /// 解码
        /// </summary>
        /// <param name="encryptedMessage"></param>
        /// <returns></returns>
        public static string Decrypt(byte[] encryptedMessage)
        {
            // Decrypt the message using the public key  
            byte[] decryptedMessage = RsaPublic.Decrypt(encryptedMessage, false);

            string decryptedMessageString = Encoding.UTF8.GetString(decryptedMessage);
            return decryptedMessageString;
        }

完整可以直接复制使用的 Rsa 帮助类代码:


    /// <summary>
    /// Rsa 加解密.
    /// </summary>
    public static class RsaHelper
    {
        /// <summary>
        /// 导入 rsa 私钥.
        /// </summary>
        /// <param name="privateKey">base64 编码的 pck8 格式的 Rsa 私钥.</param>
        /// <param name="keySize">Key 大小,默认 2048.</param>
        /// <returns><see cref="RSACryptoServiceProvider"/> 对象.</returns>
        public static RSACryptoServiceProvider ImportPrivateKey(string privateKey, int keySize = 2048)
        {
            var rsa = new RSACryptoServiceProvider(keySize);
            rsa.ImportPkcs8PrivateKey(Convert.FromBase64String(privateKey), out var bytesRead);
            return rsa;
        }

        /// <summary>
        /// 导出 Rsa 私钥,使用 base64 编码的 pck8 格式的 Rsa 私钥.
        /// </summary>
        /// <param name="rsa"><see cref="RSACryptoServiceProvider"/> 对象.</param>
        /// <returns>base64 编码的 pck8 格式的 Rsa 私钥.</returns>
        public static string ExportPrivateKey([NotNull] RSACryptoServiceProvider rsa)
        {
            return Convert.ToBase64String(rsa.ExportPkcs8PrivateKey());
        }

        /// <summary>
        /// 通过 Rsa 私钥生成新的公钥.
        /// </summary>
        /// <param name="privateKey">base64 编码的 pck8 格式的 Rsa 私钥.</param>
        /// <param name="keySize">Key 大小,默认 2048.</param>
        /// <returns>base64 编码的 pck8 格式的 Rsa 公钥.</returns>
        public static string ExportPublicKey(string privateKey, int keySize = 2048)
        {
            using var rsa = ImportPrivateKey(privateKey, keySize);
            return Convert.ToBase64String(rsa.ExportRSAPublicKey());
        }

        /// <summary>
        /// 通过 Rsa 私钥生成新的公钥.
        /// </summary>
        /// <param name="rsa"><see cref="RSACryptoServiceProvider"/> 对象.</param>
        /// <returns>base64 编码的 pck8 格式的 Rsa 公钥.</returns>
        public static string ExportPublicKey([NotNull] RSACryptoServiceProvider rsa)
        {
            return Convert.ToBase64String(rsa.ExportRSAPublicKey());
        }

        /// <summary>
        /// 导入公钥.
        /// </summary>
        /// <param name="publicKey">base64 编码的 pck8 格式的 Rsa 公钥.</param>
        /// <param name="keySize">Key 大小,默认 2048.</param>
        /// <returns><see cref="RSACryptoServiceProvider"/> 对象.</returns>
        public static RSACryptoServiceProvider ImportPublicKey(string publicKey, int keySize = 2048)
        {
            var rsa = new RSACryptoServiceProvider(keySize);
            rsa.ImportRSAPublicKey(Convert.FromBase64String(publicKey), out _);
            return rsa;
        }

        /// <summary>
        /// 通过公钥加密信息.
        /// </summary>
        /// <param name="publicKey">base64 编码的 pck8 格式的 Rsa 公钥.</param>
        /// <param name="message">要被加密的信息.</param>
        /// <param name="keySize">Key 大小,默认 2048.</param>
        /// <returns>base64 编码的密文.</returns>
        public static string Encrypt(string publicKey, string message, int keySize = 2048)
        {
            using var rsa = ImportPublicKey(publicKey, keySize);
            var encryptData = rsa.Encrypt(Encoding.UTF8.GetBytes(message), false);
            return Convert.ToBase64String(encryptData);
        }

        /// <summary>
        /// 使用私钥解密.
        /// </summary>
        /// <param name="privateKey">base64 编码的 pck8 格式的 Rsa 公钥.</param>
        /// <param name="message">base64 编码的密文.</param>
        /// <param name="keySize">Key 大小,默认 2048.</param>
        /// <returns>解密后的信息.</returns>
        public static string Decrypt(string privateKey, string message, int keySize = 2048)
        {
            using var rsa = ImportPrivateKey(privateKey, keySize);

            var cipherByteData = Convert.FromBase64String(message);

            var encryptData = rsa.Decrypt(cipherByteData, false);
            return Encoding.UTF8.GetString(encryptData);
        }
    }

痴者工良

高级程序员劝退师

文章评论