文章目录
-
- [openssl3.2 - exp - class warp for sha3-512](#openssl3.2 - exp - class warp for sha3-512)
- 概述
- 笔记
- 调用方代码
- [子类 - cipher_sha3_512.h](#子类 - cipher_sha3_512.h)
- [子类 - cipher_sha3_512.cpp](#子类 - cipher_sha3_512.cpp)
- [基类 - cipher_md_base.h](#基类 - cipher_md_base.h)
- [基类 - cipher_md_base.cpp](#基类 - cipher_md_base.cpp)
- 备注
- END
openssl3.2 - exp - class warp for sha3-512
概述
前面实验整了一个对buffer进行sha3-512算hash的函数。
实际用的时候,要对几个buffer连续做hash. 前面封装的统一做hash的函数不适用。
重新封装了一个类,只要在类的生命周期中,就可以随时对连续的buffer(可能不在一个函数中)做hash的update.
笔记
调用方代码
c
bool CPeFileCheck::calc_hash_SHA3_512()
{
bool b_rc = false;
CCipherSha3_512 hash;
do {
if (!hash.begin())
{
break;
}
// 如果buffer不在一个函数中,将hash的指针传给那些函数做hash.update
if (!hash.update(this->m_pu8_map_file, this->m_u32_file_size))
{
break;
}
if (!hash.end())
{
break;
}
m_digest_length = hash.get_md_len();
if (m_digest_length > sizeof(m_ary_digest_value))
{
break;
}
memcpy(m_ary_digest_value, hash.get_md(), hash.get_md_len());
b_rc = true;
} while (false);
return b_rc;
}
子类 - cipher_sha3_512.h
c
//! \file cipher_sha3_512.h
#ifndef __CIPHER_SHA3_512_H__
#define __CIPHER_SHA3_512_H__
#include "cipher_md_base.h"
class CCipherSha3_512 : public CCipherMdBase
{
public:
CCipherSha3_512();
virtual ~CCipherSha3_512();
};
#endif // #ifndef __CIPHER_SHA3_512_H__
子类 - cipher_sha3_512.cpp
c
//! \file cipher_sha3_512.cpp
#include "pch.h"
#include "cipher_sha3_512.h"
CCipherSha3_512::CCipherSha3_512()
{
setCiphherName("SHA3-512");
}
CCipherSha3_512::~CCipherSha3_512()
{
}
基类 - cipher_md_base.h
c
//! \file cipher_md_base.h
#ifndef __CIPHER_MD_BASE_H__
#define __CIPHER_MD_BASE_H__
#include <openssl/evp.h>
#include <string>
//! \ref https://blog.csdn.net/LostSpeed/article/details/135581192
class CCipherMdBase
{
public:
CCipherMdBase();
virtual ~CCipherMdBase();
bool begin();
bool update(uint8_t* pBuf, int lenBuf);
bool end();
unsigned int get_md_len() { return m_digest_length; }
uint8_t* get_md() { return m_p_digest_value; }
void setCiphherName(const char* pszNmae) { m_strCipherName = ((NULL != pszNmae) ? pszNmae : ""); }
private:
void clear();
private:
std::string m_strCipherName;
OSSL_LIB_CTX* m_ossl_lib_ctx;
EVP_MD* m_evp_md;
EVP_MD_CTX* m_evp_md_ctx;
unsigned int m_digest_length;
uint8_t* m_p_digest_value;
};
#endif // #ifndef __CIPHER_MD_BASE_H__
基类 - cipher_md_base.cpp
c
//! \file cipher_md_base.cpp
#include "pch.h"
#include "cipher_md_base.h"
CCipherMdBase::CCipherMdBase()
: m_ossl_lib_ctx(NULL),
m_evp_md(NULL),
m_evp_md_ctx(NULL),
m_digest_length(0),
m_p_digest_value(NULL)
{
}
CCipherMdBase::~CCipherMdBase()
{
clear();
}
void CCipherMdBase::clear()
{
if (NULL != m_evp_md_ctx)
{
EVP_MD_CTX_free(m_evp_md_ctx);
m_evp_md_ctx = NULL;
}
m_digest_length = 0;
if (NULL != m_p_digest_value)
{
OPENSSL_free(m_p_digest_value);
m_p_digest_value = NULL;
}
if (NULL != m_evp_md)
{
EVP_MD_free(m_evp_md);
m_evp_md = NULL;
}
if (NULL != m_ossl_lib_ctx)
{
OSSL_LIB_CTX_free(m_ossl_lib_ctx);
m_ossl_lib_ctx = NULL;
}
}
bool CCipherMdBase::begin()
{
bool b_rc = false;
const char* _psz_option_properties = NULL;
do {
clear();
m_ossl_lib_ctx = OSSL_LIB_CTX_new();
if (NULL == m_ossl_lib_ctx) {
// fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
break;
}
/*
* Fetch a message digest by name
* The algorithm name is case insensitive.
* See providers(7) for details about algorithm fetching
*/
if (m_strCipherName.empty())
{
break;
}
m_evp_md = EVP_MD_fetch(m_ossl_lib_ctx, m_strCipherName.data(), _psz_option_properties);
if (NULL == m_evp_md) {
// fprintf(stderr, "EVP_MD_fetch could not find SHA3-512.");
break;
}
/*
* Make a message digest context to hold temporary state
* during digest creation
*/
m_evp_md_ctx = EVP_MD_CTX_new();
if (NULL == m_evp_md_ctx) {
// fprintf(stderr, "EVP_MD_CTX_new failed.\n");
break;
}
/*
* Initialize the message digest context to use the fetched
* digest provider
*/
if (EVP_DigestInit(m_evp_md_ctx, m_evp_md) != 1) {
// fprintf(stderr, "EVP_DigestInit failed.\n");
break;
}
b_rc = true;
} while (false);
return b_rc;
}
bool CCipherMdBase::update(uint8_t* pBuf, int lenBuf)
{
bool b_rc = false;
do {
if (EVP_DigestUpdate(m_evp_md_ctx, pBuf, lenBuf) != 1) {
// fprintf(stderr, "EVP_DigestUpdate(hamlet_1) failed.\n");
break;
}
b_rc = true;
} while (false);
return b_rc;
}
bool CCipherMdBase::end()
{
bool b_rc = false;
int digest_length = 0;
do {
/* Determine the length of the fetched digest type */
m_digest_length = EVP_MD_get_size(m_evp_md);
if (m_digest_length <= 0) {
// fprintf(stderr, "EVP_MD_get_size returned invalid size.\n");
break;
}
m_p_digest_value = (uint8_t*)OPENSSL_malloc(m_digest_length);
if (NULL == m_p_digest_value) {
// fprintf(stderr, "No memory.\n");
break;
}
if (EVP_DigestFinal(m_evp_md_ctx, m_p_digest_value, &m_digest_length) != 1) {
// fprintf(stderr, "EVP_DigestFinal() failed.\n");
break;
}
b_rc = true;
} while (false);
return b_rc;
}
备注
这个封装类用的很舒服。
如果要做其他种类的hash, 只需要继承一个子类,给定新的hash算法名称就行。