【RSA】加密算法 RSA| RSA_pss| RSA_oaep 讲解与使用示例

1. RSA

RSA算法是一种广泛使用的非对称加密算法,它在1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)三位数学家提出,RSA就是他们三人姓氏的首字母缩写。

RSA算法的原理基于整数分解的难解性,即对于一个大的合数,很难分解出它的两个质数因子。

以下是RSA算法的基本步骤:

1.1 密钥生成
步骤一:选择两个大的质数

随机选择两个大的质数 ( p ) 和 ( q ),并计算它们的乘积 ( n = p \times q )。( n ) 将是公钥的一部分。

步骤二:计算欧拉函数

计算 ( n ) 的欧拉函数 ( ϕ ( n ) = ( p − 1 ) ( q − 1 ) ) ( \phi(n) = (p-1)(q-1) ) (ϕ(n)=(p1)(q1))

步骤三:选择公钥指数

选择一个整数 ( e ),满足 ( 1 < e < ϕ ( n ) ) ( 1 < e < \phi(n) ) (1<e<ϕ(n)) 且 ( e ) 与 ϕ(n) 互质(即 ( e ) 和 ϕ(n) 的最大公约数为1)。

步骤四:计算私钥指数

找到一个整数 ( d ),使得 ( d × e ) 模 ( ϕ ( n ) ) ( d \times e ) 模 ( \phi(n) ) (d×e)(ϕ(n)) 的余数为1。

( d × e ≡ 1 m o d    ϕ ( n ) ) ( d \times e \equiv 1\mod \phi(n) ) (d×e1modϕ(n)) 这个 ( d ) 就是私钥指数。

1.2 公钥和私钥
  • 公钥:由 ( n ) 和 ( e ) 组成,即 ( (n, e) )。
  • 私钥:由 ( n ) 和 ( d ) 组成,即 ( (n, d) )。
1.3 加密过程

假设要加密的信息为 ( m ),其中 ( m ) 是一个小于 ( n ) 的正整数。加密后的密文 ( c ) 计算如下:

c ≡ m e m o d    n c \equiv m^e \mod n cmemodn

1.4 解密过程

使用私钥 ( (n, d) ) 对密文 ( c ) 进行解密,得到原始信息 ( m ):

m ≡ c d m o d    n m \equiv c^d \mod n mcdmodn
RSA算法的安全性主要依赖于大数分解的难度。如果能够快速地将 ( n ) 分解为 ( p ) 和 ( q ),那么就可以计算出 ϕ(n) ,进而求出私钥 ( d )。然而,对于非常大的数,目前并没有有效的分解算法,这使得 RSA算法在适当的密钥长度下被认为是安全的。

在实际应用中,RSA算法通常用于数字签名和密钥交换,而不是直接用于加密大量数据,因为它的加密和解密过程相对较慢。对于加密大量数据,通常会使用对称加密算法,并用 RSA来加密对称密钥。

1.5 程序示例

以下是一个使用 RSA算法进行加密和解密的简单示例。在这个示例中,我们将使用 Python 的cryptography库来实现 RSA加密和解密。这个库提供了高级接口来处理加密任务。

首先,需要安装cryptography库。如果还没有安装,可以使用以下命令安装:

pip install cryptography -i https://pypi.tuna.tsinghua.edu.cn/simple

以下是一个简单的 Python 脚本,演示了如何生成 RSA密钥对、使用公钥加密消息以及使用私钥解密消息:

from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding

# 生成RSA密钥对
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)
public_key = private_key.public_key()

# 将私钥和公钥序列化为PEM格式
private_pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
)
public_pem = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

# 打印私钥和公钥(在实际应用中,你应该将这些密钥安全地存储起来)
print("Private Key (PEM):\n", private_pem.decode())
print("Public Key (PEM):\n", public_pem.decode())

# 要加密的消息
message = b"Secret Message"

# 使用公钥和OAEP填充进行加密
ciphertext = public_key.encrypt(
    message,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# 打印加密后的消息(通常是二进制数据)
print("Ciphertext (encrypted message):\n", ciphertext)

# 使用私钥进行解密
decrypted_message = private_key.decrypt(
    ciphertext,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# 打印解密后的消息
print("Decrypted Message:\n", decrypted_message.decode())

在这个脚本中,我们执行了以下步骤:

  1. 生成一个 2048位的 RSA密钥对。
  2. 将私钥和公钥序列化为 PEM格式,以便于存储和传输。
  3. 使用公钥和 OAEP填充方案加密一个消息。
  4. 使用私钥解密接收到的密文。

请注意,在实际应用中,应该确保私钥的安全,不应该将其打印或以明文形式存储。同样,公钥可以安全地公开,但应该通过安全的方式分发。

2. RSA_pss

RSA-PSS(Probabilistic Signature Scheme)是一种基于 RSA 加密算法的签名方案,它在1998年由 Mihir Bellare 和 Philip Rogaway 提出。RSA-PSS是为了解决传统 RSA 签名方案中存在的某些安全弱点而设计的,它提供了更强的安全性和抗攻击能力。RSA-PSS 被广泛认为是比传统的 PKCS#1 v1.5 更安全的签名方案,并且被包括在 PKCS#1 v2.0 及以后的版本中。在许多安全标准和协议中,RSA-PSS 已经成为推荐的 RSA 签名方案。

RSA-PSS 是一种概率性签名方案,这意味着每次签名操作都会生成一个不同的签名,即使是对同一消息。

以下是 RSA-PSS 签名和验证过程的基本步骤:

2.1 签名过程:
步骤一:消息预处理
  1. 计算消息的哈希值 ( H(m) )。
  2. 选择一个随机盐值 ( s ),其长度与哈希函数的输出长度相同。
  3. 构造一个编码的EM(编码消息)块,该块由哈希值、盐值和一个填充字符串组成。
步骤二:签名生成
  1. 使用私钥 ( (n, d) ) 对编码的 EM 块进行签名:
    S ≡ ( E M ) d m o d    n S \equiv (EM)^d \mod n S(EM)dmodn
    其中,( S ) 是签名。
2.2 验证过程:
步骤一:消息预处理
  1. 使用相同的哈希函数计算消息的哈希值 ( H(m) )。
步骤二:签名验证
  1. 使用公钥 ( (n, e) ) 对签名 ( S ) 进行解密:
    E M ′ ≡ S e m o d    n EM' \equiv S^e \mod n EMSemodn
  2. 从 ( EM’ ) 中提取哈希值、盐值和填充字符串。
  3. 使用提取的盐值重新计算编码的EM块,并与 ( EM’ ) 进行比较。
步骤三:比较和验证
  1. 如果 ( EM’ ) 与重新计算的EM块匹配,则签名有效。
  2. 如果不匹配,则签名无效。
2.3 RSA-PSS 的特点:
  • 抗碰撞:由于使用了哈希函数和随机盐值,RSA-PSS 能够抵抗哈希碰撞攻击。
  • 安全性证明:RSA-PSS 在设计时就有形式化的安全性证明,这是相对于传统 RSA 签名方案的一个优势。
  • 填充方案:RSA-PSS 使用了一种特殊的填充方案,这使得即使攻击者知道了一些签名,也无法轻易地为其他消息伪造签名。
2.4 代码示例

以下是一个简单的 Python 脚本,演示了如何生成 RSA密钥对、使用私钥进行签名以及使用公钥验证签名:

from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding

# 生成RSA密钥对
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)
public_key = private_key.public_key()

# 将私钥和公钥序列化为PEM格式
private_pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
)
public_pem = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

# 要签名的消息
message = b"Message to be signed"

# 使用私钥和PSS填充进行签名
signature = private_key.sign(
    message,
    padding.PSS(
        mgf=padding.MGF1(hashes.SHA256()),
        salt_length=padding.PSS.MAX_LENGTH
    ),
    hashes.SHA256()
)

# 打印签名(通常是二进制数据)
print("Signature:\n", signature)

# 使用公钥进行签名验证
try:
    public_key.verify(
        signature,
        message,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()
    )
    print("The signature is valid.")
except Exception as e:
    print("The signature is not valid:", e)

在这个脚本中,我们执行了以下步骤:

  1. 生成一个2048位的RSA密钥对。
  2. 将私钥和公钥序列化为PEM格式,以便于存储和传输。
  3. 使用私钥和PSS填充方案对消息进行签名。
  4. 使用公钥验证接收到的签名。

在RSA-PSS签名方案中,我们使用了MGF1(Mask Generation Function 1)和 SHA-256哈希算法。salt_length参数设置为padding.PSS.MAX_LENGTH,这表示使用最大允许的盐长度。
在实际应用中,签名验证失败可能会抛出异常,因此我们使用try-except块来捕获可能发生的异常。

3. RSA_oaep

RSA-OAEP(Optimal Asymmetric Encryption Padding)是一种基于 RSA 加密算法的加密方案,旨在提供对抗适应性选择密文攻击(adaptive chosen-ciphertext attack)的安全性。OAEP 是由Bellare 和 Rogaway 在1994年提出的,并且被包含在 PKCS#1 v2.0 及以后的版本中。

RSA-OAEP 是一种概率性加密方案,这意味着即使使用相同的密钥对相同的明文进行多次加密,每次产生的密文也是不同的。

以下是 RSA-OAEP 加密和解密过程的基本步骤:

3.1 加密过程:
步骤一:消息预处理
  1. 选择一个随机盐值 ( s )。
  2. 使用一个哈希函数 ( H ) 和一个掩码生成函数 ( MGF ),将明文消息 ( m ) 和盐值 ( s ) 结合起来,生成一个编码的消息块 ( EM )。
步骤二:加密
  1. 使用公钥 ( (n, e) ) 对编码的消息块 ( EM ) 进行加密:
    c ≡ E M e m o d    n c \equiv EM^e \mod n cEMemodn
    其中,( c ) 是密文。
3.2 解密过程:
步骤一:解密
  1. 使用私钥 ( (n, d) ) 对密文 ( c ) 进行解密:
    E M ′ ≡ c d m o d    n EM' \equiv c^d \mod n EMcdmodn
步骤二:消息提取
  1. 从 ( EM’ ) 中提取盐值 ( s ) 和明文消息 ( m )。
  2. 使用相同的哈希函数 ( H ) 和掩码生成函数 ( MGF ),验证 ( EM’ ) 的结构是否正确。
步骤三:验证和提取
  1. 如果 ( EM’ ) 的结构验证通过,则提取明文消息 ( m )。
  2. 如果结构验证失败,则拒绝解密,因为密文可能被篡改或不是有效的加密结果。
3.3 RSA-OAEP的特点:
  • 安全性:OAEP设计用来提供在随机预言模型下的语义安全性,这意味着即使攻击者可以请求对任意密文的解密,他们也无法获取关于明文的任何信息。
  • 填充方案:OAEP使用了一种复杂的填充方案,这使得即使攻击者知道了一些密文和对应的明文,也无法轻易地为其他明文伪造密文。
  • 适应性:OAEP能够抵抗适应性选择密文攻击,这是加密方案的一个重要安全属性。

由于这些特性,RSA-OAEP被认为是目前最安全的RSA加密方案之一,并且被广泛应用于各种加密标准和协议中。

3.4 程序示例

以下是一个简单的 Python 脚本,演示了如何生成 RSA密钥对、使用公钥进行加密以及使用私钥进行解密:

from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding

# 生成RSA密钥对
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)
public_key = private_key.public_key()

# 将私钥和公钥序列化为PEM格式
private_pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
)
public_pem = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

# 要加密的消息
message = b"Secret message"

# 使用公钥和OAEP填充进行加密
ciphertext = public_key.encrypt(
    message,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# 打印加密后的文本(通常是二进制数据)
print("Ciphertext:\n", ciphertext)

# 使用私钥进行解密
try:
    decrypted_message = private_key.decrypt(
        ciphertext,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    print("Decrypted message:", decrypted_message)
except Exception as e:
    print("Decryption failed:", e)

在这个脚本中,我们执行了以下步骤:

  1. 生成一个2048位的RSA密钥对。
  2. 将私钥和公钥序列化为PEM格式,以便于存储和传输。
  3. 使用公钥和OAEP填充方案对消息进行加密。
  4. 使用私钥对加密后的消息进行解密。

在 RSA-OAEP加密方案中,我们使用了MGF1(Mask Generation Function 1)和 SHA-256哈希算法。label参数设置为None,但在某些情况下,可以提供一个标签来提供额外的上下文。
请注意,RSA加密通常用于加密小量的数据,如密钥交换中的对称密钥,而不是大量数据,因为RSA加密和解密操作相对较慢。

这个示例展示了 RSA-OAEP加密和解密的基本流程,它通常用于安全通信场景,以确保消息的机密性。

4. 异同点

RSA算法、RSA-PSS和RSA-OAEP都是基于RSA加密算法构建的,但它们用于不同的目的,并具有一些关键的区别。以下是这三种算法的异同点:

4.1 相同点:
  1. 基于RSA加密算法:以上这三种算法都基于 RSA公钥加密算法,使用 RSA密钥对(公钥和私钥)进行操作。
  2. 非对称加密:它们都是非对称加密算法,意味着它们使用一对密钥:一个公钥用于加密或验证签名,一个私钥用于解密或生成签名。
  3. 密钥长度:这些算法通常支持相同的密钥长度,如2048位、3072位或4096位,密钥长度决定了算法的安全性。
4.2 不同点:
  1. 用途
    • RSA:传统的 RSA算法可以用于加密和解密,也可以用于数字签名。但是,由于安全性的问题,直接使用 RSA进行加密或签名(没有适当的填充方案)是不推荐的。
    • RSA-PSS:RSA-PSS是一种签名方案,专门用于生成和验证数字签名。它使用概率性填充方案来提高签名过程的安全性。
    • RSA-OAEP:RSA-OAEP是一种加密方案,专门用于加密数据。它使用 OAEP填充方案来提高加密过程的安全性。
  2. 填充方案
    • RSA:传统的 RSA加密和签名通常使用简单的填充方案,如PKCS#1 v1.5,但这些方案容易受到某些类型的攻击。
    • RSA-PSS:RSA-PSS使用一种称为 PSS(Probabilistic Signature Scheme)的填充方案,该方案提供了更强的安全性,特别是在抵抗适应性选择密文攻击方面。
    • RSA-OAEP:RSA-OAEP使用 OAEP(Optimal Asymmetric Encryption Padding)填充方案,该方案提供了更强的安全性,特别是在抵抗适应性选择明文攻击方面。
  3. 安全性
    • RSA:直接使用 RSA(没有适当的填充方案)存在安全风险,如侧信道攻击和填充攻击。
    • RSA-PSS:RSA-PSS被认为是目前最安全的RSA签名方案之一,因为它提供了更强的抗攻击能力。
    • RSA-OAEP:RSA-OAEP被认为是目前最安全的RSA加密方案之一,因为它提供了更强的抗攻击能力。
  4. 性能
    • RSA:传统的RSA操作可能相对较快,但由于安全风险,通常不推荐使用。
    • RSA-PSSRSA-OAEP:由于使用了更复杂的填充方案,RSA-PSS 和 RSA-OAEP的操作可能比传统RSA稍微慢一些,但这是为了提高安全性。

总的来说,RSA-PSS 和 RSA-OAEP是 RSA算法的改进版本,它们通过使用更安全的填充方案来提高算法的安全性,但牺牲了一些性能。在实际应用中,RSA-PSS 用于数字签名,而 RSA-OAEP用于数据加密。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值