一、 RSA 介绍
RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,它是由Ron Rivest、Adi Shamir和Leonard Adleman于1977年共同提出的,是最早的一种用于公开密钥加密和数字签名的算法。RSA算法的安全性基于大数因子分解的难度,即大整数分解问题。
以下是关于RSA加密算法的详细知识点:
1.1. 非对称加密算法
- RSA是一种非对称加密算法,它使用一对公钥(public key)和私钥(private key)。公钥用于加密,私钥用于解密。由于使用不同的密钥进行加密和解密,因此被称为非对称加密算法。
1.2. 大数因子分解问题
- RSA的安全性基于大数因子分解问题,即将一个非常大的整数分解为两个质数的乘积。目前尚未找到一种高效算法可以在合理时间内解决大整数的分解问题,这使得RSA在当前计算机性能下是安全的。
1.3. 加密过程
RSA加密过程涉及使用公钥加密数据,而接收方使用私钥解密数据。以下是RSA加密的详细过程:
1.3.1. 密钥生成
- 首先,生成一对RSA密钥,包括公钥(public key)和私钥(private key)。这对密钥是由两个大素数(p和q)生成的。计算n = p * q,n作为RSA的模数。选择一个与(n)的欧拉函数(φ(n) = (p-1)(q-1))互质的整数e,作为公钥的指数。然后,计算私钥d,满足 ( d ≡ e − 1 ( mod φ ( n ) ) ) (d \equiv e^{-1} \ (\text{mod}\ \varphi(n))) (d≡e−1 (mod φ(n))) 。公钥为(n, e),私钥为(n, d)。
1.3.2. 加密
- 发送方获得接收方的公钥 (n, e)。然后,将明文消息m转换成整数,确保 (0 \leq m < n)。接着,使用公钥 (n, e) 对明文消息进行加密。
- 加密的过程使用的是以下公式:
c
≡
m
e
(
mod
n
)
\ c \equiv m^e \ (\text{mod}\ n)
c≡me (mod n)
这里,c是加密后的密文,m是明文消息,e是公钥的指数,n是模数。
1.4 解密过程
- 解密方使用私钥(n, d)将密文c解密还原成明文消息m,计算公式为: m ≡ c d ( mod n ) m \equiv c^d \ (\text{mod}\ n) m≡cd (mod n)
1.5. 数字签名
- RSA还可以用于数字签名。发送方使用私钥对消息的散列值进行签名,接收方使用发送方的公钥验证签名的有效性,确保消息的完整性和来源认证。
1.6 密钥长度
- RSA密钥长度通常以比特(bits)为单位表示。密钥长度越长,安全性越高,但加密和解密的速度相对较慢。一般来说,现代应用中RSA密钥长度通常选择2048比特或更长。
1.7 性能和应用
- RSA算法的性能较差,尤其是对较长的消息进行加密和解密时。因此,在实际应用中,通常使用RSA来加密对称密钥,然后使用对称密钥加密实际的消息。RSA的主要应用领域包括数字签名、密钥协商、数据加密等。
二、Openssl开发详解
2.1 openssl生成并导出RSA密钥对
在 C++ 中使用 OpenSSL 生成 RSA 密钥对的示例代码如下:
#include <iostream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
int main() {
RSA *rsa = RSA_new();
// 生成 RSA 密钥对,这里的 2048 是密钥位数
BIGNUM *e = BN_new();
BN_set_word(e, RSA_F4); // RSA_F4 是通常的公钥指数值
RSA_generate_key_ex(rsa, 2048, e, nullptr);
// 导出公钥到文件
FILE *pubKeyFile = fopen("public_key.pem", "wb");
PEM_write_RSAPublicKey(pubKeyFile, rsa);
// 导出私钥到文件(通常需要密码保护)
FILE *privKeyFile = fopen("private_key.pem", "wb");
PEM_write_RSAPrivateKey(privKeyFile, rsa, nullptr, nullptr, 0, nullptr, nullptr);
// 释放资源
RSA_free(rsa);
BN_free(e);
fclose(pubKeyFile);
fclose(privKeyFile);
std::cout << "RSA密钥对生成成功!" << std::endl;
return 0;
}
这段代码使用 OpenSSL 的函数生成了一个2048位的RSA密钥对,并将公钥和私钥分别导出到public_key.pem
和private_key.pem
文件中。请注意,实际应用中,你可能需要为私钥设置密码保护,以增加安全性。
在编译时,确保你链接了 OpenSSL 的库,例如使用以下命令进行编译:
g++ -o rsa_example rsa_example.cpp -lssl -lcrypto
这个示例只是一个基础的生成RSA密钥对的例子,实际应用中可能需要更多的错误处理和安全性考虑,比如密码保护私钥、处理错误返回值、安全地存储密钥等。
2.3 openssl(RSA)加解密
以下是一个使用 OpenSSL 进行 RSA 加密和解密的 C++ 代码示例。在这个示例中,我们将使用 OpenSSL 生成 RSA 密钥对,然后使用公钥进行加密,私钥进行解密。
#include <iostream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
int main() {
// 生成 RSA 密钥对
RSA *rsa = RSA_generate_key(2048, RSA_F4, nullptr, nullptr);
if (rsa == nullptr) {
std::cerr << "Error generating RSA key pair." << std::endl;
return 1;
}
// 要加密的明文
const char *plain_text = "Hello, RSA Encryption and Decryption!";
int plain_len = strlen(plain_text);
// 分配内存存储加密后的数据
unsigned char *encrypted_text = (unsigned char *)malloc(RSA_size(rsa));
if (encrypted_text == nullptr) {
std::cerr << "Memory allocation failed." << std::endl;
RSA_free(rsa);
return 1;
}
// 使用公钥进行加密
int encrypted_len = RSA_public_encrypt(plain_len, (const unsigned char *)plain_text, encrypted_text, rsa, RSA_PKCS1_PADDING);
if (encrypted_len == -1) {
std::cerr << "Error encrypting data." << std::endl;
free(encrypted_text);
RSA_free(rsa);
return 1;
}
// 使用私钥进行解密
unsigned char *decrypted_text = (unsigned char *)malloc(RSA_size(rsa));
if (decrypted_text == nullptr) {
std::cerr << "Memory allocation failed." << std::endl;
free(encrypted_text);
RSA_free(rsa);
return 1;
}
int decrypted_len = RSA_private_decrypt(encrypted_len, encrypted_text, decrypted_text, rsa, RSA_PKCS1_PADDING);
if (decrypted_len == -1) {
std::cerr << "Error decrypting data." << std::endl;
free(encrypted_text);
free(decrypted_text);
RSA_free(rsa);
return 1;
}
// 输出解密后的明文
std::cout << "Decrypted text: " << decrypted_text << std::endl;
// 释放内存
free(encrypted_text);
free(decrypted_text);
RSA_free(rsa);
return 0;
}
在这个示例中,我们使用 RSA_generate_key
函数生成了一个2048位的 RSA 密钥对。然后,我们使用公钥对明文进行加密,并使用私钥进行解密。请确保你的编译环境中链接了 OpenSSL 库。
请注意,这个示例代码是基本的演示,实际应用中你可能需要添加错误处理、密钥存储、数据编码等功能。确保在实际应用中采取适当的安全措施,例如在存储密钥时使用密码保护。
2.4 openssl(RSA签名)
下面是一个使用 OpenSSL 进行 RSA 数字签名和验证的 C++ 代码示例。在这个示例中,我们使用 OpenSSL 生成 RSA 密钥对,并使用私钥对数据进行签名,然后使用公钥进行验证。
#include <iostream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
int main() {
// 生成 RSA 密钥对
RSA *rsa = RSA_generate_key(2048, RSA_F4, nullptr, nullptr);
if (rsa == nullptr) {
std::cerr << "Error generating RSA key pair." << std::endl;
return 1;
}
// 要签名的数据
const char *data = "Hello, RSA Signature!";
int data_len = strlen(data);
// 分配内存存储签名
unsigned char *signature = (unsigned char *)malloc(RSA_size(rsa));
if (signature == nullptr) {
std::cerr << "Memory allocation failed." << std::endl;
RSA_free(rsa);
return 1;
}
// 使用私钥进行签名
unsigned int signature_len;
int success = RSA_sign(NID_sha256, (const unsigned char *)data, data_len, signature, &signature_len, rsa);
if (success != 1) {
std::cerr << "Error signing data." << std::endl;
free(signature);
RSA_free(rsa);
return 1;
}
// 使用公钥进行验证
success = RSA_verify(NID_sha256, (const unsigned char *)data, data_len, signature, signature_len, rsa);
if (success != 1) {
std::cerr << "Signature verification failed." << std::endl;
} else {
std::cout << "Signature verified successfully." << std::endl;
}
// 释放内存
free(signature);
RSA_free(rsa);
return 0;
}
在这个示例中,我们使用 RSA_generate_key
函数生成了一个2048位的 RSA 密钥对。然后,我们使用私钥对数据进行签名,签名算法使用了SHA-256散列算法(NID_sha256)。接着,我们使用公钥进行签名验证,验证签名的正确性。
请确保你的编译环境中链接了 OpenSSL 库。在实际应用中,你可能需要添加错误处理、密钥存储、数据编码等功能。
三、openssl(RSA)命令详解
OpenSSL 是一个开源的加密和解密工具集,它提供了一系列命令行工具,用于执行各种加密、解密和证书管理操作。在Linux操作系统中,你可以使用 OpenSSL 的命令行工具执行RSA加密、解密、签名、验证等操作。以下是一些常用的 OpenSSL RSA 相关命令的详解:
3.1 openssl生成RSA密钥对
openssl genpkey -algorithm RSA -out private_key.pem
openssl rsa -pubout -in private_key.pem -out public_key.pem
这两个命令分别用于生成RSA私钥和公钥,私钥会保存在private_key.pem
文件中,而公钥则保存在public_key.pem
文件中。
3.2 openssl RSA加密和解密
# 使用公钥加密
openssl rsautl -encrypt -in plaintext.txt -inkey public_key.pem -pubin -out encrypted.txt
# 使用私钥解密
openssl rsautl -decrypt -in encrypted.txt -inkey private_key.pem -out decrypted.txt
这两个命令分别用于使用公钥加密和私钥解密数据。plaintext.txt
是要加密的明文数据,encrypted.txt
是加密后的密文数据,decrypted.txt
是解密后的明文数据。
3.3 openssl RSA签名和验证
# 使用私钥签名
openssl dgst -sha256 -sign private_key.pem -out signature.bin data.txt
# 使用公钥验证签名
openssl dgst -sha256 -verify public_key.pem -signature signature.bin data.txt
这两个命令分别用于使用私钥对数据进行签名,并使用公钥验证签名的有效性。data.txt
是要签名的数据,signature.bin
是签名后的数据。
3.4 openssl 生成RSA密钥和证书请求
# 生成RSA私钥
openssl genpkey -algorithm RSA -out private_key.pem
# 生成CSR(证书签名请求)
openssl req -new -key private_key.pem -out certificate.csr
这两个命令用于生成RSA私钥和证书签名请求(Certificate Signing Request,CSR)。CSR文件(certificate.csr
)包含了公钥和一些身份信息,可以用来向证书颁发机构(CA)申请数字证书。
以上是一些常用的OpenSSL命令行操作,它们使得在Linux系统中执行RSA加密、解密、签名、验证等操作变得方便。具体命令的选项和用法可以使用man openssl
命令来查看OpenSSL的手册页,或者在终端中使用openssl command --help
来获取特定命令的帮助信息。
四、openssl知识点
4.1 公钥指数值
RSA算法中的公钥指数值(公钥指数或公钥取模)通常使用Fermat指数F4,其实际值为65537。Fermat指数是一个较小的质数,通常选择它作为公钥指数是因为它具有良好的性质,如下:
-
安全性: Fermat指数65537是一个质数,它是一个相对较小的素数,同时也不容易被分解,因此它提供了足够的安全性。攻击者通常需要计算模幂运算来破解RSA,选择一个素数作为指数可以增加攻击的难度。
-
速度: Fermat指数具有较小的比特长度,因此进行模幂运算(modular exponentiation)时更快,加速了RSA加密和解密的过程。速度是公钥加密算法中一个关键的性能指标,较小的指数可以提高运算速度。
-
通用性: Fermat指数65537是一个经过广泛测试和使用的值,它在各种情况下都被广泛应用,并被认为是安全性和性能的平衡选择。
因此,RSA算法中公钥的指数通常选择Fermat指数F4(即65537)。实际上,F4是在公共领域中广泛使用的标准指数值。在大多数情况下,选择F4作为公钥指数是一个合适的选择,因为它提供了良好的安全性和性能。