Linux C语言调用OpenSSL:EVP 接口概述

一、EVP接口简介

EVP(Envelope)接口是OpenSSL中一个高级别的加密API,旨在提供一个统一、灵活且安全的方式来进行各种加密操作。它将复杂的加密算法实现细节封装起来,提供给开发者一个简单易用的接口。这使得开发者无需关心具体的算法实现,从而能够更专注于应用逻辑的开发。

OpenSSL提供了两类API:低级API和高级API。低级API是针对特定加密算法的,而高级API(如EVP接口)则能够跨越多种加密算法。低级API虽然提供了更高的灵活性,但它的使用复杂且容易出错。为了简化开发过程并提高代码的可维护性,OpenSSL团队长期以来一直鼓励使用高级API。在OpenSSL 3.0版本中,这一建议变得更加正式:所有低级API被标记为已弃用,并可能在未来版本中移除。

比如:EVP API 提供了一些函数如 EVP_EncryptInit_ex、EVP_EncryptUpdate和 EVP_EncryptFinal来执行对称加密。这些函数可以与多种算法一起使用,如 AES、CHACHA、3DES 等。
如果使用低级API来进行AES加密,需要调用特定于AES的函数,例如 AES_set_encrypt_key、AES_encrypt 等。对于3DES,使用的函数又是不同的。

实际的代码示例,可以参考我的专栏中的其他文章。

二、EVP接口特点

1. 优点

统一接口:EVP接口为多种加密算法提供了统一的调用接口,无论是对称加密、非对称加密还是哈希算法,开发者都可以使用相同的函数来完成相应的操作。
易于维护:由于EVP接口屏蔽了底层算法的细节,当需要更换加密算法时,只需修改初始化函数的参数,其他代码无需变动,大大简化了代码的维护和升级。
灵活性:EVP接口支持多种加密模式和填充方式,并且可以与硬件加速模块结合使用,从而提高加密操作的性能。
安全性:EVP接口提供了更好的内存管理和错误处理机制,减少了内存泄漏和潜在的安全漏洞。
兼容性:通过使用EVP接口,开发者可以确保他们的应用程序在不同版本的OpenSSL中保持更好的兼容性。

2. 缺点

性能开销:由于EVP接口封装了更多的逻辑,相比于直接调用低级API,它可能会带来一定的性能开销。不过,在大多数应用场景中,这种开销是可以接受的。
复杂性:对于一些特定的高级应用场景,使用EVP接口可能无法满足需求,这时仍需借助低级API进行更细粒度的控制。

三、适用场景

数据加密:适用于需要对数据进行对称或非对称加密的场景,如文件加密、网络通信加密等。
消息摘要:适用于需要计算数据摘要的场景,如数据完整性校验、数字签名等。
数字签名和验证:适用于需要进行数据签名和验证的场景,如数字证书的生成和验证。
密钥派生:适用于需要从密码或其他数据派生加密密钥的场景,如密钥交换协议、密码存储等。

四、注意事项

弃用警告:在OpenSSL 3.0及以后版本中,低级API被标记为已弃用,因此强烈建议使用EVP接口进行开发。尽早迁移到EVP接口可以避免未来版本升级时的兼容性问题。
内存管理:尽管EVP接口简化了内存管理,但开发者仍需注意释放分配的内存,以避免内存泄漏。
错误处理:EVP接口提供了详细的错误信息,开发者应充分利用这些信息进行错误处理和调试。
安全实践:在使用EVP接口进行加密操作时,应遵循最佳的安全实践,如使用安全的随机数生成器、避免使用已知不安全的加密算法等。

五、常用的接口

以下列举一些常见的接口:
对称加密
EVP_EncryptInit_ex:初始化加密操作。
EVP_EncryptUpdate:进行数据加密。
EVP_EncryptFinal_ex:完成加密操作。
EVP_DecryptInit_ex:初始化解密操作。
EVP_DecryptUpdate:进行数据解密。
EVP_DecryptFinal_ex:完成解密操作。
消息摘要
EVP_DigestInit_ex:初始化消息摘要计算。
EVP_DigestUpdate:进行消息摘要计算。
EVP_DigestFinal_ex:完成消息摘要计算。
数字签名和验证
EVP_SignInit_ex:初始化签名操作。
EVP_SignUpdate:进行签名计算。
EVP_SignFinal:完成签名操作。
EVP_VerifyInit_ex:初始化验证操作。
EVP_VerifyUpdate:进行验证计算。
EVP_VerifyFinal:完成验证操作。
密钥派生
EVP_PKEY_derive_init:初始化密钥派生操作。
EVP_PKEY_derive_set_peer:设置对等方公钥。
EVP_PKEY_derive:派生密钥。
密钥管理
EVP_PKEY_new:创建新的密钥对象。
EVP_PKEY_free:释放密钥对象。
EVP_PKEY_assign:分配特定类型的密钥。

六、性能对比

1. 测试环境:

在这里插入图片描述

2. 测试的算法

AES(对称加密)
SHA-256(消息摘要)
RSA(非对称加密)
RSA (签名与验证)

AES 性能比较

使用低级API

#include <openssl/aes.h>
#include <string.h>

void aes_encrypt_lowlevel(unsigned char *plaintext, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) {
    AES_KEY enc_key;
    AES_set_encrypt_key(key, 256, &enc_key);
    AES_cbc_encrypt(plaintext, ciphertext, strlen((char *)plaintext), &enc_key, iv, AES_ENCRYPT);
}

使用EVP高级API

#include <openssl/evp.h>
#include <string.h>

void aes_encrypt_evp(unsigned char *plaintext, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) {
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
    int len;
    EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, strlen((char *)plaintext));
    int ciphertext_len = len;
    EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
    ciphertext_len += len;
    EVP_CIPHER_CTX_free(ctx);
}

性能对比
低级API的AES加密通常比EVP接口的AES加密快约5%-10%。具体的性能差异取决于实现细节和系统环境。

SHA-256 性能比较

使用低级API:

#include <openssl/sha.h>

void sha256_lowlevel(unsigned char *input, unsigned char *output) {
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, input, strlen((char *)input));
    SHA256_Final(output, &sha256);
}

使用EVP高级API

#include <openssl/evp.h>

void sha256_evp(unsigned char *input, unsigned char *output) {
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
    EVP_DigestUpdate(ctx, input, strlen((char *)input));
    EVP_DigestFinal_ex(ctx, output, NULL);
    EVP_MD_CTX_free(ctx);
}

性能对比
低级API的SHA-256计算性能通常比EVP接口快约5%-15%。EVP接口的性能开销主要体现在上下文的创建和销毁上。

RSA 加密性能比较

使用低级API:

#include <openssl/rsa.h>
#include <openssl/pem.h>

void rsa_encrypt_lowlevel(RSA *rsa, unsigned char *plaintext, unsigned char *ciphertext) {
    int len = RSA_public_encrypt(strlen((char *)plaintext), plaintext, ciphertext, rsa, RSA_PKCS1_OAEP_PADDING);
}

使用EVP高级API

#include <openssl/evp.h>
#include <openssl/rsa.h>

void rsa_encrypt_evp(EVP_PKEY *pkey, unsigned char *plaintext, unsigned char *ciphertext) {
    EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
    EVP_PKEY_encrypt_init(ctx);
    size_t outlen;
    EVP_PKEY_encrypt(ctx, ciphertext, &outlen, plaintext, strlen((char *)plaintext));
    EVP_PKEY_CTX_free(ctx);
}

性能对比
低级API的RSA加密性能通常比EVP接口快约10%-20%。这主要是由于EVP接口在操作过程中引入了额外的抽象层。

RSA 签名与验证性能比较

使用低级API:

#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
#include <string.h>

void rsa_sign_lowlevel(RSA *rsa, unsigned char *msg, unsigned int msg_len, unsigned char *sig, unsigned int *sig_len) {
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256(msg, msg_len, hash);

    if (RSA_sign(NID_sha256, hash, SHA256_DIGEST_LENGTH, sig, sig_len, rsa) != 1) {
        // Handle error
    }
}

int rsa_verify_lowlevel(RSA *rsa, unsigned char *msg, unsigned int msg_len, unsigned char *sig, unsigned int sig_len) {
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256(msg, msg_len, hash);

    return RSA_verify(NID_sha256, hash, SHA256_DIGEST_LENGTH, sig, sig_len, rsa);
}

使用EVP高级API

#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <string.h>

void rsa_sign_evp(EVP_PKEY *pkey, unsigned char *msg, unsigned int msg_len, unsigned char *sig, size_t *sig_len) {
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    EVP_PKEY_CTX *pkey_ctx = NULL;

    EVP_DigestSignInit(ctx, &pkey_ctx, EVP_sha256(), NULL, pkey);
    EVP_DigestSignUpdate(ctx, msg, msg_len);
    EVP_DigestSignFinal(ctx, NULL, sig_len);
    EVP_DigestSignFinal(ctx, sig, sig_len);

    EVP_MD_CTX_free(ctx);
}

int rsa_verify_evp(EVP_PKEY *pkey, unsigned char *msg, unsigned int msg_len, unsigned char *sig, size_t sig_len) {
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    EVP_PKEY_CTX *pkey_ctx = NULL;
    int ret;

    EVP_DigestVerifyInit(ctx, &pkey_ctx, EVP_sha256(), NULL, pkey);
    EVP_DigestVerifyUpdate(ctx, msg, msg_len);
    ret = EVP_DigestVerifyFinal(ctx, sig, sig_len);

    EVP_MD_CTX_free(ctx);
    return ret;
}

性能对比

低级API的RSA签名验签性能通常比EVP接口快约5%-15%。

七、结论

尽管低级API在性能上有一定优势,但这一优势通常在5%-20%之间。在许多实际应用场景中,这种性能差异并不会对整体系统性能产生显著影响。相反,使用EVP高级API带来的代码简洁性、可维护性和安全性提升是非常显著的。特别是在OpenSSL 3.0及以后的版本中,低级API已被正式弃用,强烈建议开发者迁移到EVP接口。

参考链接:https://www.openssl.org/docs/man3.0/man7/migration_guide.html

  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值