1、HMAC简介

1 MAC(Message Authentication Code, 消息认证码算法 ) ,可以将其认为是含有秘钥的散列 (Hash) 函数算法 ; 即兼容了 MD SHA 算法,并在此基础上加上了秘钥。因此 MAC 算法也经常被称作 HMAC 算法。当然 HMAC 就是“基于Hash的消息认证码”英文 (Hash-based Message Authentication Code) 的缩写。我个人理解它主要包括两块:一个是信息摘要算法 (MD/SHA ) ;另外就是秘钥。

1 HMAC 基于的信息摘要算法。 目前主要集合了MD和SHA两大系列消息摘要算法。其中MD系列的算法有HmacMD2、HmacMD4、HmacMD5三种算法;SHA系列的算法有HmacSHA1、HmacSHA224、HmacSHA256、HmacSHA384、HmacSHA512五种算法。

2 )秘钥。理论上 密钥可以是任何长度 ,但是一般出于安全强度的考量不建议使用太短的秘钥。也就是说一般情况下要 使用摘要算法计算密钥的摘要作为新的密钥。

2 )使用流程。 你和对方共享了一个密钥K,你要发消息给对方 ;这个过程即要保证 消息没有被篡改 还要能够 证明信息确实是你本人 发送的。所以处理的方式是: 在发送数据以前,HMAC算法对 数据块 + 约定的公钥 进行散列操作 并将所 生成 摘要”附加在待发送的数据块中。当 数据 和摘要到达其目的地时, 目的端也会使用 HMAC 算法 对原数据块和公钥 来生成 本地摘要 ,如果两个 摘要 相匹配,那么 就认为 数据未被做任何篡改 且消息为约定的对方本人发送

(3)加深理解。

1)其实通过MD5、SHA1等哈希算法我们可以验证一段数据是否有效,方法就是对比该数据的哈希值。例如判断用户的口令(密码)是否正确我们用保存在数据库中的password_md5对比计算得到的md5(password),如果一致就认为用户输入的密码是正确的。

2)由于用户密码通常会设置的比较简单而且具有普遍性,如果黑客做了足够大的对照表实际上就很有可能反推出真实密码。为了防止黑客通过对照表反推到原始密码,通常在计算哈希的时候会增加一个salt以使得相同的输入(这里指不同用户的相同密码)也能达到不同的哈希(例如将每个用户的唯一id作为salt的一部分),这样就大大的增加了破解难度。

3)实际上我们可以把上面说的salt看做是一个“口令”,所以加salt的哈希就是:计算一段message的哈希时,根据不同的口令计算出不同的哈希。即,要验证哈希值必须同时提供口令。上面的这个思路实际上就是Hmac算法了,它通过一个标准算法,在计算哈希的过程中把key混入计算过程。和我们自定义的加salt算法不同,Hmac算法针对所有的哈希算法都通用,无论是MD5还是SHA-1。其实 可以认为Hmac算法和我们自定义的加salt的哈希算法本质上就是一个东西 。但是 使用Hmac替代我们自己的salt算法可以使程序算法更标准话,也更安全

2、实例程序(打包代码 这里 )

(1)algo_hmac.h

#ifndef _ALGO_HMAC_H_
#define _ALGO_HMAC_H_
int HmacEncode(const char * algo,
	const char * key, unsigned int key_length,
	const char * input, unsigned int input_length,
	unsigned char * &output, unsigned int &output_length);
#endif

(2)algo_hmac.cpp

#include "algo_hmac.h"
#include <openssl/hmac.h>
#include <string.h>
#include <iostream>
using namespace std;
int HmacEncode(const char * algo, 
		const char * key, unsigned int key_length, 
		const char * input, unsigned int input_length, 
		unsigned char * &output, unsigned int &output_length) {
	const EVP_MD * engine = NULL;
	if(strcasecmp("sha512", algo) == 0) {
		engine = EVP_sha512();
	else if(strcasecmp("sha256", algo) == 0) {
		engine = EVP_sha256();
	else if(strcasecmp("sha1", algo) == 0) {
		engine = EVP_sha1();
	else if(strcasecmp("md5", algo) == 0) {
		engine = EVP_md5();
	else if(strcasecmp("sha224", algo) == 0) {
		engine = EVP_sha224();
	else if(strcasecmp("sha384", algo) == 0) {
		engine = EVP_sha384();
	else if(strcasecmp("sha", algo) == 0) {
		engine = EVP_sha();
	else if(strcasecmp("md2", algo) == 0) {
		engine = EVP_md2();
	else {
		cout << "Algorithm " << algo << " is not supported by this program!" << endl;
		return -1;
	output = (unsigned char*)malloc(EVP_MAX_MD_SIZE);
	/*---------------------------------
	这块应该是相对通用的计算流程了
	--------------------------------*/
	HMAC_CTX ctx;
	HMAC_CTX_init(&ctx);
	HMAC_Init_ex(&ctx, key, strlen(key), engine, NULL);
	HMAC_Update(&ctx, (unsigned char*)input, strlen(input));	// input is OK; &input is WRONG !!!
	HMAC_Final(&ctx, output, &output_length);
	HMAC_CTX_cleanup(&ctx);	
	return 0;

(3)main.cpp

#include "algo_hmac.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main(int argc, char * argv[])
	if(argc < 2) {
		//参数指定hash算法,支持HmacEncode列举的那些
		cout << "Please specify a hash algorithm!" << endl;
		return -1;
	char key[] = "fasdkgjl;asdfjg;dsfjgasdsr";//secret key
	string data = "/pic/small/3007024147/8ba5a744-f48d-4ba2-b93f-da17e7f52dff";//要加密传输的数据
	unsigned char * mac = NULL;
	unsigned int mac_length = 0;
	int ret = HmacEncode(argv[1], key, strlen(key), data.c_str(), data.length(), mac, mac_length);	
	if(0 == ret) {
		cout << "Algorithm HMAC encode succeeded!" << endl;
	else {
		cout << "Algorithm HMAC encode failed!" << endl;
		return -1;
	cout << "mac length: " << mac_length << endl;
	cout << "mac:";
	for(int i = 0; i < mac_length; i++) {
		printf("%-03x", (unsigned int)mac[i]);
	cout << endl;
	if(mac) {
		free(mac);
		cout << "mac is freed!" << endl;
	return 0;

(4)Makefile

LNK_OPT = -g -L/usr/lib64/ -lssl  -L/lib64/ -lcrypto
	rm -f *.o
	rm -f test
	g++ -g -c algo_hmac.cpp
	g++ -g main.cpp -o test algo_hmac.o $(LNK_OPT)
clean:
	rm -f *.o
	rm -f test

3、执行效果

执行效果如下:

各种算法得到的摘要长度如下:

算法摘要长度(字节)
MD216
MD516
SHA20
SHA120
SHA22428
SHA25632
SHA38448
SHA51264

主要涉及如下函数:

HMAC, HMAC_CTX_init, HMAC_Init, HMAC_Init_ex, HMAC_Update, HMAC_Final, HMAC_CTX_cleanup, HMAC_cleanup - HMAC message authentication code

注:其中 HMAC_CTX_cleanup 作用如下。如果结尾处不调用此函数的话会导致内存泄漏。

HMAC_CTX_cleanup() erases the key and other data from the HMAC_CTX and releases any associated resources. It must be called when an HMAC_CTX is no longer required.

关于遗漏 HMAC_CTX_cleanup 引发的内存泄漏的实际测试可以参照这篇文章。

https://blog.csdn.net/mijichui2153/article/details/126412532?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22126412532%22%2C%22source%22%3A%22mijichui2153%22%7D

1、HMAC简介(1)MAC(Message Authentication Code,消息认证码算法),可以将其认为是含有秘钥的散列(Hash)函数算法;即兼容了MD和SHA算法,并在此基础上加上了秘钥。因此MAC算法也经常被称作HMAC算法。当然HMAC就是“基于Hash的消息认证码”英文(Hash-based Message Authentication Code)的缩写。我个人理解它主要...... HMAC 全称(Hash-based Message Authentication Code,即基于Hash的消息的认证码)。 - 基本过程为对某个消息,利用提前共享的对称密钥和Hash算法进行加密处理,得到HMAC值。 - 该HMAC值提供方可以证明自己拥有共享密钥的对称密钥,并且消息自身可以利用HMAC确保未经篡改。 二、为什么不直接使用哈希值来进行校验 每个数据哈希值唯一,数据被伪造篡改后,哈希值改变。 例如: xxxxx?name=hahah&hash=547779D1FBA9B6
[ 66%] Building CXX object proxy_ws/CMakeFiles/proxy_lws.dir/proxy_lws.cpp.o In file included from /vagrant/include/libwebsockets.h:600, from /vagrant/proxy_ws/proxy_lws_utils.hpp:12, from /vagrant/proxy_ws/proxy_lws.cpp:1
HMAC_CTX hctx; HMAC_CTX_init(&hctx); HMAC_Init_ex(&hctx, mac_key, sizeof(mac_key), EVP_sha1(), NULL); HMAC_Update(&hctx, pTemp + offset, DEFAULT_PAGESIZE - reserve - offset + IV_SIZE); HMAC_Update(&hctx, (const unsigned char)& nPage, sizeof(n
为了降低第三方应用集成华为云会议难度,并且提升开放接口的安全性,华为云会议开放能力中支持基于App ID的鉴权方式。App ID是一个应用的标识,同一个App ID可以同时在第三方的桌面终端、移动终端、Web应用上使用。 App ID鉴权原理 图1 第三方客户端App ID鉴权流程 鉴权前提: 开发者在华为云会议控制台上为自己的应用申请AppID,并获取App ID和App Key。 开发者在自己的服务端集成Signature生成算法,请参考“第三方服务集成Signature生成算法”。 SDK初始化时传
索引摘要算法(Digest)获取EVP_MDDigest API例子对称加密(Cipher)获取EVP_CIPHERCipher API上下文管理Encrypt APIDecrypt API加解密统一API其他设置例子非对称加密密钥管理公钥算法上下文 EVP_PKEY_CTX生成密钥密钥参数打印密钥的提取和指定密钥的保存和读取使用OSSL_ENCODER和OSSL_DECODER使用EVP_PKEY_todata和EVP_PKEY_fromdata检测私钥是否正确加解密签名和验签 摘要算法(Digest) #include "hmac/hmac.h" void hmac_sha1(const uint8_t *k, /* secret key */ size_t lk, /* length of the key in bytes */ const uint8_t *d, /* data */ size_t ld, /* length of data in bytes */ uint8_t *out, /* output buffer, at least "t" bytes */ size_t *t);
HMAC(Hash-based Message Authentication Code):基于Hash的消息认证码,是一种通过特别计算方式之后产生的消息认证码(MAC),使用密码散列函数,同时结合一个加密密钥。它可以用来保证数据的完整性,同时可以用来作某个消息的身份验证。HMAC运算利用哈希算法,以一个密钥和一个消息作为输入,生成一个消息摘要作为输出。 使用消息摘要算法MD2、MD4、MD5、SHA-1、SHA-224、SHA-256、SHA-384、SHA-512所构造的HMAC,分别称为HMAC-MD2
OpenSSL MD5算法是一种散列算法,它可以将任意长度的输入数据转换成一个128位的输出数据。它主要利用了MD5(Message-Digest Algorithm 5)算法来计算和生成消息摘要。它常被用于证明文件的完整性和真实性。OpenSSL MD5算法的实例如下: echo -n "example" | openssl md5 (stdin)= d3a1865f75b56d1b7f3b17c2f8ab6836