> 文章列表 > C# | 上位机开发新手指南(九)加密算法——RSA

C# | 上位机开发新手指南(九)加密算法——RSA

C# | 上位机开发新手指南(九)加密算法——RSA

上位机开发新手指南(九)加密算法——RSA

文章目录

  • 上位机开发新手指南(九)加密算法——RSA
    • 前言
    • RSA的特性
      • 非对称性
      • 安全性
      • 可逆性
      • 签名
      • 速度较慢
      • 密钥管理
    • RSA算法的参数
      • 公钥
        • 公钥指数e
        • 模数n
      • 私钥
        • 私钥指数d
        • 模数n
        • 质数p和q
        • dp和dq
        • qInv
      • 质数
      • 填充方式
      • 密钥长度
    • RSA在HTTPS中的应用
      • HTTPS实现加密通信的流程
      • 对称与非对称各取所长
    • C#中使用RSA
      • RSACryptoServiceProvider类
        • 核心参数
        • 核心方法
        • 使用建议
      • 示例代码
    • 结束语

前言


RSA的特性

非对称性

RSA算法使用公钥和私钥两个不同的密钥,公钥用于加密数据,私钥用于解密数据。公钥可以公开,任何人都可以使用,而私钥只有密钥持有人可以访问。

安全性

RSA算法基于大数分解难题,即将一个大的合数分解成其质数因子的乘积。由于目前没有有效的算法可以在合理的时间内对大质数进行分解,因此RSA算法被认为是一种安全的加密算法。

可逆性

RSA算法既可以用于加密,也可以用于解密。加密和解密都是可逆的过程,只要使用正确的密钥,就可以还原原始数据。

签名

RSA算法可以用于数字签名,用于验证数据的完整性和真实性。签名过程是将数据使用私钥进行加密,验证过程是将签名使用公钥进行解密。

速度较慢

RSA算法的加密和解密速度较慢,尤其是对于大的数据块。因此在实际应用中,通常使用RSA算法来传输对称密钥,然后使用对称加密算法来加密数据。

密钥管理

RSA算法需要管理公钥和私钥,其中私钥需要保护密钥持有人的私密信息。此外,RSA算法还需要注意密钥的长度,以确保安全性。


RSA算法的参数

公钥

RSA公钥由两个参数组成,即公钥指数e模数n

公钥指数e

公钥指数是一个大整数,通常为65537。在RSA加密过程中,明文数据会被加密为一个新的数值,该数值与明文数据的指数e取模后得到密文数据。公钥指数e可以是任何大于1且不与欧拉函数φ(n)共有质因子的正整数。

模数n

模数n是两个大质数p和q的乘积,即n = p*q。在RSA加密和解密过程中,模数n作为加密和解密的公共参数。模数n的长度取决于所使用的密钥长度,通常为1024位或2048位。模数n越大,加密强度越高,但加密和解密的速度也会变慢。

私钥

RSA私钥由多个参数组成,包括私钥指数d模数n质数p质数qdpdqqInv

私钥指数d

私钥指数是一个大整数,用于解密数据。在RSA解密过程中,密文数据会被解密为一个新的数值,该数值与私钥指数d取模后得到明文数据。

模数n

与公钥模数相同。

质数p和q

质数p和q是私钥的关键参数,用于计算私钥参数dp、dq和qInv。p和q必须是两个不同的质数,且长度必须相等。

dp和dq

私钥参数dp和dq是通过质数p和q计算得到的,用于解密数据。dp和dq的计算公式为:dp = d mod (p-1) 和 dq = d mod (q-1)。

qInv

qInv是q的乘法逆元,用于计算私钥参数dp和dq。计算公式为:qInv = q^-1 mod p。

质数

RSA算法的安全性基于质数分解难题,因此质数是RSA算法的关键参数。通常选择两个大质数作为RSA算法的质数,其大小一般为512位或1024位。

填充方式

RSA算法在加密和解密过程中需要对数据进行填充,以增强安全性和可靠性。

密钥长度

密钥长度是指模数的位数,一般为1024位或2048位。密钥长度越长,加密强度越高,但加密和解密的速度也会变慢。


RSA在HTTPS中的应用

RSA加密算法的应用非常广泛,其中就包含在HTTPS中的应用。接下来我们就以RSA在HTTPS中的应用为例,来详细讲解RSA是如何帮助客户端与服务端实现安全通信的。

HTTPS实现加密通信的流程

HTTPS中使用加密算法进行加密通信的流程如下:

  1. 客户端向服务器发起HTTPS请求,请求中包含了客户端支持的加密算法列表。

  2. 服务器从客户端发送的加密算法列表中选择一种非对称加密算法(如RSA),并向客户端发送自己的数字证书,其中包含了服务器的公钥和其他身份信息。

  3. 客户端收到服务器发送的数字证书后,使用自己内置的证书颁发机构(CA)的公钥对数字证书进行解密,以验证服务器的真实性和合法性。

  4. 客户端使用服务器的公钥对一个随机生成的会话密钥进行加密,然后将加密后的数据发送给服务器。

  5. 服务器收到客户端发送的加密数据后,使用自己的私钥对数据进行解密,以获取会话密钥。

  6. 服务器使用会话密钥对通信过程中的数据进行对称加密,然后将加密后的数据发送给客户端。

  7. 客户端收到服务器发送的加密数据后,使用会话密钥对数据进行解密,以获取原始数据。

思考:从上述的流程中,我们看到HTTPS通信中不仅使用了非对称加密,还使用了对称加密。既然同是加密算法,为什么不直接使用非对称加密(如RSA)对通信数据加密呢?

对称与非对称各取所长

从之前的流程中,我们看到HTTPS通信中不仅使用了非对称加密,还使用了对称加密,这是因为对称加密和非对称加密分别具有不同的优缺点,通过两种加密方式的组合,可以充分发挥它们各自的优势,实现更高效和安全的通信。

首先,对称加密算法具有加密速度快的优点,但是其安全性较低,容易受到中间人攻击等安全威胁。因此,在HTTPS通信中,为了保证通信数据的安全性,会话密钥采用对称加密算法进行加密,但是为了保证传输过程中的安全性,会话密钥本身采用非对称加密算法进行加密,即服务器使用自己的私钥对会话密钥进行加密,然后将加密后的会话密钥发送给客户端,客户端使用服务器的公钥对会话密钥进行解密,从而获取会话密钥,以实现对称加密通信。

其次,非对称加密算法具有较高的安全性,但是加密速度较慢,因此,在HTTPS通信中,RSA算法通常用于加密和签名数字证书,以验证网站的真实性和合法性,同时也用于对会话密钥进行加密,以保证通信过程中的安全性。

因此,HTTPS通信中采用对称加密和非对称加密的组合方式,既保证了加密速度的快捷和通信效率的高效,又保证了通信数据的安全性和可靠性。


C#中使用RSA

RSACryptoServiceProvider类

使用加密服务提供程序 (CSP) 提供的 RSA 算法的实现执行非对称加密和解密。 >> 跳转至官方文档

核心参数

  1. KeySize:指定RSA密钥长度,一般推荐使用2048位或以上的密钥长度。
  2. Padding:指定RSA加密和解密时使用的填充模式,默认为PKCS#1填充模式。
  3. KeyExchangeAlgorithm:指定RSA密钥交换算法,一般使用RSA。
  4. SignatureAlgorithm:指定RSA签名算法,一般使用RSA-SHA256。

核心方法

  1. GenerateKeyPair:生成RSA密钥对。
  2. Encrypt:使用公钥加密数据。
  3. Decrypt:使用私钥解密数据。
  4. ExportParameters:导出RSA密钥参数。
  5. ImportParameters:导入RSA密钥参数。
  6. FromXmlString:从XML字符串中加载RSA密钥。
  7. ToXmlString:将RSA密钥导出为XML字符串。

使用建议

在RSA算法中,每个RSA密钥对只能对应一个公钥和一个私钥。因此每次通过RSACryptoServiceProvider创建随机的RSA秘钥后需妥善保管参数。
在创建一个新的RSA秘钥时,可以使用ToXmlString方法将其转化为XML格式进行储存。
在需要使用RSA解密时,通过FromXmlString还原创建时的参数,再使用私钥进行解密。

示例代码

引用库:

using System.Security.Cryptography;

创建指定秘钥长度(如2048)的RSACryptoServiceProvider对象:

// 创建RSACryptoServiceProvider对象
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048);

生成公钥和私钥:

// 生成RSA密钥对
RSAParameters privateKey = rsa.ExportParameters(true);
RSAParameters publicKey = rsa.ExportParameters(false);

加密数据的方法:

        static byte[] EncryptData(byte[] data, RSAParameters publicKey){// 创建RSACryptoServiceProvider对象RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();// 设置公钥rsa.ImportParameters(publicKey);// 加密数据byte[] encryptedData = rsa.Encrypt(data, false);return encryptedData;}

解密数据的方法

        static byte[] DecryptData(byte[] data, RSAParameters privateKey){// 创建RSACryptoServiceProvider对象RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();// 设置私钥rsa.ImportParameters(privateKey);// 解密数据byte[] decryptedData = rsa.Decrypt(data, false);return decryptedData;}

结束语

RSA加密已经被框架集成好了,为什么(有什么必要)还需要去了解其实现细节?

框架应对的问题是有穷的,现实开发中面对的问题是无穷的。

我对RSA算法的了解源自于曾经供职公司的真实需求,自研的硬件设备需要对数据进行保护,要求一机一密,但由于原本的硬件算力不足以支持RSA的运算,因此引入了一颗加密芯片。
为加密芯片提供参数时产生了一些困惑,比如为什么芯片不要求填入DP和DQ就能进行加解密运算?
而每当回忆起在当时对RSA的特性并不了解的情况下采用了所有数据完全使用RSA进行加密造成了大量的性能浪费,总会心生惭愧…

这便是原因。


禁止转载声明:
本文受到版权保护,未经作者许可,严禁转载。任何机构或个人不得以任何形式将本文用于商业用途或进行二次创作、复制、转载等行为。任何未经授权使用本文所涉及的任何内容,作者保留追究法律责任的权利。如需引用本文,请务必注明出处并获得作者的明确授权。本文刊载于[https://blog.csdn.net/lgj123xj/article/details/130036450],感谢您的理解与支持!