栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

Go语⾔实现加密算法(上)

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Go语⾔实现加密算法(上)

哈希算法 (⼀)、Hash的定义
  1. hash的单词意思
  • n.剁碎的⻝物; 蔬菜⾁丁
  • vt.把…弄乱; 切碎;
  1. hash (哈希或散列)算法是信息技术领域⾮常基础也⾮常重要的技术。它能任意⻓度的⼆进制值(明⽂)映射为较短的固定⻓度的⼆进制值(Hash 值),并且不同的明⽂很难映射为相同的 Hash 值。hash 值在应⽤中⼜被称为数字指纹(fingerprint)或数字摘要(digest)、消息摘要。
  • 例如计算⼀段话“hello blockchain”的 MD5 hash 值为:
    78e6a8bcdef7a4a254c16054b082c783
  • 这意味着我们只要对某⽂件进⾏ MD5 Hash 计算,得到结果为78e6a8bcdef7a4a254c16054b082c783,这就说明⽂件内容极⼤概率上就是 “hello blockchain”。可⻅,Hash 的核⼼思想⼗分类似于基于内容的编址或命名。
  1. ⼀个优秀的 hash 算法,将能实现:
  • 正向快速:给定明⽂和 hash 算法,在有限时间和有限资源内能计算出hash 值。
  • 逆向困难:给定(若⼲) hash 值,在有限时间内很难(基本不可能)逆推出明⽂。
  • 输⼊敏感:原始输⼊信息修改⼀点信息,产⽣的 hash 值看起来应该都有很⼤不同。
  • 抗冲突:
  • 对不同的关键字可能得到同⼀散列地址,或者说两段内容不同的明⽂,它们的 hash 值可能⼀致。这种现象称冲突或者碰撞。具有相同函数值的关键字对该散列函数来说称做同义词。
  • 抗冲突⼜称为“抗碰撞性”或冲突避免。哈希函数抗冲突就是不同的输⼊不能产⽣相同的输出。
  • 抗冲突并不是不会有冲突,只不过找到有冲突的两个输⼊的代价⾮常⼤。就好像暴⼒破解⼀个有效期为20年的密码,整个破解过程或许⻓达30年。这样虽然最后密码被破解了,但是也失去意义了。
(⼆)、流⾏的哈希算法

⽬前流⾏的 Hash 算法包括 MD5、SHA-1 和 SHA-2系列(SHA-224、SHA-256、SHA-384,和 SHA-512 )。

  1. MD4
    MD4(RFC 1320)是 MIT (Massachusetts Institute of Technology , 麻州理⼯⼤学) 的 Ronald L. Rivest (荣获2002年图灵奖)在 1990 年设计的,MD 是 Message Digest 的缩写。其输出为 128 位。
  2. MD5
    MD5(RFC 1321)是 Rivest 于1991年对 MD4 的改进版本。其输出是128 位。MD5 ⽐ MD4 复杂,并且计算速度要慢⼀点,更安全⼀些。MD5已被证明不具备“强抗碰撞性”。MD5 是⼀个经典的 hash 算法,其和 SHA-1 算法都已被证明安全性不⾜应⽤于商业场景。
  3. SHA
  • SHA (Secure Hash Algorithm, [sɪ’kjʊǝ®] ['ælɡǝrɪðǝm] ,加密哈希算法)是⼀个 Hash 函数族,由 NIST(National Institute of Standards and Technology , 美国国家标准技术研究所)于 1993 年发布第⼀个算法。SHA-1 在 1995 年⾯世,它的输出为⻓度 160 位的 hash 值,SHA-1 设计时基于和 MD4 相同原理,SHA-1 已被证明不具备“强抗碰撞性”。
  • 为了提⾼安全性,NIST 还设计出了 SHA-224、SHA-256、SHA-384, 和 SHA-512 算法(统称为 SHA-2),跟 SHA-1 算法原理类似。
  • ⽬前,⼀般认为 MD5 和 SHA1 已经不够安全,推荐⾄少使⽤ SHA-256算法。
  1. RIPEMD-160(RACE Integrity Primitives Evaluation Message Digest 160, RACE完整的原始评估信息摘要 )是⼀个160位的加密哈希函数,旨在替代128位哈希函数MD4、MD5。
  2. 各种hash算法后的⻓度
  • md5(‘1’) ,128位⻓度,16字节
    • c4ca4238a0b923820dcc509a6f75849b //32位16进制数字
  • SHA1(‘1’) ,160位⻓度,20字节
    • 356a192b7913b04c54574d18c28d46e6395428ab //40位16进制数字
  • RIPEMD-160(‘1’) ,160位⻓度,20字节
    • c47907abd2a80492ca9388b05c0e382518ff3960 //40位16进制数字
  • SHA256(‘1’) ,256位⻓度,32字节
    • 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b //64位16进制数字
  • SHA512(‘1’) ,512位⻓度,64字节
    • 4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a //128位16进制数字
(三)、Hash与加密解密的区别
  1. 哈希(Hash)与加密(Encrypt)的区别
  • 这两个概念不是很清晰,容易混淆两者。⽽正确区别两者是正确选择和使⽤哈希与加密的基础。
  • 哈希(Hash)是将⽬标⽂本转换成具有相同⻓度的、不可逆的杂凑字符串(或叫做消息摘要),⽽加密(Encrypt)是将⽬标⽂本转换成具有不同⻓度的、可逆的密⽂。
    • 哈希算法往往被设计成⽣成具有相同⻓度的⽂本,⽽加密算法⽣成的⽂本⻓度与明⽂本身的⻓度有关。
    • 哈希的结果具有相同的⻓度,⽽加密的结果则⻓度不同。实际上,如果使⽤相同的哈希算法,不论你的输⼊有多么⻓,得到的结果⻓度是⼀个常数,⽽加密算法往往与明⽂的⻓度成正⽐。
      • 哈希算法是不可逆的,⽽加密算法是可逆的。
      • 哈希不是⼀⼀映射,是不可逆的。⽽加密算法是⼀⼀映射,是可逆的。
      • 哈希是不可能可逆的,因为如果可逆,那么哈希就是世界上最强悍的压缩⽅式了——能将任意⼤⼩的⽂件压缩成固定⼤⼩。
  1. 哈希(Hash)与加密(Encrypt)的选择
  • 要实现数据保护,可以选择使⽤哈希或加密两种⽅式。那么在什么时候该选择哈希、什么时候该选择加密呢?
  • 基本原则是:
  • 如果被保护数据仅仅⽤作⽐较验证,在以后不需要还原成明⽂形式,则使⽤哈希;
  • 如果被保护数据在以后需要被还原成明⽂,则需要使⽤加密。
  • 例如,你正在做⼀个系统,你打算当⽤户忘记⾃⼰的登录⼝令时,重置此⽤户⼝令为⼀个随机⼝令,⽽后将此随机⼝令发给⽤户,让⽤户下次使⽤此⼝令登录,则适合使⽤哈希。实际上很多⽹站都是这么做的,想想你以前登录过的很多⽹站,是不是当你忘记⼝令的时候,⽹站并不是将你忘记的⼝令发送给你,⽽是发送给你⼀个新的、随机的⼝令,然后让你⽤这个新⼝令登录。这是因为你在注册时输⼊的⼝令被哈希后存储在数据库⾥,⽽哈希算法不可逆,所以即使是⽹站管理员也不可能通过哈希结果复原你的⼝令,⽽只能重置⼝令。
  • 相反,如果你做的系统要求在⽤户忘记⼝令的时候必须将原⼝令发送给⽤户,⽽不是重置其⼝令,则必须选择加密⽽不是哈希。
  1. 对简单哈希(Hash)的攻击
  • 对于哈希的攻击,主要有寻找碰撞法和穷举法。
  • 寻找碰撞法
    • ⽬前对于MD5和SHA1并不存在有效地寻找碰撞⽅法。
    • 我国杰出的数学家王⼩云教授曾经在国际密码学会议上发布了对于MD5和SHA1的碰撞寻找改进算法,但这种⽅法和“破解”相去甚远。该理论⽬前仅具有数学上的意义,她将破解MD5的预期步骤降低了好⼏个数量级,但对于实际应⽤来说仍然是⼀个天⽂数字。

  • 穷举法(或暴⼒破解法)
    • 通俗来说,就是在⼀个范围内,如从000000到999999,将其中所有值⼀个⼀个⽤哈希算法哈希,然后将结果和杂凑串⽐较,如果相同,则这个值就⼀定是源字串或源字串的⼀个碰撞,于是就可以⽤这个值⾮法登录了。
  • 穷举法看似笨拙,但⽬前⼏乎所有的MD5破解机或MD5在线破解都是⽤这种穷举法。
  • 纠其缘由,就是相当⼀部分⼝令是⾮常简单的,如“123456”或“000000”。穷举法是否能成功很⼤程度上取决于⼝令的复杂性。因为穷举法扫描的区间往往是单字符集、规则的区间,或者由字典数据进⾏组合,因此,如果使⽤复杂的⼝令,例如“!@#$%^&*()”这种⼝令,穷举法就很难奏效了。
(四)、SHA256
  1. SHA-256算法输⼊报⽂的最⼤⻓度不超过2^64 bit,输⼊按512-bit分组进⾏
    处理,产⽣的输出是⼀个256-bit的报⽂摘要。
  2. SHA256算法包括以下⼏步:
  • step1:附加填充⽐特。
    • 对报⽂进⾏填充使报⽂⻓度与448 模512 同余(⻓度=448 mod512),填充的⽐特数范围是1 到512,填充⽐特串的最⾼位为1,其余位为0。就是先在报⽂后⾯加⼀个 1,再加很多个0,直到⻓度满⾜mod512=448.为什么是448,因为448+64=512. 第⼆步会加上⼀个64bit的原始报⽂的 ⻓度信息。
  • step2:附加⻓度值。
    • 将⽤64-bit 表示的初始报⽂(填充前)的位⻓度附加在步骤1的结果
      后(低位字节优先)。
  • step3:初始化缓存。
    • 使⽤⼀个256-bit 的缓存来存放该散列函数的中间及最终结果。该缓存表示为A=0x6A09E667 , B=0xBB67AE85 , C=0x3C6EF372 ,D=0xA54FF53A, E=0x510E527F , F=0x9B05688C ,G=0x1F83D9AB , H=0x5BE0CD19 。
  • step4:处理512-bit(16 个字)报⽂分组序列。
    • 该算法使⽤了六种基本逻辑函数,由64 步迭代运算组成。每步都以256-bit 缓存值ABCDEFGH 为输⼊,然后更新缓存内容。每步使⽤⼀个32-bit 常数值Kt 和⼀个32-bit Wt。
(五)、核⼼代码
  1. 基础⼯具函数
func BytesToHexString(arr []byte) string {
 return hex.EncodeToString(arr) }

func HexStringToBytes(s string) ([]byte, error) {
 arr, err := hex.DecodeString(s)
 return arr, err
}

func ReverseHexString(hexStr string) string {
 arr, _ := hex.DecodeString(hexStr)
 ReverseBytes(arr)
 return hex.EncodeToString(arr) }

func ReverseBytes(data []byte) {
 for i, j := 0, len(data)-1; i < j; i, j = i+1, j-1 {
 data[i], data[j] = data[j], data[i]
 }
}
  1. 哈希函数
func SHA256HexString(text string) string {
 sha256Instance := sha256.New()
 arr, _ := hex.DecodeString(text)
 sha256Instance.Write(arr)
 ciphertext := sha256Instance.Sum(nil)
 return fmt.Sprintf("%x", ciphertext) }
func SHA256Double(text string, isHex bool) string {
 sha256Instance := sha256.New()
 if isHex {
 arr, _ := hex.DecodeString(text)
 sha256Instance.Write(arr)
 } else {
 sha256Instance.Write([]byte(text))
 }
 hashBytes := sha256Instance.Sum(nil)
 sha256Instance.Reset()
 sha256Instance.Write(hashBytes)
 hashBytes = sha256Instance.Sum(nil)
 return fmt.Sprintf("%x", hashBytes) }
func HASH(text string, hashType string, isHex bool) string {
 var hashInstance hash.Hash
 switch hashType {
 case "md4":
 hashInstance = md4.New()
 case "md5":
 hashInstance = md5.New()
 case "sha1":
 hashInstance = sha1.New()
 case "sha256":
 hashInstance = sha256.New()
 case "sha512":
 hashInstance = sha512.New()
 case "ripemd160":
 hashInstance = ripemd160.New()
 }
 if isHex {
 arr, _ := hex.DecodeString(text)
 hashInstance.Write(arr)
 } else {
 hashInstance.Write([]byte(text))
 }
 ciphertext := hashInstance.Sum(nil)
 return fmt.Sprintf("%x", ciphertext) }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/965388.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号