RSA加密的基本常识和封装类

发布时间 2023-07-26 21:38:36作者: 陈憨憨啊

RSA加密的基本常识和封装类

RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,广泛应用于数据加密、数字签名和密钥交换等领域。在RSA加密封装中,主要涉及生成密钥对、加密和解密的过程。

一、 RSA加密封装的过程

1. 生成密钥对: RSA算法使用一对密钥,包括公钥和私钥。公钥用于加密数据,私钥用于解密数据。生成密钥对的过程如下:

a. 选择两个大素数: 首先选择两个足够大的不同素数,通常用p和q来表示。

b. 计算n和Φ(n): 计算n = p * q,以及Φ(n) = (p-1) * (q-1)。其中,n是公钥和私钥的一部分,Φ(n)在后续计算中会用到。

c. 选择公钥e: 选择一个整数e(1 < e < Φ(n)),且e与Φ(n)互质,即e和Φ(n)的最大公约数为1。e作为公钥的一部分,用于加密数据。

d. 计算私钥d: 计算e关于Φ(n)的模反元素d,使得 (d * e) % Φ(n) = 1。d作为私钥的一部分,用于解密数据。

最终,得到的公钥是(n, e),私钥是(n, d)。

2. 加密过程: RSA加密使用公钥进行加密,加密的过程如下:

a. 将数据转换为整数: 将要加密的数据转换为一个整数,通常使用编码方式(如UTF-8)将数据转换为字节数组,再将字节数组转换为一个大整数。

b. 使用公钥加密: 使用公钥中的参数n和e,对整数进行加密运算,得到密文。加密运算的公式为:密文 = 明文^e % n。

3. 解密过程: RSA解密使用私钥进行解密,解密的过程如下:

a. 获取密文: 获取到被加密的密文。

b. 使用私钥解密: 使用私钥中的参数n和d,对密文进行解密运算,得到原始数据。解密运算的公式为:原始数据 = 密文^d % n。

需要注意的是,RSA算法中,加密和解密的整数运算非常耗时,因此在实际应用中通常只用RSA加密对称密钥等少量数据,再使用对称加密算法(如AES)对大量数据进行加密。这样可以兼顾RSA的安全性和对称加密的高效性。

二、RSA的应用

  1. 数据传输安全: RSA广泛用于保证敏感数据在网络传输过程中的安全性。在例如网上银行、电子商务等应用中,用户的敏感信息(如密码、身份证号等)在传输过程中需要使用RSA加密,确保只有授权用户能够解密并读取这些信息,从而避免信息被恶意截获或篡改。
  2. 数字签名: RSA可以用于生成数字签名,用于验证数据的完整性和来源。在数字签名中,使用私钥对数据进行签名,而任何人都可以使用公钥验证签名的有效性。这在保证文件的完整性和防止数据篡改方面非常有用,例如软件下载时的数字签名验证。
  3. 安全登录: 在身份验证过程中,用户的登录密码通常需要进行加密传输,以免密码在网络传输过程中被截获。RSA可用于将登录密码加密,并在服务器端使用私钥进行解密,从而保证登录密码的安全传输。
  4. 数字证书: RSA用于生成数字证书,用于证明实体(如网站、应用程序等)的身份和安全性。数字证书中包含实体的公钥,由数字证书颁发机构(CA)签名,用于验证实体的身份和公钥的合法性。
  5. 加密密钥交换: 在对称加密中,加密密钥需要在通信双方之间进行安全交换。RSA可以用于在通信开始时安全地交换对称加密密钥,从而确保加密密钥不被中间人攻击截获或篡改。

应用场景中的代码示例:

生成RSA密钥对

using System.Security.Cryptography;

using (var rsa = new RSACryptoServiceProvider(2048))
{
    // 获取公钥和私钥
    string publicKey = rsa.ToXmlString(false);
    string privateKey = rsa.ToXmlString(true);

    // 这里只是简单示例,实际应用中需要妥善保管私钥
}

使用公钥加密数据

// 使用公钥加密数据
using System.Security.Cryptography;

string publicKey = "......"; // 从证书或其他安全渠道获取公钥
byte[] data = Encoding.UTF8.GetBytes("敏感数据");

using (var rsa = new RSACryptoServiceProvider(2048))
{
    rsa.FromXmlString(publicKey);
    byte[] encryptedData = rsa.Encrypt(data, false);

    // 将加密后的数据传输给接收方
}

使用私钥解密数据

// 使用私钥解密数据
using System.Security.Cryptography;

string privateKey = "......"; // 仅在安全的环境下获取私钥
byte[] encryptedData = ......; // 从接收方获取加密后的数据

using (var rsa = new RSACryptoServiceProvider(2048))
{
    rsa.FromXmlString(privateKey);
    byte[] decryptedData = rsa.Decrypt(encryptedData, false);

    // 处理解密后的数据
    string originalData = Encoding.UTF8.GetString(decryptedData);
}

以上示例演示了RSA密钥对的生成,以及使用公钥加密数据和使用私钥解密数据的过程。在实际应用中,通常需要更多的处理来确保数据的安全性和正确性,例如数据填充、数字签名验证等。同时,由于RSA加密运算较为耗时,通常将RSA与对称加密算法结合使用,以保证加密过程的高效性和安全性。

三、RSA加密封装类

/// <summary>
/// RSA ECC
/// 可逆非对称加密 
/// 非对称加密算法的优点是密钥管理很方便,缺点是速度慢。
/// </summary>
public class RsaEncrypt
{
    /// <summary>
    /// 获取加密/解密对
    /// 给你一个,是无法推算出另外一个的
    /// 
    /// Encrypt   Decrypt
    /// </summary>
    /// <returns>Encrypt   Decrypt</returns>
    public static KeyValuePair<string, string> GetKeyPair()
    {
        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
        string publicKey = RSA.ToXmlString(false); //在C#中只实现了 公钥加密  私钥解密  如果有需要其他场景的,需要引入一个第三方dll
        string privateKey = RSA.ToXmlString(true);
        return new KeyValuePair<string, string>(publicKey, privateKey);
    }

    /// <summary>
    /// 加密:内容+加密key
    /// 
    /// </summary>
    /// <param name="content"></param>
    /// <param name="encryptKey">加密key</param>
    /// <returns></returns>
    public static string Encrypt(string content, string encryptKey)
    {
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(encryptKey);
        UnicodeEncoding ByteConverter = new UnicodeEncoding();
        byte[] DataToEncrypt = ByteConverter.GetBytes(content);
        byte[] resultBytes = rsa.Encrypt(DataToEncrypt, false);
        return Convert.ToBase64String(resultBytes);
    }

    /// <summary>
    /// 解密  内容+解密key
    /// </summary>
    /// <param name="content"></param>
    /// <param name="decryptKey">解密key</param>
    /// <returns></returns>
    public static string Decrypt(string content, string decryptKey)
    {
        byte[] dataToDecrypt = Convert.FromBase64String(content);
        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
        RSA.FromXmlString(decryptKey);
        byte[] resultBytes = RSA.Decrypt(dataToDecrypt, false);
        UnicodeEncoding ByteConverter = new UnicodeEncoding();
        return ByteConverter.GetString(resultBytes);
    }


    /// <summary>
    /// 可以合并在一起的,每次产生一组新的密钥
    /// </summary>
    /// <param name="content"></param>
    /// <param name="encryptKey">加密key</param>
    /// <param name="decryptKey">解密key</param>
    /// <returns>加密后结果</returns>
    private static string Encrypt(string content, out string publicKey, out string privateKey)
    {
        RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
        publicKey = rsaProvider.ToXmlString(false);
        privateKey = rsaProvider.ToXmlString(true);

        UnicodeEncoding ByteConverter = new UnicodeEncoding();
        byte[] DataToEncrypt = ByteConverter.GetBytes(content);
        byte[] resultBytes = rsaProvider.Encrypt(DataToEncrypt, false);
        return Convert.ToBase64String(resultBytes);
    }
}