5. 单向散列函数
"单向散列函数 --- 获取消息的指纹"
5.1 什么是单向散列函数
5.2 关于术语
5.3 单向散列函数的性质
根据任意长度的消息计算出固定长度的散列值
能够快速计算出散列值
消息不同散列值也不同
具备单向性
5.4 单向散列函数的实际应用
5.4.1 检测软件是否被篡改
5.4.2 消息认证码
5.4.3 数字签名
5.4.6 伪随机数生成器
5.4.7 一次性口令
5.5 常用的单向散列函数
5.5.1 MD4、MD5
5.5.2 Go中使用MD5
需要导入的包
import (
"crypto/md5"
"encoding/hex"
)
计算Md5的方式1
func getMD5_1(str []byte) string {
// 1. 计算数据的md5
result := md5.Sum(str)
fmt.Println(result)
fmt.Printf("%x\n", result)
// 2. 数据格式化为16进制格式字符串
res := fmt.Sprintf("%x", result)
fmt.Println(res)
// --- 这是另外一种格式化切片的方式
res = hex.EncodeToString(result[:])
fmt.Println("res: ", res)
return res
}
重要函数说明:
返回数据data的MD5校验和
函数所属的包: "crypto/md5"
func Sum(data []byte) [Size]byte
- 参数 data: 原始数据
- 返回值: 经过md5计算之后得到的数据, 长度为 16字节(byte)
将字符串编码为16进制格式
函数所属的包: "encoding/hex"
func EncodeToString(src []byte) string
- 参数 src: 要转换的数据
- 返回值: 转换之后得到的16进制格式字符串
计算Md5的方式2
func getMD5_2(str []byte) string {
// 1. 创建一个使用MD5校验的Hash对象`
myHash := md5.New()
// 2. 通过io操作将数据写入hash对象中
io.WriteString(myHash, "hello")
//io.WriteString(myHash, ", world")
myHash.Write([]byte(", world"))
// 3. 计算结果
result := myHash.Sum(nil)
fmt.Println(result)
// 4. 将结果转换为16进制格式字符串
res := fmt.Sprintf("%x", result)
fmt.Println(res)
// --- 这是另外一种格式化切片的方式
res = hex.EncodeToString(result)
fmt.Println(res) return res
}重要函数说明:
创建一个新的使用MD5校验的hash.Hash接口
函数所属的包: "crypto/md5"
func New() hash.Hash
Hash是一个被所有hash函数实现的公共接口。
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
} "io" 包中 Writer 接口用于包装基本的写入方法。
type Writer interface {
Write(p []byte) (n int, err error)
}
通过io操作将数据写入hash对象中
# 第一种方式
函数所属的包: "io"
func WriteString(w Writer, s string) (n int, err error)
- 参数 w: 实现了/包含Writer接口的对象
- 参数 s: 要添加到IO对象中的数据
- 返回值 n: 数据长度
- 返回值 err: 错误信息
# 第二种方式
使用md5包中的New()方法得到的hash.Hash接口(假设名为: myHash)添加数据
myHash.Write([]byte("测试数据"))
使用hash.Hash接口中的Sum方法计算结果
Sum(b []byte) []byte
- 参数 b: 将b中的数据进行哈希计算, 结果添加到原始数据的前面,
一般情况下该参数指定为空, 即: nil
- 返回值: 进行哈希运算之后得到的结果
5.5.3 SHA-1、SHA-224、SHA-256、SHA-384、SHA-512
MD4 | 128bit | 16byte |
MD5 | 128bit | 16byte |
SHA-1 | 160bit | 20byte |
SHA-224 | 224bit | 28byte |
SHA-256 | 256bit | 32byte |
SHA-384 | 384bit | 48byte |
SHA-512 | 512bit | 64byte |
5.5.4 Go中对SHA-1、SHA-2的使用
需要导入的包
import (
"crypto/sha1"
"encoding/hex"
"crypto/sha256"
"crypto/sha512"
)
使用sha1计算文件指纹
func getSha1(src string) string {
// 1. 打开文件
fp, err := os.Open(src)
if err != nil {
return "文件打开失败"
}
// 2. 创建基于sha1算法的Hash对象
myHash := sha1.New()
// 3. 将文件数据拷贝给哈希对象
num, err := io.Copy(myHash, fp)
if err != nil {
return "拷贝文件失败"
}
fmt.Println("文件大小: ", num)
// 4. 计算文件的哈希值
tmp1 := myHash.Sum(nil)
// 5. 数据格式转换
result := hex.EncodeToString(tmp1)
fmt.Println("sha1: ", result) return result
}