Linux C语言调用OpenSSL: RSA签名验签算法(填充模式PSS)

一、概述

在OpenSSL中,有多种签名验签算法,包括:RSA (Rivest-Shamir-Adleman)、DSA (Digital Signature Algorithm)、ECDSA (Elliptic Curve Digital Signature Algorithm)、EdDSA (Edwards-curve Digital Signature Algorithm)、SM2算法等。
本文主讲RSA签名验签算法的PSS填充模式。
本文对签名验签的机制只做简单介绍,若对签名验签机制存疑,可参考我的其他博客。

1. RSA签名流程

在OpenSSL中进行签名,需要一个私钥(通常是一个PEM或DER格式的密钥文件)。以下是一个简化的签名过程:

加载私钥:使用OpenSSL的API(如PEM_read_RSAPrivateKey或d2i_PrivateKey)从密钥文件中加载私钥。
计算数据的哈希值:使用OpenSSL的哈希函数(如SHA256)计算要签名的数据的哈希值。
签名哈希值:使用私钥对哈希值进行签名。
输出签名:将签名结果以适当的格式(如DER或PEM)输出。

2. RSA验签流程

在OpenSSL中进行验签,需要公钥和签名数据。以下是一个简化的验签过程:

加载公钥:使用OpenSSL的API(如PEM_read_RSAPublicKey或d2i_PUBKEY)从公钥文件中加载公钥。
计算数据的哈希值:与签名过程相同,使用相同的哈希函数计算要验签的数据的哈希值。
验签哈希值:使用公钥和签名数据对哈希值进行验签。
检查结果:根据验签函数的返回值判断签名是否有效。

3. RSA签名验签算法填充模式

常见的填充模式包括PKCS#1 v1.5填充、PKCS#1 OAEP填充和PSS填充。以下是它们的大致原理和特点:
PKCS#1 v1.5填充:
原理: 在进行RSA签名时,首先需要对消息进行填充以满足RSA算法的要求。PKCS#1 v1.5填充是一种较早期的填充模式,它在消息前面添加了一定数量的随机字节,以增加填充的随机性,然后再进行RSA加密。
特点:PKCS#1 v1.5填充是一种较为简单的填充模式,广泛应用于RSA签名和加密中。然而,它存在一些安全性方面的问题,如存在一些攻击方法可以利用其漏洞进行RSA签名伪造或密文恢复。
PKCS#1 OAEP填充:
原理:OAEP(Optimal Asymmetric Encryption Padding)是一种改进的填充模式,旨在提供更好的安全性。它引入了一个哈希函数和掩盖函数,将消息进行填充,以增加填充的随机性,并提供一定程度的抗攻击能力。
特点:PKCS#1 OAEP填充相对于PKCS#1 v1.5填充来说,提供了更好的安全性,能够抵御一些针对PKCS#1 v1.5填充的攻击。因此,在更高安全要求的场景下,推荐使用OAEP填充。
PSS填充:
原理:PSS(Probabilistic Signature Scheme)是一种基于随机化的签名填充方案,旨在提供更好的安全性和抗攻击能力。它引入了随机盐和哈希函数,将消息进行填充,并采用一定的概率分布来生成填充的结果。
特点:PSS填充提供了更好的安全性和抗攻击能力,相对于PKCS#1 v1.5填充和OAEP填充来说,更为推荐。它提供了更好的防护机制,能够抵御一些针对RSA签名填充的攻击,如长度扩展攻击等。

总的来说,PKCS#1 v1.5填充是最简单的填充模式,但安全性较低,OAEP填充提供了更好的安全性,而PSS填充则是最推荐的填充模式,提供了更高的安全性和抗攻击能力。

4. 注意事项

在进行签名验签时,要确保:

  1. 使用的哈希算法和签名算法,与公私钥生成时使用的算法相同;
  2. 签名和验签使用的算法填充模式相同。

二、调用函数介绍

本文主要使用openssl中,EVP高级函数来实现签名验签。

1. EVP高级函数简介

在OpenSSL中,可用于签名验签的接口很多,官方的封装上比较杂,本人在开发过程中倾向于全使用EVP打头的函数,整洁统一安全。
关于EVP高级函数,可以参考我的博客Linux C语言调用OpenSSL:EVP 接口概述

2. hash算法

RSA签名验签过程中,会对原文计算hash,涉及一些计算hash的openssl接口,这部分内容可以参考我的另一篇博客:
Linux C语言调用OpenSSL: 摘要算法(SHA-2和SHA-3)

3. EVP_PKEY_new

动态地分配并初始化一个 EVP_PKEY 结构体。这个结构体通常与特定的密钥类型(如 RSA、DSA、EC 等)关联,并且包含密钥的实际数据。

#include <openssl/evp.h>
EVP_PKEY *EVP_PKEY_new(void);

返回值:
如果成功,返回一个指向新分配的 EVP_PKEY 结构体的指针。如果失败,返回 NULL。

注意:
(1)通常不会直接使用 EVP_PKEY_new 来生成密钥。应该使用特定于密钥类型的函数(如 RSA_generate_key_ex、EC_KEY_generate_key 等)来生成密钥,并将生成的密钥设置为 EVP_PKEY 结构体的内容。
(2)当使用完 EVP_PKEY 结构体后,应该使用 EVP_PKEY_free 函数来释放它,以避免内存泄漏。
(3)如果在创建 EVP_PKEY 结构体后没有设置其密钥类型或内容,那么它就是一个“空”的或“未初始化”的 EVP_PKEY 结构体,并且可能无法用于任何有意义的操作。

4. EVP_PKEY_set1_RSA

用于将RSA密钥(RSA *类型)设置为EVP密钥(EVP_PKEY *类型)的RSA部分。

#include <openssl/evp.h>
#include <openssl/rsa.h>
int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key)

参数:
*EVP_PKEY pkey:这是一个指向EVP_PKEY结构的指针,该结构表示一个公
  • 26
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一些关于使用openssl编写RSA加解密算法RSA签名验证算法的基本思路: 1. 引入openssl库 在代码文件中引入openssl库头文件,如下所示: ```c #include <openssl/rsa.h> #include <openssl/pem.h> ``` 2. 生成RSA密钥对 使用openssl库生成RSA密钥对,示例代码如下: ```c RSA *rsa = RSA_new(); BIGNUM *bne = BN_new(); unsigned long e = RSA_F4; if (BN_set_word(bne, e) != 1) { // error } if (RSA_generate_key_ex(rsa, 2048, bne, NULL) != 1) { // error } // 获取公钥和私钥 EVP_PKEY *private_key = EVP_PKEY_new(); EVP_PKEY *public_key = EVP_PKEY_new(); if (EVP_PKEY_assign_RSA(private_key, rsa) != 1) { // error } if (EVP_PKEY_assign_RSA(public_key, rsa) != 1) { // error } // 释放bne BN_free(bne); ``` 3. RSA加解密算法 使用openssl库进行RSA加解密算法,示例代码如下: ```c // 加密 unsigned char *encrypt_data = NULL; int encrypt_length = RSA_public_encrypt(data_length, data, encrypt_data, public_key, RSA_PKCS1_PADDING); // 解密 unsigned char *decrypt_data = NULL; int decrypt_length = RSA_private_decrypt(encrypt_length, encrypt_data, decrypt_data, private_key, RSA_PKCS1_PADDING); ``` 4. RSA签名验证算法 使用openssl库进行RSA签名验证算法,示例代码如下: ```c // 签名 unsigned char *sign_data = NULL; unsigned int sign_length = 0; EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); EVP_SignInit(md_ctx, EVP_sha256()); EVP_SignUpdate(md_ctx, data, data_length); EVP_SignFinal(md_ctx, sign_data, &sign_length, private_key); // 验证签名 EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); EVP_VerifyInit(md_ctx, EVP_sha256()); EVP_VerifyUpdate(md_ctx, data, data_length); int verify_result = EVP_VerifyFinal(md_ctx, sign_data, sign_length, public_key); ``` 以上是基本的思路,您可以参考这些代码来使用openssl库实现RSA加解密算法RSA签名验证算法。当然,具体的实现细节和代码结构还需要根据您的具体需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值