OpenSSL 内存 BIO 和部分密码块

Posted

技术标签:

【中文标题】OpenSSL 内存 BIO 和部分密码块【英文标题】:OpenSSL memory BIO and partial cipher blocks 【发布时间】:2011-10-02 15:43:54 【问题描述】:

我在需要我在本地执行加密和解密的架构中使用 OpenSSL。

解密函数获取一个在连接另一端加密的缓冲区。 加密/解密过程通常可以正常工作,但对于缓冲区包含部分密码块的情况。

我想我的问题归结为: 设 s 是 SSL 对象, buf 是内存缓冲区或加密数据。 我为了解密它所做的(减去错误处理、线程安全、内存安全等)是按照

int decDataBufSize = 1000000; //approximation of length of decrypted data
int8_t* decData = (int8_t*)malloc(decDataBufSize*sizeof(int8_t)); //room for the decrypted data to be written into
BIO* bio = BIO_new_mem_buf(encData, decDataBufSize); //set up BIO pointing to the encrypted data
int decDataLength;
BIO_set_close(bio, BIO_NOCLOSE); //This means OpenSSL doesn't try to free the encrypted data buffer
int totalDecData = 0;
for(int remaining_length = buffie->getBuffer()->limit() ; remaining_length > 0 ; )

    SSL_set_bio(ssl, bio, bio);
    remaining_length -= BIO_pending(bio);
    int decDataLength = SSL_read(ssl, decData + totalDecData, decDataBufSize - totalDecData);
    totalDecData += decDataLength;
    remaining_length += BIO_pending(bio);

return decData;

这似乎工作正常,但对于我在缓冲区中有一部分块的情况。 我知道,如果我使用套接字而不是内存 BIO,我会得到一个 SSL_ERROR_WANT_READ,但在我的情况下,我会得到一个最简洁的 SSL_ERROR_SSL(解密失败或坏记录 mac)。

有什么方法可以提前验证我有一个完整的块吗?

提前致谢

【问题讨论】:

一个 DES 块是 8 个字节。一个 AES 块是 16 个字节。你期望什么大小的块? 我实际上无法提前知道,因为 OpenSSL 也应用压缩... 【参考方案1】:

显然解决方案在于 BIO_get_mem_data。

大致如下: #define DEC_BUF_SIZE 1000000 静态 int 缓冲区长度; 静态 int8_t* 部分块;

int8_t* decrypt(int8_t* ecnData)  
    int decDataBufSize = 1000000; //approximation of length of decrypted data
    int8_t* decData = (int8_t*)malloc(decDataBufSize*sizeof(int8_t)); //room for the decrypted data to be written into
    if (buffer_length == 0) /*prepend the contents of partial_block to encData somehow*/;
    BIO* bio = BIO_new_mem_buf(encData, decDataBufSize); //set up BIO pointing to the encrypted data
    int decDataLength;
    BIO_set_close(bio, BIO_NOCLOSE); //This means OpenSSL doesn't try to free the encrypted data buffer
    int totalDecData = 0;
    for(int remaining_length = buffie->getBuffer()->limit() ; remaining_length > 0 ; ) 
        buffer_length = BIO_get_mem_data(bio,&partial_block);
        SSL_set_bio(ssl, bio, bio);
        remaining_length -= BIO_pending(bio);
        int decDataLength = SSL_read(ssl, decData + totalDecData, decDataBufSize - totalDecData);
        totalDecData += decDataLength;
        remaining_length += BIO_pending(bio);
    
return decData;

【讨论】:

以上是关于OpenSSL 内存 BIO 和部分密码块的主要内容,如果未能解决你的问题,请参考以下文章

使用openssl BIO逐块进行base64解码

OpenSSL之EVP用法

OpenSSL TLS/DTLS PSK

openssl之BIO系列之9---BIO对的创建和应用

为 openssl EVP_PKEY 私钥清理内存的 C 代码

openssl之BIO系列之24---SSL类型的BIO