G8.1 自己设计最基本的数据加密解密算法-用Go语言实现

一般情况下所说的“加密”,是指对一段数据进行特定的处理后,使其不被会人或计算机识别出原有数据的过程;“解密”则是与之相反的过程,即将加密处理后的数据还原成原始数据的过程。加密算法都有一定的“加密强度”,加密强度越高,代表着这种加密算法被破译的可能性越小,或者说破译这种加密算法的代价越高。一般研制加密算法时,并不要求该算法一定不可以会被破译,而是达到一定的加密强度目标就可以。例如,如果只是朋友之间传送几句无伤大雅但又不是很愿意让外人看到的话,用强度很低的加密算法就可以了;如果涉及商业机密等高敏感性的数据,则需要加密强度很高的算法。


如同我们前面所说,计算机中一般最小的数据单位是字节,除了很特殊的情况,一般很少用二进制位(也叫比特,即bit)来做最小数据单位。Go语言中,绝大多数类型的数据都可以转换为字节切片([]byte类型),因此,如果一种加密算法和对应的解密算法能够对字节切片进行加密解密,那么它也就可以对所有的数据类型进行加密解密。


本节将介绍一个自定义的、非常简单的,加密强度也比较低的加密算法和其对应的解密算法,主要用于演示加密、解密算法的基本实现方式。


这个算法的描述如下:


-> 加密时,首先要确定一个密码,例如“test”,转换成字节切片将是[]byte{0x74, 0x65, 0x73,

0x74};

-> 假设要加密的一段文本字符串是“This is an example.”,也转换成字节切片是[]byte{0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e};

-> 加密的过程中,先将原文字符串的第一个字节与密码的第一个字节相加,得到加密后的第一个字节。注意如果两个字节相加超过255,将会发生“溢出”的情况,即该数据类型无法容纳计算后的结果,例如一个字节最大能够表示的整数是255,而如果代表原文和密码的两个字节分别是十进制的200和90,则相加结果为290,超过了255,此时该结果会被去掉255,变成35。溢出对我们的计算并不会有影响,因为解密时如果把35减去90,这时候会发生“负向”的溢出,得到-55,由于字节必须是0至255范围之间的整数,所以最终结果会再加上255而得到200,这正好是原数据的值。

-> 然后依次将原文的第二个字节与密码的第二个字节相加,如此继续下去,直到原文的第5个字节时,密码已经没有多余的字节,此时就再从头加上密码的第1个字节,然后原文的第6个字节加上密码的第2个字节,……,如此循环往复直到所有字节加密完毕;

-> 为了提高一定的加密强度,我们再在之前每一次相加中再多加一个循环变量的当前值,即第一次相加(原文的第一个字节与密码的第一个字节相加)再多加0,第二次相加多加1,如此一直到加密完原文最后一个字节即得到最终加密后的密文。

-> 由于密文是由字节加法而来,各个字节的值不一定像原文那样是可显示字符,因此密文一般只能以字节切片的形式存在,如果保存成文件也是二进制文件。

-> 解密过程与加密过程完全相反,即把密文的每个字节与密码的每个字节循环相减,再多减一个循环变量的值,这样就会还原出原文的所有字节。

-> 这种加密解密算法,显然需要加密解密的双方都知道密码才可以进行正确的加密解密。


下面是实现该算法的代码:


package main


import (

  t "tools"

)


// encryptBytes 是用密码codeA来加密原文dataA的函数

func encryptBytes(dataA []byte, codeA []byte) []byte {


  //获取原始数据的长度

  dataLenT := len(dataA)


  //获取密码的长度

  codeLenT := len(codeA)


  //创建放置密文的缓冲区,其大小与原文的字节长度应该是一样的

  encBufT := make([]byte, dataLenT)


  //循环进行加密

  for i := 0; i < dataLenT; i++ {


       // codeA[i%codeLenT]可以保证循环取到合理索引范围内的密码字节

       encBufT[i] = dataA[i] + codeA[i%codeLenT]+ byte(i)

  }


  return encBufT

}


// decryptBytes 是用密码codeA来解密密文dataA的函数

func decryptBytes(dataA []byte, codeA []byte) []byte {


  //获取密文数据的长度

  dataLenT := len(dataA)


  //获取密码的长度

  codeLenT := len(codeA)


  //创建放置还原的原文的缓冲区,其大小与密文的字节长度应该是一样的

  decBufT := make([]byte, dataLenT)


  //循环进行解密

  for i := 0; i < dataLenT; i++ {


       // codeA[i%codeLenT]可以保证循环取到合理索引范围内的密码字节

       decBufT[i] = dataA[i] - codeA[i%codeLenT]- byte(i)

  }


  return decBufT

}


func main() {


  originText := "This is an example."


  codeT := "test"


  t.Printfln("原文是:%#v", originText)

  t.Printfln("密码是:%#v", []byte(codeT))


  encBytes := encryptBytes([]byte(originText),[]byte(codeT))


  t.Printfln("加密后的字节切片是:%#v", encBytes)


  decBytes := decryptBytes(encBytes,[]byte(codeT))


  t.Printfln("解密后的字节切片是%#v", decBytes)

  t.Printfln("解密后还原的原文是%#v", string(decBytes))


}

代码 14‑1crypto1/crypto1.go

代码14‑1忠实地实现了前述的加密解密算法,代码很简单,其中也有足够的注释,运行后的结果如下:

原文是:"This is an example."

密码是:[]byte{0x74, 0x65, 0x73, 0x74}

加密后的字节切片是:[]byte{0xc8, 0xce, 0xde, 0xea, 0x98, 0xd3, 0xec, 0x9b, 0xdd, 0xdc, 0x9d, 0xe4, 0xf8, 0xd3, 0xee, 0xf3, 0xf0, 0xdb, 0xb3}

解密后的字节切片是[]byte{0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e}

解密后还原的原文是"This is an example."

可以看到,原文经过加密和解密两个相反的过程之后,再次被还原如初,说明整个加密和解密过程都执行正确,算法也无误。

这个算法和本代码实现的加密解密函数实际上可以用于任何类型数据的加密,加密时只要将该种类型的数据转换为字节切片,而解密时做反向的转换就可以了(例如使用gob包来进行序列化和反序列化)。加密强度虽然不高,但对于非敏感数据的简单加密需求一般也够用了。

如果所需加密/解密的数据量很大,需要使用流式的方法,参照文件拷贝的例子结合本节的加解密方法可以很容易地实现。

另外,在本节代码中加上文件的读取和写入操作,完全可以实现对任何文件的加密解密,由于比较简单,在此不再深入举例。

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