HMAC消息认证码
- 哈希运算消息码(Hash-based Message Authentication Code)
- 与密钥相关的单向散列函数
- 应用在SSL协议中
- 消息是否被正确传输
- 消息完整性
- 消息认证
算法流程
文章来源:https://uudwc.com/A/8d13v
- 密钥填充
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;
}
文章来源地址https://uudwc.com/A/8d13v