[TOC] # 消息认证码 ![](https://box.kancloud.cn/09ac625acdabe44c3cab78eb2a86586b_605x518.png) ## go消息认证码的使用 > 有一个包: crypto/hmac ~~~ > func New(h func() hash.Hash, key []byte) hash.Hash > - 返回值: hash接口 > - 参数1: 函数函数的函数名 > sha1.new > md5.new > sha256.new > - 参数2: 秘钥 > > 第二步: 添加数据 > type Hash interface { > // 通过嵌入的匿名io.Writer接口的Write方法向hash中添加更多数据,永远不返回错误 > io.Writer > // 返回添加b到当前的hash值后的新切片,不会改变底层的hash状态 > Sum(b []byte) []byte > // 重设hash为无数据输入的状态 > Reset() > // 返回Sum会返回的切片的长度 > Size() int > // 返回hash底层的块大小;Write方法可以接受任何大小的数据, > // 但提供的数据是块大小的倍数时效率更高 > BlockSize() int > } > type Writer interface { > Write(p []byte) (n int, err error) > } > 第三步: 计算散列值 ~~~ ## 使用步骤 ![](https://box.kancloud.cn/5f500ca1ab2ff0febcf39590b803828c_772x474.png) > 1. 前提条件: > - 在消息认证码生成的一方和校验的一方, 必须有一个秘钥 > - 双方约定好使用同样的哈希函数对数据进行运算 > 2. 流程: > - 发送者: > - 发送原始法消息 > - 将原始消息生成消息认证码 > - ((原始消息) + 秘钥) * 函数函数 = 散列值(消息认证码) > - 将消息认证码发送给对方 > - 接收者: > - 接收原始数据 > - 接收消息认证码 > - 校验: > - ( 接收的消息 + 秘钥 ) * 哈希函数 = 新的散列值 > - 通过新的散列值和接收的散列值进行比较 ~~~ // 生成消息认证码 func GenerateHamc(plainText, key []byte)[]byte { // 1.创建哈希接口, 需要指定使用的哈希算法, 和秘钥 myhash := hmac.New(sha1.New, key) // 2. 给哈希对象添加数据 myhash.Write(plainText) // 3. 计算散列值 hashText := myhash.Sum(nil) return hashText } // 验证消息认证码 func VerifyHamc(plainText, key, hashText []byte) bool { // 1.创建哈希接口, 需要指定使用的哈希算法, 和秘钥 myhash := hmac.New(sha1.New, key) // 2. 给哈希对象添加数据 myhash.Write(plainText) // 3. 计算散列值 hamc1 := myhash.Sum(nil) // 4. 两个散列值比较 return hmac.Equal(hashText, hamc1) } func main () { src := []byte("在消息认证码中,需要发送者和接收者之间共享密钥,而这个密钥不能被主动攻击者Mallory获取。" + "如果这个密钥落入Mallory手中,则Mallory也可以计算出MAC值,从而就能够自由地进行篡改和伪装攻击," + "这样一来消息认证码就无法发挥作用了。") key := []byte("helloworld") hamc1 := GenerateHamc(src, key) bl := VerifyHamc(src, key, hamc1) //fmt.Printf("校验结果: %t\n", bl) fmt.Println(bl) } ~~~ ## 消息认证码的问题 1. 弊端 - 有秘钥分发困难的问题 2. 无法解决的问题 - 不能进行第三方证明 - 不能防止否认