我需要多个EVP_CIPHER_CTX结构吗?

 MySeptember 发布于 2023-01-08 08:20

我有一个单线程客户端/服务器应用程序,需要对其网络通信进行加密和解密.我计划使用OpenSSL的EVP API和AES-256-CBC.

我从一些例子中找到了一些示例伪代码:

// key is 256 bits (32 bytes) when using EVP_aes_256_*()
// I think iv is the same size as the block size, 128 bits (16 bytes)...is it?
1: EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
2: EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv, 1); //0=decrypt, 1=encrypt
3: EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen);
4: EVP_CipherFinal_ex(ctx, outbuf + outlen, &tmplen));
5: outlen += tmplen;
6: EVP_CIPHER_CTX_cleanup(ctx);
7: EVP_CIPHER_CTX_free(ctx);

问题来自所有这些例子,我不确定在每次加密/解密时需要做什么,以及我应该只在启动时做一次.

特别:

在第1行,我是否只创建EVP_CIPHER_CTX一次并继续重复使用它直到应用程序结束?

同样在第1行,我可以重复使用相同EVP_CIPHER_CTX的加密和解密,或者我应该创建其中的2个?

在第2行,是否应该在我正在加密的每个数据包上重新设置IV?或者我只将IV设置一次,然后让它永远继续下去?

如果我正在加密UDP数据包,数据包很容易丢失或被无序接收怎么办?我认为CBC无法正常工作,或者我需要在每个数据包开始时重置IV我发出去了?

小智.. 10

很抱歉恢复旧线程,但我注意到接受的答案中出现以下错误:

在第1行,我是否只创建一次EVP_CIPHER_CTX并继续重复使用它直到应用程序结束?

您每次使用都会创建一次.也就是说,当您需要加密时,您使用相同的上下文.如果需要加密第二个流,则可以使用第二个上下文.如果您需要解密第三个流,您将使用第三个上下文.

同样在第1行,我可以重复使用相同的EVP_CIPHER_CTX加密和解密,还是我应该创建其中的2个?

不,见上文.

这不是必需的.从OpenSSL的手册页:

新代码应该使用EVP_EncryptInit_ex(),EVP_EncryptFinal_ex(),EVP_DecryptInit_ex(),EVP_DecryptFinal_ex(),EVP_CipherInit_ex()和EVP_CipherFinal_ex(),因为它们可以重用现有的上下文,而无需在每次调用时分配和释放它.

换句话说,您需要在每次使用之前重新初始化上下文,但是您可以反复使用相同的上下文而无需创建(分配)新的上下文.

2 个回答
  • 我有一个单线程客户端/服务器应用程序,需要对其网络通信进行加密和解密.我计划使用OpenSSL的EVP API和AES-256-CBC.

    如果您使用的是SSL_*函数libssl,那么您可能永远不会触及EVP_*API.


    在第1行,我是否只创建一次EVP_CIPHER_CTX并继续重复使用它直到应用程序结束?

    您每次使用都会创建一次.也就是说,当您需要加密时,您使用相同的上下文.如果需要加密第二个流,则可以使用第二个上下文.如果您需要解密第三个流,您将使用第三个上下文.


    同样在第1行,我可以重复使用相同的EVP_CIPHER_CTX加密和解密,还是我应该创建其中的2个?

    不,见上文.

    密码将具有不同的状态.


    在第2行,是否应该在我正在加密的每个数据包上重新设置IV?或者我只将IV设置一次,然后让它永远继续下去?

    不.你设置IV一次然后忘了它.这是上下文对象为密码管理的状态的一部分.


    如果我正在加密UDP数据包,数据包很容易丢失或被无序接收该怎么办?我认为CBC无法正常工作......

    如果您使用的是UDP,则由您来检测这些类型的问题.你可能最终会重新发明TCP.

    仅加密通常是不够的.您还需要确保真实性和完整性.您不对不真实的数据进行操作.这就是让SST/TLS和SSH陷入困境的原因.

    例如,在SSL/TLS使用的Authenticate-Then-Encrypt(EtA)方案中,编写关于IPSec,SSL/TLS和SSH的认证加密的开创性论文的人:最后调用:(加密 - 然后-TAC for TLS和DTLS)建议标准:

    我在2001年的论文中的技术结果是正确的,但关于SSL/TLS的结论是错误的.我假设TLS使用新的IV并且MAC是在编码的明文上计算的,即Encode-Mac-Encrypt,而TLS正在进行Mac-Encode-Encrypt,这正是我的理论示例显示的不安全.

    为了真实性,您应该放弃CBC模式并切换到GCM模式.GCM是一种经过身份验证的加密模式,它将机密性和真实性结合到一种模式中,因此您无需组合基元(如AES/CBC和HMAC).


    或者这是我需要在发送的每个数据包开始时重置IV的地方?

    不,你设置IV一次然后忘记它.


    问题来自所有这些例子,我不确定在每次加密/解密时需要做什么,以及我应该只在启动时做一次.

      创建一次: EVP_CIPHER_CTX

      调用此设置一次: EVP_CipherInit

      根据您的喜好多次调用: EVP_CipherUpdate

      将此调用一次以进行清理: EVP_CipherFinal

    OpenSSL wiki有很多使用这些EVP_*接口的例子.请参阅EVP对称加密和解密,EVP认证加密和解密以及EVP签名和验证.

    所有的例子都使用相同的模式:Init,Update然后Final.它的加密或散列并不重要.


    相关:您应该对此感兴趣:EVP Authenticated Encryption and Decryption.它的示例代码来自OpenSSL wiki.


    相关:您可以在线找到Viega,Messier和Chandra的Network Security与OpenSSL的副本.您可以考虑搜索副本并熟悉其中的一些概念.

    2023-01-08 08:23 回答
  • 很抱歉恢复旧线程,但我注意到接受的答案中出现以下错误:

    在第1行,我是否只创建一次EVP_CIPHER_CTX并继续重复使用它直到应用程序结束?

    您每次使用都会创建一次.也就是说,当您需要加密时,您使用相同的上下文.如果需要加密第二个流,则可以使用第二个上下文.如果您需要解密第三个流,您将使用第三个上下文.

    同样在第1行,我可以重复使用相同的EVP_CIPHER_CTX加密和解密,还是我应该创建其中的2个?

    不,见上文.

    这不是必需的.从OpenSSL的手册页:

    新代码应该使用EVP_EncryptInit_ex(),EVP_EncryptFinal_ex(),EVP_DecryptInit_ex(),EVP_DecryptFinal_ex(),EVP_CipherInit_ex()和EVP_CipherFinal_ex(),因为它们可以重用现有的上下文,而无需在每次调用时分配和释放它.

    换句话说,您需要在每次使用之前重新初始化上下文,但是您可以反复使用相同的上下文而无需创建(分配)新的上下文.

    2023-01-08 08:23 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有