文章目录
- openssl3.2 - exp - zlib
- 概述
- 笔记
- 命令行实现
- 程序实现
- 备注 - 压缩时无法base64
- 压缩时无法带口令压缩
- 实现 - 对buffer进行压缩和解压缩
- 测试效果
- 工程实现
- main.cpp
- COsslZlibBuffer.h
- COsslZlibBuffer.cpp
- 总结
- END
openssl3.2 - exp - zlib
概述
客户端和服务端进行数据交换时,如果压缩一下要交互的数据,可以节省带宽。
如果数据是文本型, 压缩率特别大。
以前用zlib库单独实验过,写起来还挺麻烦的。
正好这次已经将zlib特性加入了openssl(openssl3.2 - 编译 - zlib.dll不要使用绝对路径), 试一下用openssl来压缩/解压缩数据方便不?
笔记
命令行实现
// openssl zip help
openssl zlib --help
// zip
openssl zlib -e -in test.txt -out test.txt.zlib -pass pass:my_pwd
// unzip
openssl zlib -d -in test.txt.zlib -out test.txt.zlib.unzlib -pass pass:my_pwd
程序实现
先看一下openssl.exe的实现
备注 - 压缩时无法base64
如果选了zlib, 就不能选base64.
如果想zlib后,再base64, 需要单独对输出结果进行base64(https://lostspeed.blog.csdn.net/article/details/136881319).
if (do_zlib)
base64 = 0;
压缩时无法带口令压缩
压缩时口令不起作用,因为可以不带口令解开。
openssl zlib -d -in test.txt.zlib -out test.txt.zlib.unzlib
如果想将压缩后的内容加密,需要自己单独对压缩后的内容加密。
实现 - 对buffer进行压缩和解压缩
测试效果
org:
0000 - 68 65 6c 6c 6f 20 6f 70-65 6e 73 73 6c 33 2e 32 hello openssl3.2
0010 - 20 7a 6c 69 62 0a zlib.
zip:
0000 - 78 9c cb 48 cd c9 c9 57-c8 2f 48 cd 2b 2e ce 31 x..H...W./H.+..1
0010 - d6 33 52 a8 ca c9 4c e2-02 00 5e 4e 07 a7 .3R...L...^N..
unzip:
0000 - 68 65 6c 6c 6f 20 6f 70-65 6e 73 73 6c 33 2e 32 hello openssl3.2
0010 - 20 7a 6c 69 62 0a zlib.
free mem_hook map, g_mem_hook_map.size() = 0, no openssl API call memory leak
工程实现
test prj is exp034_zlib
main.cpp
/*!
* \file main.cpp
*/
#include "ossl/my_openSSL_lib_v1.1.h"
#include <openssl/crypto.h>
#include <openssl/bio.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "COsslZlibBuffer.h"
void my_openssl_app();
int main(int argc, char** argv)
{
setvbuf(stdout, NULL, _IONBF, 0); // 清掉stdout缓存, 防止调用printf时阻塞
mem_hook();
my_openssl_app();
mem_unhook();
return 0;
}
void my_openssl_app()
{
bool b_rc = false;
int i_rc = 0;
COsslZlibBuffer zlib;
uint8_t szBuf[0x1000];
int lenBuf = 0;
uint8_t* pBufOut1 = NULL;
int lenBufOut1 = 0;
uint8_t* pBufOut2 = NULL;
int lenBufOut2 = 0;
strcpy((char*)szBuf, "hello openssl3.2 zlib\n");
lenBuf = strlen((char*)szBuf);
printf("org:\n");
BIO_dump_fp(stdout, szBuf, lenBuf);
b_rc = zlib.zip(szBuf, lenBuf, pBufOut1, lenBufOut1);
assert(b_rc);
printf("zip:\n");
BIO_dump_fp(stdout, pBufOut1, lenBufOut1);
b_rc = zlib.unzip(pBufOut1, lenBufOut1, pBufOut2, lenBufOut2);
assert(b_rc);
printf("unzip:\n");
BIO_dump_fp(stdout, pBufOut2, lenBufOut2);
assert(lenBufOut2 == lenBuf);
i_rc = memcmp(szBuf, pBufOut2, lenBuf);
assert(0 == i_rc);
if (NULL != pBufOut1)
{
OPENSSL_free(pBufOut1);
pBufOut1 = NULL;
}
if (NULL != pBufOut2)
{
OPENSSL_free(pBufOut2);
pBufOut2 = NULL;
}
}
COsslZlibBuffer.h
//! \file COsslZlibBuffer.h
#ifndef __C_OSSL_ZLIB_BUFFER_H__
#define __C_OSSL_ZLIB_BUFFER_H__
#include <stdlib.h>
#include <stdio.h>
#include <cstdint> // for uint8_t
#ifndef IN
#define IN
#endif // !IN
#ifndef OUT
#define OUT
#endif // !OUT
#include "openssl/bio.h"
class COsslZlibBuffer
{
public:
COsslZlibBuffer();
virtual ~COsslZlibBuffer();
// 出参指针调用者负责释放(OPENSSL_free())
bool zip(IN uint8_t* pBuf, IN int lenBuf, OUT uint8_t*& pBufOut, OUT int& lenBufOut);
bool unzip(IN uint8_t* pBuf, IN int lenBuf, OUT uint8_t*& pBufOut, OUT int& lenBufOut);
private:
bool zipOpt(bool isZip, IN uint8_t* pBuf, IN int lenBuf, OUT uint8_t*& pBufOut, OUT int& lenBufOut);
size_t bio_get_length(BIO* bio);
bool bio_to_buf(BIO* bio, uint8_t*& pBuf, int& lenBuf);
};
#endif // #ifndef __C_OSSL_ZLIB_BUFFER_H__
COsslZlibBuffer.cpp
//! \file COsslZlibBuffer.cpp
#include "COsslZlibBuffer.h"
#include "openssl/bio.h"
#include "openssl/comp.h"
COsslZlibBuffer::COsslZlibBuffer()
{
}
COsslZlibBuffer::~COsslZlibBuffer()
{
}
bool COsslZlibBuffer::zip(IN uint8_t* pBuf, IN int lenBuf, OUT uint8_t*& pBufOut, OUT int& lenBufOut)
{
return zipOpt(true, pBuf, lenBuf, pBufOut, lenBufOut);
}
bool COsslZlibBuffer::unzip(IN uint8_t* pBuf, IN int lenBuf, OUT uint8_t*& pBufOut, OUT int& lenBufOut)
{
return zipOpt(false, pBuf, lenBuf, pBufOut, lenBufOut);
}
bool COsslZlibBuffer::zipOpt(bool isZip, IN uint8_t* pBuf, IN int lenBuf, OUT uint8_t*& pBufOut, OUT int& lenBufOut)
{
bool b_rc = false;
BIO* bio_zip = NULL;
BIO* bio_in = NULL;
BIO* bio_out = NULL;
BIO* bio_read = NULL;
BIO* bio_write = NULL;
uint8_t szBuf[0x1000];
int iCntRead = 0;
int iCntWasWrite = 0;
do {
if ((NULL == pBuf) || (lenBuf <= 0))
{
break;
}
lenBufOut = 0;
bio_zip = BIO_new(BIO_f_zlib());
if (NULL == bio_zip)
{
break;
}
bio_in = BIO_new_mem_buf(pBuf, lenBuf);
if (NULL == bio_in)
{
break;
}
bio_out = BIO_new(BIO_s_mem());
if (NULL == bio_out)
{
break;
}
if (isZip)
{
bio_read = bio_in;
bio_write = BIO_push(bio_zip, bio_out); // write to bio link header, out form bio link tail
}
else {
bio_read = BIO_push(bio_zip, bio_in);
bio_write = bio_out;
}
do {
iCntRead = BIO_read(bio_read, szBuf, (int)sizeof(szBuf));
if (iCntRead <= 0)
{
break;
}
iCntWasWrite = BIO_write(bio_write, szBuf, iCntRead);
if (iCntWasWrite != iCntRead)
{
goto END;
}
} while (true);
if (!BIO_flush(bio_write))
{
break;
}
// 如果读bio_write, 得到的是写入的数据, 而不是处理完的输出数据
if (!bio_to_buf(bio_out, pBufOut, lenBufOut))
{
break;
}
/*
do_zlib = 1;
enc = 1;
saltlen = PKCS5_SALT_LEN;
dgst = (EVP_MD *)EVP_sha256();
iter = 1;
if (do_zlib)
base64 = 0;
BIO *bzl = NULL;
bzl = BIO_new(BIO_f_zlib()
wbio = BIO_push(bzl, wbio);
while (BIO_pending(rbio) || !BIO_eof(rbio)) {
inl = BIO_read(rbio, (char *)buff, bsize);
if (inl <= 0)
break;
if (!streamable && !BIO_eof(rbio)) {
// BIO_printf(bio_err, "Unstreamable cipher mode\n");
// goto end;
//}
//if (BIO_write(wbio, (char*)buff, inl) != inl) {
// BIO_printf(bio_err, "error writing output file\n");
// goto end;
//}
//if (!streamable)
//break;
// }
BIO_flush(wbio)
if (enc)
wbio = BIO_push(bzl, wbio);
else
rbio = BIO_push(bzl, rbio);
*/
b_rc = true;
} while (false);
END:
if (NULL != bio_read)
{
BIO_free_all(bio_read);
bio_read = NULL;
}
if (NULL != bio_write)
{
BIO_free_all(bio_write);
bio_write = NULL;
}
return b_rc;
}
size_t COsslZlibBuffer::bio_get_length(BIO* bio)
{
size_t bio_length = 0;
do {
if (NULL == bio)
{
break;
}
// BIO_seek(bio, 0);
bio_length = BIO_ctrl_pending(bio);
} while (false);
return bio_length;
}
bool COsslZlibBuffer::bio_to_buf(BIO* bio, uint8_t*& pBuf, int& lenBuf)
{
bool b_rc = false;
int i_rc = 0;
do {
if (NULL == bio)
{
break;
}
lenBuf = (int)bio_get_length(bio);
pBuf = (uint8_t*)OPENSSL_malloc(lenBuf + 1);
if (NULL == pBuf)
{
break;
}
pBuf[lenBuf] = '\0';
i_rc = BIO_read(bio, pBuf, lenBuf);
BIO_seek(bio, 0); // ! 读完了, 将数据读指针恢复.
b_rc = (i_rc == lenBuf);
} while (false);
return b_rc;
}
总结
用openssl做zip操作比直接用zlib库操作方便多了。
openssl的封装真优秀。