Aes 我需要多个EVP\u CIPHER\u CTX结构吗?

Aes 我需要多个EVP\u CIPHER\u CTX结构吗?,aes,openssl,Aes,Openssl,我有一个单线程客户机/服务器应用程序,需要对其网络通信进行加密和解密。我计划使用OpenSSL的EVPAPI和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

我有一个单线程客户机/服务器应用程序,需要对其网络通信进行加密和解密。我计划使用OpenSSL的EVPAPI和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\u CIPHER\u CTX
    ,并继续重复使用它,直到应用程序结束
  • 同样在第1行,我是否可以对加密和解密重复使用相同的
    EVP\u CIPHER\u CTX
    ,或者我应该创建两个
  • 在第2行,应该在我加密的每个数据包上重新设置IV吗?还是我只注射一次,然后让它永远持续
  • 如果我对UDP数据包进行加密,数据包很容易丢失或收到时出现故障,该怎么办:我认为CBC无法工作是正确的,还是我需要在发送的每个数据包开始时重置IV
我有一个单线程客户机/服务器应用程序,需要对其网络通信进行加密和解密。我计划使用OpenSSL的EVPAPI和AES-256-CBC

如果您正在使用
libssl
中的
SSL
函数,那么您可能永远不会接触
EVP
api


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

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


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

不,见上文

密码将具有不同的状态


在第2行,应该在我加密的每个数据包上重新设置IV吗?还是我只注射一次,然后让它永远持续

不,你先给静脉注射一次,然后就忘了。这是上下文对象为密码管理的状态的一部分


如果我正在加密UDP数据包,数据包很容易丢失或被无序接收,该怎么办:我认为CBC不起作用是正确的吗

如果您使用的是UDP,那么就由您来检测这类问题。您可能最终会重新发明TCP

仅仅加密通常是不够的。您还需要确保真实性和完整性。你不能对不真实的数据进行操作。这就是为什么SST/TLS和SSH总是遇到麻烦

例如,这里有一个人写了关于IPSec、SSL/TLS和SSH的文章,他参与了SSL/TLS使用的先验证后加密(EtA)方案:

我2001年论文中的技术结果是正确的,但结论是正确的 关于SSL/TLS是错误的。我假设TLS使用的是新鲜静脉注射和 MAC是在编码的明文上计算的,即。 编码Mac加密,而TLS正在执行Mac编码加密,这是 我的理论例子所显示的正是不安全的

为了保证真实性,您应该放弃CBC模式并切换到GCM模式。GCM是一种经过身份验证的加密模式,它将机密性和真实性结合到一种模式中,因此您不必将原语(如AES/CBC和HMAC)结合起来


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

不,你先给静脉注射一次,然后就忘了


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

  • 创建一次:
    EVP\u CIPHER\u CTX
  • 调用此设置一次:
    EVP\u CipherInit
  • 您可以多次调用此命令:
    EVP\u CipherUpdate
  • 为清理调用此命令一次:
    EVP\u CipherFinal
  • OpenSSL wiki有很多使用
    EVP.*
    接口的示例。看,还有

    所有示例都使用相同的模式:
    Init
    Update
    ,然后是
    Final
    。它的加密或散列都无关紧要


    相关:您应该对此感兴趣:。它的示例代码来自OpenSSL wiki



    相关:你可以在网上找到维加、梅西耶和钱德拉的副本。你可能会考虑寻找一个拷贝并熟悉它的一些概念。

    < P>对不起,为了恢复一个旧线程,但是我发现在接受的答案中有以下错误:

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

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

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

    不,见上文

    这是没有必要的。从OpenSSL的手册页:

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


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

    很抱歉也恢复了一个旧线程,但Lazershark在评论中两次询问了evp密码上下文。我在这里没有足够的声誉点来添加一些评论,这就是为什么我要