G8.3 实现不可逆加密 - 用Go语言 Golang实现

前两节介绍的加密方法都属于“可逆”的加密算法,因为加密后的密文经过解密的过程就可以还原出原文。还有一类加密算法属于“不可逆”的加密算法,是指一般无法进行正常解密还原出原文的加密算法。


不可逆加密算法的应用场景也有很多,最典型的是服务端保存用户登录密码的方式。从保护用户隐私角度考虑,服务器端不应该存储用户的登录密码原文,也不应该保存可逆加密后的密文(因为也可以被解密还原),这时候实践中常用的方法是在服务器保存密码时将其用不可逆的算法转换成密文存储,下次用户登录时服务器将发来的用户密码以同样的不可逆算法加密后再与保存的密码密文做比对来判断是否相同。


从这个例子也可以看出,不可逆加密算法一般要满足这个要求:同样的明文用同样的方式加密后,得到的密文必须是一样,否则就无法用于比对了。


最简单的不可逆加密算法可能就是取模算法了,例如18 % 5 的结果是3,而23 % 5的结果也是3,如果18和23代表明文,“% 5”这个取模操作(也就是求对于5的余数)代表加密算法,3代表加密后的密文,那么显然这个加密算法是不可逆的,因为从密文“3”无法确定原文是18还是23(甚至还可能是其他更多的数字),而任何数字对5取模的结果都是不变的。那么该算法如果用于对密码加密,可以将密码转换后的字节切片中的每个字节数值对5取模后形成新的密文字节切片,服务器端保存这个密文就可以了,以后用户登录时传上来的密码做同样的加密操作,得到的结果与保存的密文应该是一致的。


当然,取模操作作为加密方法来说加密强度太低,实际应用中用的最多的不可逆加密算法是MD5算法,该算法应用了散列函数的原理,可以将任何数据转换成固定长度的字节序列(一般是16个字节),并且与取模操作一样具有原文对应到密文的唯一性。


取模操作也可以看做散列函数的一种,可以将任何数据散列到[0, n)的范围内(n是取模的模数)。散列函数一般都具备这样的特性:原始数据与散列后的数据是多对一的关系,即同样的原始数据用同样的散列函数处理后必然得到同样的结果,但同样的结果不一定对应同一个原始数据。这也是为什么大多数不可逆算法使用散列函数作为核心方法的原因。


下面的代码演示了如何使用Go语言中的crypto/md5等包来实现MD5加密算法。


package main


import (

  "crypto/md5"

  "encoding/hex"

  "io"

  "log"

  "os"

  "strings"

  t "github.com/topxeq/goexamples/tools"

)


func main() {


  //原始字符串

  originalTextT := "测试字符串"


  //对原始字符串生成md5码,md5BytesArrayT是[16]byte类型的数组

  md5BytesArrayT :=md5.Sum([]byte(originalTextT))


  //将数组转换为切片

  md5BytesT := md5BytesArrayT[:]


  t.Printfln("md5字节切片(16个字节): %#v", md5BytesT)


  //将md5字节切片转换为16进制的文本,将有32个字符

  //并转换为全大写字母

  md5TextT := strings.ToUpper(hex.EncodeToString(md5BytesT))


  t.Printfln("md5文本(32位): %#v", md5TextT)


  //用流式方法对字符串进行md5编码

  md5Encoder := md5.New()


  //向md5Encoder中写入字符串

  io.WriteString(md5Encoder, originalTextT)


  //调用Sum函数进行md5编码,并转换为十六进制字符串

  md5TextT = hex.EncodeToString(md5Encoder.Sum(nil))


  t.Printfln("流式编码的md5文本(小写): %#v", md5TextT)


  //直接用流式方法对一个文件进行md5编码

  fileT, errT := os.Open(`c:\test\long.txt`)


  if errT != nil {

       log.Fatal(errT)

  }


  defer fileT.Close()


  md5Encoder = md5.New()


  //带有初始化语句的条件判断

  if _, errT = io.Copy(md5Encoder, fileT); errT!= nil {

       log.Fatal(errT)

  }


  t.Printfln("文件的md5码:%x", md5Encoder.Sum(nil))

}

代码 14‑3 MD5加密示例


代码14‑3中已经有详尽的解释,再附加几点解释如下:


-> 代码中用到的md5包中的函数最主要的是md5.Sum函数,该函数实现了将任意一个字节切片编码为MD5,编码结果的数据类型是[16]byte,即16个字节的字节数组;

-> 由于字节数组与字节切片并不是同一个类型,所以还需要进行转换,将[16]byte类型的数据转换为[]byte类型才能符合后面hex.EncodeToString等函数的传入参数类型要求;

-> 目前一般使用时都是用MD码的十六进制文本形式,这会有32个字符长度;

-> 代码后面也演示了如何用流式方法来直接编码一个字符串为MD码以及直接编码一个文件;md5.New函数将新建一个MD5的编码器(hash.Hash类型),该编码器支持流式写入,写入完所有内容后,调用该编码器的Sum函数就会进行MD5编码;


代码14‑3的运行结果是:


md5字节切片(16个字节): []byte{0x1f, 0x3c, 0xa0, 0x51, 0x2, 0x8d, 0x1d, 0x1e, 0x95, 0xa6, 0xf4, 0xe2, 0x69, 0xd7, 0x27, 0xab}

md5文本(32位): "1F3CA051028D1D1E95A6F4E269D727AB"

流式编码的md5文本(小写): "1f3ca051028d1d1e95a6f4e269d727ab"

文件的md5码:9da81dede7a381a6d9fecc0cd69a81a9


可以看出,无论使用普通方式还是流式方式进行MD5编码,对同样的输入字符串的结果都是一样的(注意,十六进制文本的大小写一般在各个系统中都可以识别,目前的趋势更多的是使用小写形式)。


类似MD5这样的不可逆加密,也不需要使用密码就可以直接进行加密。


最后顺便提一下,任何加密理论上都可以被破解,即使是不可逆的加密算法也是有办法破解的。MD5的破解方法已经在网络上有所流传,实质上是穷举法的破解方式,就是不停地收集和计算各种明文的MD5编码并将这两者的成对保存起来,然后根据保存的海量数据,对MD5密文进行反查,这需要大量的积累,消耗的资源也较大,查出来的结果也可能是多个(MD5的密文与明文是一对多的关系),但确实也算是一种方法,在此说明一下供大家了解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容