OpenSSL 中的 EVP_MD 学习笔记(针对1.1.1版本)

EVP_MD_CTX 和 EVP_MD 的定义

在 OpenSSL 1.1.1 源码 \crypto\evp\evp_locl.h 中定义了结构体 evp_md_ctx_st, 如下:

struct evp_md_ctx_st {
    const EVP_MD *digest;
    ENGINE *engine;
    unsigned long flags;
    void *md_data;
    EVP_PKEY_CTX *pctx;
    int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
} /* EVP_MD_CTX */ ;

在 OpenSSL 1.1.1 源码 \crypto\include\internal\evp_int.h 中定义了结构体 evp_md_st,如下:

struct evp_md_st {
    int type;
    int pkey_type;
    int md_size;
    unsigned long flags;
    int (*init) (EVP_MD_CTX *ctx);
    int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
    int (*final) (EVP_MD_CTX *ctx, unsigned char *md);
    int (*copy) (EVP_MD_CTX *to, const EVP_MD_CTX *from);
    int (*cleanup) (EVP_MD_CTX *ctx);
    int block_size;
    int ctx_size;
    int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
} /* EVP_MD */ ;

在 \include\openssl\ossl_typ.h 中定义了以下宏:

typedef struct evp_md_st EVP_MD;

typedef struct evp_md_ctx_st EVP_MD_CTX;

和计算摘要有关的部分函数

EVP_MD_CTX *EVP_MD_CTX_new(void);

动态分配一个摘要上下文(digest context)所需的内存空间,并返回指向这个摘要上下文的指针。

void EVP_MD_CTX_free(EVP_MD_CTX *ctx);

清理参数 ctx 指向的摘要上下文内存空间,然后释放这一段内存。

int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);

重置参数 ctx 指向的摘要上下文,用户可以使用本函数来重用一个已经创建的摘要上下文,而不是再创建一个新的摘要上下文。

int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);

使用摘要类型参数 type、引擎参数 impl 初始化摘要上下文参数 ctx 。参数 type 的值可以是以下函数的返回值:EVP_sha256( ), EVP_sha384( ),EVP_sha512( ),EVP_sm3( )等。当参数 impl 的值为 NULL 时,使用默认的引擎计算摘要值。

int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);

与 EVP_DigestInit_ex( ) 类似,但总是使用默认的引擎计算摘要值。 

int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);

针对参数 d 指向的输入缓冲区中长度为 cnt 字节的数据计算摘要值。当原始数据长度较长、难以被一次性的读入内存缓冲区时,可以将数据分批读入缓冲区,反复调用该函数来计算摘要值,在这种情况下,每次调用该函数时参数 ctx 的值必须相同。

int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);

从参数 ctx 中获取摘要值,放入参数 md 指向的缓冲区。如果参数 s 的值不是空指针,将摘要的长度赋值给指针 s 指向的整型变量。对于标准的摘要算法,其杂凑值长度是固定的,用户能够提前知道摘要值长度,不需要通过调用 EVP_DigestFinal_ex( ) 获取杂凑值长度,此时可以将变量 s 的值直接赋为 NULL,但是一定要保证用来存放摘要值的缓冲区长度足够容纳。调用 EVP_DigestFinal_ex( ) 函数将终结摘要计算过程,在此之后不能再调用 EVP_DigestUpdate( ) 函数。

EVP_DigestFinal_ex( ) 函数的实现在 \crypto\evp\digest.c 中,内部包含以下语句: 

if (size != NULL)
   *size = ctx->digest->md_size;
int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);

与 EVP_DigestFinal_ex( ) 类似,并且该函数会重置 ctx 指向的摘要上下文。

该函数的实现在 \crypto\evp\digest.c 中,如下:

int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
{
    int ret;
    ret = EVP_DigestFinal_ex(ctx, md, size);
    EVP_MD_CTX_reset(ctx);
    return ret;
}
int EVP_MD_type(const EVP_MD *md);

当输入参数是一个 EVP_MD 结构体时,返回该摘要算法对象识别符对应的 NID。例如

EVP_MD_type(EVP_sha1()) 的返回值是 NID_sha1 。

如果根据输入的 EVP_MD 找不到对应的摘要算法,将返回 NID_undef 。

注意:

NID_sha1,NID_undef 都是在 \include\openssl\obj_mac.h 中定义的宏,常见的一些 NID 定义如下:

#define NID_undef                      0
#define NID_sha1                       64
#define NID_sha256                     672
#define NID_sha256WithRSAEncryption    668
#define NID_sm3                        1143
const EVP_MD *EVP_get_digestbynid(int type);

当输入值是一个摘要 NID 时,例如 NID_sha1,返回一个 EVP_MD 结构体。如果根据摘要 NID 找不到对应的摘要算法,将返回 NULL。

注意:

从 OpenSSL 1.1.0 版开始,以前版本中的 EVP_MD_CTX_create( ) 被重命名为 EVP_MD_CTX_new,EVP_MD_CTX_init( ) 被重命名为 EVP_MD_CTX_reset( ),EVP_MD_CTX_destroy( ) 被重命名为 EVP_MD_CTX_free( )。
在 OpenSSL 1.1.1 版的 \include\openssl\evp.h 文件中,可以看到以下宏定义: 

# define EVP_MD_CTX_create()     EVP_MD_CTX_new()
# define EVP_MD_CTX_init(ctx)    EVP_MD_CTX_reset((ctx))
# define EVP_MD_CTX_destroy(ctx) EVP_MD_CTX_free((ctx))

转载:OpenSSL 中的 EVP_MD 学习笔记(针对1.1.1版本)_henter的博客-CSDN博客_evp_md_st

(SAW:Game Over!) 

 

 

 

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值