消息认证码(MAC)使用
消息认证码(message authentication code)是一种确认完整性并进行认证的技术,取三个单词的首字母,简称为MAC。
– 保证数据未被篡改
– 对发送者进行身份认证
1. 发送者Alice与接收者Bob事先共享密钥。
2. 发送者Alice根据汇款请求消息计算MAC值(使用共享密钥)。
3. 发送者Alice将汇款请求消息和MAC值两者发送给接收者Bob。
4. 接收者Bob根据接收到的汇款请求消息计算MAC值(使用共享密钥)。
5. 接收者Bob将自己计算的MAC值与从Alice处收到的MAC值进行对比。
6. 如果两个MAC值一致,则接收者Bob就可以断定汇款请求的确来自Alice(认证成功);如果不一致,则可以断定消息不是来自Alice(认证失败)。
MAC使用场景
## 1. SWIFT
环球银行金融电信协会,是一个组织,为银行间的交易报价护航。银行间交互使用了SWIFT进行交互,这里面对消息的完成性和身份验证,就是使用了消息认证码。
– 最初使用消息认证码,由人工配送秘钥
– 后来使用公钥
## 2. https
– ssl/tls协议,里面的握手协议使用了消息认证码
– https = http + ssl/tls(security socket layer)
## 3. IPSec
– IP协议的增强版,使用了消息认证码
HMAC
==H代表哈希==
HMAC是一种使用单向散列函数来构造消息认证码的方法(RFC2104),其中HMAC的H就是Hash的意思。
HMAC中所使用的单向散列函数并不仅限于一种,任何高强度的单向散列函数都可以被用于HMAC,如果将来设计出新的单向散列函数,也同样可以使用。
使用SHA-I、MD5、RIPEMD-160所构造的HMAC,分别称为HMAC-SHA-1、HMAC-MD5和HMAC-RlPEMD。
//接收端和验证端都要执行
//New函数返回一个采用hash.Hash作为底层hash接口、key作为密钥的HMAC算法的hash接口。
func New(h func() hash.Hash, key []byte) hash.Hash
– 参数1:自己指定哈希算法, 是一个函数
– md5.New
– sha1.New
– sha256.New
– 参数2:秘钥
– 返回值:哈希函数对象
//仅在验证端执行
//比较两个MAC是否相同,而不会泄露对比时间信息。(以规避时间侧信道攻击:指通过计算比较时花费的时间的长短来获取密码的信息,用于密码破解)
func Equal(mac1, mac2 []byte) bool
– 参数1:自己计算的哈希值
– 参数2:接收到的哈希值
– 返回值:对比结果
package main import ( "crypto/hmac" "crypto/sha256" "fmt" ) /* //接收端和验证端都要执行 //New函数返回一个采用hash.Hash作为底层hash接口、key作为密钥的HMAC算法的hash接口。 func New(h func() hash.Hash, key []byte) hash.Hash - 参数1:自己指定哈希算法, 是一个函数 - md5.New - sha1.New - sha256.New - 参数2:秘钥 - 返回值:哈希函数对象 //仅在验证端执行 //比较两个MAC是否相同,而不会泄露对比时间信息。(以规避时间侧信道攻击:指通过计算比较时花费的时间的长短来获取密码的信息,用于密码破解) func Equal(mac1, mac2 []byte) bool - 参数1:自己计算的哈希值 - 参数2:接收到的哈希值 - 返回值:对比结果 */ //生成hmac(消息认证码) func generateHMAC(src []byte, key []byte) []byte { //1. 创建哈希器 hasher := hmac.New(sha256.New, key) //2. 生成mac值 //mac := hasher.Sum(src) hasher.Write(src) mac := hasher.Sum(nil) return mac } //认证mac func verifyHMAC(src, key, mac1 []byte) bool { //1. 对端接收到的源数据 //2. 对端接收到的mac1 //3. 对端计算本地的mac2 mac2 := generateHMAC(src, key) //4. 对比mac1与mac2 return hmac.Equal(mac1, mac2) } func main() { src := []byte("hello world") key := []byte("1234567890") mac1 := generateHMAC(src, key) fmt.Printf("mac1 : %x\n", mac1) isEqual := verifyHMAC(src, key, mac1) fmt.Printf("isEqual : %v\n", isEqual) srcChanged := []byte("hello world!!!!!") isEqual = verifyHMAC(srcChanged, key, mac1) fmt.Printf("after changed, isEqual : %v\n", isEqual) }