密码学04--go语言与单向散列函数

目录

1.单向散列函数One-way hash function

1.1 定义

1.2 术语

1.3 特性

1.3.1 散列值长度固定

1.3.2 散列值计算快速

1.3.3 散列值抗碰撞性极强

1.3.4 散列值计算是单向不可逆

1.4 应用

1.5 常见类型

2.go语言中使用单向散列函数

2.1 选择不同单向散列值函数包,直接执行包内对应的sum函数

2.2 创建Hash对象,通过Hash对象的writer指针扩充数据后执行Sum函数

1.单向散列函数One-way hash function

1.1 定义

单向散列函数,是能够把任意长的输入消息串变化成固定长的输出串,并且由输出串难以得到输入串的一种函数。(以上定义摘自百度百科)对于单向散列函数而言,无论原始数据多大,成的散列集合的大小是固定的,而且这个过程是“单向”的不可逆操作。

1.2 术语

  • 单向散列函数:也称消息摘要函数(message digest function)、哈希函数(hash function)、杂凑函数(hash function)
  • 单向散列函数的输入内容:也称消息(message)、原像(pre-image)
  • 单向散列函数的输出内容:也称散列值(hash value)、哈希值(hash value)、消息摘要(message digest)、指纹(fingerprint)
  • 单向散列函数的完整性:也称为单向散列函数的一致性(uniformity)

1.3 特性

1.3.1 散列值长度固定

根据任意长度的消息,可以算出固定长度的散列值。不管原像是1kB的数据还是10GB的数据,对于单向散列函数而言它们最终生成的散列值都是固定的。

1.3.2 散列值计算快速

能够快速的计算出散列值。尽管随着原像数据的增大计算散列值的时间必然会随之增大,但散列值的计算速度仍然非常快。

1.3.3 散列值抗碰撞性极强

消息不同的散列值截然不同(雪崩效应),因此散列值的抗碰撞性极强。由于不同消息想要生成两个完全相同的散列值的概率无限小(当然不同算法有不同的概率,比如时代烙印的MD4和MD5,当然还有SHA1已经被攻破?),因此想要通过生成的散列值逆向推测生成它们的原像非常之困难。

1.3.4 散列值计算是单向不可逆

散列值的计算不是加密,因为加密是可逆的。显然10GB的数据如果计算出16byte的散列值,还能够被还原回10GB,那全世界都会为这种算法沸腾。所以散列值的计算显然是单向的,指的就是原像能够计算出散列值,而散列值却无法还原回原像。

1.4 应用

  • 检测软件是否被篡改
  • 消息认证
  • 数字签名
  • 伪随机数生成器
  • 一次性口令(很多软件只有密码修改,没有密码找回)

1.5 常见类型

  • MD4 已被攻破,不安全
  • MD5 已被攻破,相对不安全 (诞生时间是1991年,产生的散列值长度是128bit)
  • SHA-1 已被攻破,相对不安全 (1995年正式发布版本,产生的散列值长度是160bit)
  • SHA-2 暂未被攻破,安全
  • SHA-3 暂未被攻破,安全

事实上MD5和SHA-1都是比较著名的、使用范围较广泛的单向散列函数,其中SHA-1是由NIST(National Institute Of Standardsand Technology,美国国家标准技术研究所)设计的一种能够产生160bit散列值的单向散列函数。1993年被作为美国联邦信息处理标准规格(FIPS PUB 180)发布的是SHA版本(ps:传说中生命贼短的SHA-0),在1995年发布的修订版中正式更名为FIPS PUB 180-1,也就是后来大名鼎鼎的SHA-1。

SHA-2单向散列函数是一个标准泛指,其中包括SHA-224、SHA-256、SHA-384、SHA-512四种不同标准。数字224、256、384、512指的都是单向散列函数执行后生成的散列值长度,就像SHA-1生成的是160bit散列值一样。很显然生成的散列值越长就越难以被攻破,所以SHA-2标准暂时是比较安全的。

2.go语言中使用单向散列函数

由于go语言是一个封装非常完备的“漂亮”语言,所以对于如何使用单向散列函数对数据进行散列值计算都已经封装到了不同的包中。因此在go语言中使用单向散列函数是一个非常简单的操作。通常情况下有两种方式使用单向散列函数。

2.1 选择不同单向散列值函数包,直接执行包内对应的sum函数

在go语言的crypto包中包括了常见的各种单向散列函数包。

import "crypto/md5"
import "crypto/sha1"
import "crypto/sha256"    //sha224和sha256共用
import "crypto/sha512"    //sha384和sha512共用

在这些包中,每一个包内部都能够看到一个封装好的Sum接口。

在需要计算散列值的数据量比较小的情况下,直接调用sum函数即可生成对应的散列值。

func main(){
	result1 := md5.Sum([]byte("helloworldd"))
	result2 := sha1.Sum([]byte("helloworldd"))
	fmt.Printf("%s\n",result1);
	fmt.Printf("%s\n",result2);
}

2.2 创建Hash对象,通过Hash对象的writer指针扩充数据后执行Sum函数

事实上这一种方式和第一种本质上也没什么区别,都是使用go语言提供的不同单向散列函数包中的sum函数来进行散列值计算。但不同的第一种方式由于Sum的参数是一个[]byte类型,因此内存空间有限的前提下无法直接将过大的数据直接进行传参操作,毕竟内存放不下;而第二种则是利用了系统提供的Hash对象中的io.Writer指针中的write方法对数据进行不断的“拼接”,最后一次性将所有拼接在一起的数据进行一次散列值计算。

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)
 }

在数据较大的情况下可以进行如下操作,来进行hashValue的计算。以SHA-2标准下的SHA-256为例,毕竟比特币的计算方式就是这种

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"os"
)
/*
	名称:frankGenerateSha256Hash
	参数:需要生成hash值的文件名
	结果:生成的hash值
    目的:生成256bit的hash值,即32byte长度
         但实际应当是64byte长度,因为16进制下两个字符描述一个字符。例如6E描述一个小写字母n
*/
func frankGenerateSha256Hash(fileName string) string{
	//1.将文件当中的内容读出存入缓冲区,预备获取hash值
	publicFile,_ := os.Open(fileName)
	defer publicFile.Close()
	fileInfo,_ := publicFile.Stat()
	buffer := make([]byte, fileInfo.Size())
	publicFile.Read(buffer)
	//2.使用对应散列值算法包的方法,调用New()方法生成一个hash对象
	hash256 := sha256.New()
	//3.向hash对象中添加数据,如果必要可以添加多次
	hash256.Write(buffer)
	//4.计算结果sum,此时数据已经都存放于buffer中,所以Sum这里不需要在添加任何内容,此时结果为2进制
	hashValue := hash256.Sum(nil)
	//5.使用hex16进制包中的格式化方法EncodeToString将hashValue格式化为16进制的字符串
	//  因为2进制数据中存在不可见字符!
	hashString := hex.EncodeToString(hashValue)
	//6.将生成的hash字符串返回
	return hashString
}
func main(){
	hashValue := frankGenerateSha256Hash("frankMsg")
	fmt.Printf("%s", hashValue)
}

代码中的“frankMsg”文件内容如下:

而最终代码的执行结果是:

而其他单向散列函数包中的散列值计算与上面操作几乎完全相同。再一次感谢go语言对与方法封装的如此完备。

猜你喜欢

转载自blog.csdn.net/u013792921/article/details/85042088