HMAC消息认证码
 
- 哈希运算消息码(Hash-based Message Authentication Code)
- 与密钥相关的单向散列函数
- 应用在SSL协议中
- 消息是否被正确传输
- 消息完整性
- 消息认证
算法流程
 

 
- 密钥填充0(填充到与散列函数分组长度一致)
- 填充后的密钥与0X36做异或ipad
- 与消息内容组合
- 第一次与单向散列函数进行散列计算
- 填充后密钥与0x5c做异或运算的到opad.
- 得到的opad与第一次散列结果做组合
- 再做一次散列, 得到最后的MAC值。
- 整体过程中密钥有点类似于SALT
HMAC 安全问题
 
 
- 使用时间戳, nonce随机数解决
- 无第3方证明,密码发送问题
- 防止否认
模拟HMAC消息
 
模拟消息发送端生成消息
 
string GetHMAC1() 
{
   unsigned char data[1024] = "HMAC1";
   int data_size = strlen((char*)data);
   //生成MAC存储空间
   unsigned char mac[1024] = { 0 };
   unsigned int mac_size = 0;
   char key[1024] = "123456";
   HMAC(EVP_sha256(), //设置HASH算法
   	key, //共享密钥
   	strlen(key), //密钥长度
   	data,
   	data_size,
   	mac, //返回的消息MAC
   	&mac_size //返回消息MAC长度
   );
   //生成消息,模拟发送消息体
   string msg(mac, mac + mac_size);    //1 . 消息的HMAC
   msg.append(data, data+data_size);  // 2. 消息内容
   return msg;
}
 
模拟消息接收端验证消息
 
void TestHMAC(string msg1) 
{
   //string msg1 = GetHMAC1();
   const char* data = msg1.data() + 32; // SHA-256就是32个字节
   int data_size = msg1.size() - 32; //去掉头部
   string hmac(msg1.begin(), msg1.begin() + 32); //拿到发送端生成的hmac
   unsigned char out[1024];
   unsigned int out_size = 0;
   //验证消息完整和验证
   char key[1024] = "123456";
   HMAC(EVP_sha256(),
   	key,
   	strlen(key),
   	(unsigned char*)data, //输入的数据
   	data_size,
   	out, 
   	&out_size
   );
   // 验证生成的HMAC
   string my_hmac(out, out + out_size);
   if (hmac == my_hmac) 
   {
   	cout << "消息HMAC校验成功, no change!" << endl;
   }
   else 
   {
   	cout << "消息HMAC校验失败, message change!" << endl;
   }
}
 
测试
 
int main(int argc, char* argv[])
{
   // 测试HMAC
   string msg1 = GetHMAC1();
   TestHMAC(msg1);
   return 0;
}
 
