openssl evp
时间: 2023-08-05 09:05:48 浏览: 58
OpenSSL EVP是OpenSSL库中的一个模块,提供了丰富的密码学函数。它封装了各种对称算法、摘要算法以及签名/验签算法。EVP系列函数的声明包含在"evp.h"头文件中,通过这些函数可以使用不同的加密算法进行数据的加密和解密。EVP主要封装了加密、摘要、编码三大类型的算法,并且提供了一些辅助函数。其中,加密算法和摘要算法是基本的功能,公开密钥算法使用对称加密算法对数据进行加密,使用非对称加密算法对密钥进行加密和解密。数字签名是使用非对称算法进行私钥签名和公钥认证。EVP还封装了base64编解码BIO、加解密BIO、摘要BIO、reliable BIO等功能函数,以及对称加解密算法、非对称密钥的加密、解密、签名和验证等功能函数。此外,EVP还提供了基于口令的加密(PBE)、对称密钥处理、数字信封等功能。[2]
在EVP中,seal系列函数实现了一个电子信封的功能。它生成一个随机密钥,并使用公钥对该密钥进行封装。数据可以使用该随机密钥进行对称加密。信封加密在大量数据传输时非常常用,因为公开密钥算法的加解密速度较慢,而对称算法的速度更快。因此,一般使用公开密钥算法对生成的随机密钥进行加密,然后使用该随机密钥进行对称加密。最后,将加密后的密钥与数据一起发送。seal系列函数的定义如下:EVP_SealInit、EVP_SealUpdate和EVP_SealFinal。[3]
相关问题
openssl EVP_DigestSignFinal EVP_DigestVerifyFinal完整代码示例
以下是 OpenSSL EVP_DigestSignFinal 和 EVP_DigestVerifyFinal 函数的完整代码示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#define BUFFER_SIZE 1024
int sign_data(const char *message, const char *private_key_path, unsigned char **signature, size_t *signature_length) {
EVP_PKEY *pkey = NULL;
EVP_MD_CTX *mdctx = NULL;
const EVP_MD *md = NULL;
int result = 0;
// Load private key
FILE *fp = fopen(private_key_path, "r");
if (!fp) {
printf("Error: Failed to open private key file.\n");
goto cleanup;
}
pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
fclose(fp);
if (!pkey) {
printf("Error: Failed to load private key.\n");
goto cleanup;
}
// Initialize message digest context
md = EVP_get_digestbyname("SHA256");
if (!md) {
printf("Error: Failed to get message digest.\n");
goto cleanup;
}
mdctx = EVP_MD_CTX_new();
if (!mdctx) {
printf("Error: Failed to create message digest context.\n");
goto cleanup;
}
if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) {
printf("Error: Failed to initialize message digest context.\n");
goto cleanup;
}
// Update message digest context with message
if (EVP_DigestUpdate(mdctx, message, strlen(message)) != 1) {
printf("Error: Failed to update message digest context.\n");
goto cleanup;
}
// Sign message digest
size_t siglen = EVP_PKEY_size(pkey);
*signature = (unsigned char*)malloc(siglen);
if (!*signature) {
printf("Error: Failed to allocate memory for signature.\n");
goto cleanup;
}
if (EVP_DigestSignFinal(mdctx, *signature, &siglen, pkey) != 1) {
printf("Error: Failed to sign message digest.\n");
goto cleanup;
}
*signature_length = siglen;
result = 1;
cleanup:
if (mdctx) {
EVP_MD_CTX_free(mdctx);
}
if (pkey) {
EVP_PKEY_free(pkey);
}
return result;
}
int verify_signature(const char *message, unsigned char *signature, size_t signature_length, const char *public_key_path) {
EVP_PKEY *pkey = NULL;
EVP_MD_CTX *mdctx = NULL;
const EVP_MD *md = NULL;
int result = 0;
// Load public key
FILE *fp = fopen(public_key_path, "r");
if (!fp) {
printf("Error: Failed to open public key file.\n");
goto cleanup;
}
pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
fclose(fp);
if (!pkey) {
printf("Error: Failed to load public key.\n");
goto cleanup;
}
// Initialize message digest context
md = EVP_get_digestbyname("SHA256");
if (!md) {
printf("Error: Failed to get message digest.\n");
goto cleanup;
}
mdctx = EVP_MD_CTX_new();
if (!mdctx) {
printf("Error: Failed to create message digest context.\n");
goto cleanup;
}
if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) {
printf("Error: Failed to initialize message digest context.\n");
goto cleanup;
}
// Update message digest context with message
if (EVP_DigestUpdate(mdctx, message, strlen(message)) != 1) {
printf("Error: Failed to update message digest context.\n");
goto cleanup;
}
// Verify signature
if (EVP_DigestVerifyFinal(mdctx, signature, signature_length, pkey) != 1) {
printf("Error: Failed to verify signature.\n");
goto cleanup;
}
result = 1;
cleanup:
if (mdctx) {
EVP_MD_CTX_free(mdctx);
}
if (pkey) {
EVP_PKEY_free(pkey);
}
return result;
}
int main() {
const char *message = "Hello, world!";
const char *private_key_path = "private_key.pem";
const char *public_key_path = "public_key.pem";
unsigned char *signature = NULL;
size_t signature_length = 0;
// Sign data
if (!sign_data(message, private_key_path, &signature, &signature_length)) {
printf("Error: Failed to sign data.\n");
goto cleanup;
}
// Verify signature
if (!verify_signature(message, signature, signature_length, public_key_path)) {
printf("Error: Failed to verify signature.\n");
goto cleanup;
}
printf("Signature verified successfully.\n");
cleanup:
if (signature) {
free(signature);
}
return 0;
}
```
该示例使用 SHA256 哈希算法对消息进行哈希,并使用 RSA 私钥对哈希进行签名。然后,使用 RSA 公钥验证签名是否正确。在实际使用中,需要将示例代码中的私钥和公钥路径替换为实际路径。
openssl 学习 evp
OpenSSL中的EVP(Enveloped Data Processing)是一个高级API,提供了一种简单易用的方式来实现各种密码学算法。EVP API支持对称加密、非对称加密、哈希、消息认证码(MAC)和数字签名等功能。
以下是一些使用EVP API的示例:
1. 对称加密
对称加密使用相同的密钥对数据进行加密和解密。以下代码展示了如何使用EVP API进行对称加密:
```c
EVP_CIPHER_CTX *ctx;
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
EVP_EncryptUpdate(ctx, out, &outl, in, inl);
EVP_EncryptFinal_ex(ctx, out + outl, &tmpl);
EVP_CIPHER_CTX_free(ctx);
```
其中,key是加密密钥,iv是初始化向量,in是输入数据,inl是输入数据长度,out是输出数据,outl是输出数据长度,tmpl是临时变量。
2. 非对称加密
非对称加密使用公钥加密数据,私钥解密数据。以下代码展示了如何使用EVP API进行非对称加密:
```c
EVP_PKEY *pkey;
pkey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(pkey, rsa);
EVP_PKEY_CTX *ctx;
ctx = EVP_PKEY_CTX_new(pkey, NULL);
EVP_PKEY_encrypt_init(ctx);
EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING);
EVP_PKEY_encrypt(ctx, out, &outl, in, inl);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
```
其中,rsa是RSA密钥对,in是输入数据,inl是输入数据长度,out是输出数据,outl是输出数据长度。
3. 哈希
哈希函数将任意长度的数据映射为固定长度的摘要值。以下代码展示了如何使用EVP API进行哈希:
```c
EVP_MD_CTX *ctx;
ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
EVP_DigestUpdate(ctx, in, inl);
EVP_DigestFinal_ex(ctx, out, &outl);
EVP_MD_CTX_free(ctx);
```
其中,in是输入数据,inl是输入数据长度,out是输出数据,outl是输出数据长度。
4. MAC
MAC是一种用于验证消息完整性和真实性的技术。以下代码展示了如何使用EVP API进行MAC:
```c
EVP_MD_CTX *ctx;
ctx = EVP_MD_CTX_new();
EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, pkey);
EVP_DigestSignUpdate(ctx, in, inl);
EVP_DigestSignFinal(ctx, out, &outl);
EVP_MD_CTX_free(ctx);
```
其中,pkey是私钥,in是输入数据,inl是输入数据长度,out是输出数据,outl是输出数据长度。
5. 数字签名
数字签名是一种用于验证消息来源和完整性的技术。以下代码展示了如何使用EVP API进行数字签名:
```c
EVP_MD_CTX *ctx;
ctx = EVP_MD_CTX_new();
EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, pkey);
EVP_DigestSignUpdate(ctx, in, inl);
EVP_DigestSignFinal(ctx, NULL, &slen);
EVP_SignFinal(ctx, out, &outl, pkey);
EVP_MD_CTX_free(ctx);
```
其中,pkey是私钥,in是输入数据,inl是输入数据长度,out是输出数据,outl是输出数据长度,slen是临时变量。