G8.1 自己設計最基本的數(shù)據(jù)加密解密算法-用Go語言實現(xiàn)

一般情況下所說的“加密”塞耕,是指對一段數(shù)據(jù)進行特定的處理后坤塞,使其不被會人或計算機識別出原有數(shù)據(jù)的過程;“解密”則是與之相反的過程纷妆,即將加密處理后的數(shù)據(jù)還原成原始數(shù)據(jù)的過程。加密算法都有一定的“加密強度”晴弃,加密強度越高凭需,代表著這種加密算法被破譯的可能性越小,或者說破譯這種加密算法的代價越高肝匆。一般研制加密算法時,并不要求該算法一定不可以會被破譯顺献,而是達到一定的加密強度目標就可以旗国。例如,如果只是朋友之間傳送幾句無傷大雅但又不是很愿意讓外人看到的話注整,用強度很低的加密算法就可以了能曾;如果涉及商業(yè)機密等高敏感性的數(shù)據(jù)度硝,則需要加密強度很高的算法。


如同我們前面所說寿冕,計算機中一般最小的數(shù)據(jù)單位是字節(jié)蕊程,除了很特殊的情況,一般很少用二進制位(也叫比特驼唱,即bit)來做最小數(shù)據(jù)單位藻茂。Go語言中,絕大多數(shù)類型的數(shù)據(jù)都可以轉換為字節(jié)切片([]byte類型)玫恳,因此辨赐,如果一種加密算法和對應的解密算法能夠對字節(jié)切片進行加密解密,那么它也就可以對所有的數(shù)據(jù)類型進行加密解密京办。


本節(jié)將介紹一個自定義的掀序、非常簡單的,加密強度也比較低的加密算法和其對應的解密算法惭婿,主要用于演示加密不恭、解密算法的基本實現(xiàn)方式。


這個算法的描述如下:


-> 加密時财饥,首先要確定一個密碼换吧,例如“test”,轉換成字節(jié)切片將是[]byte{0x74, 0x65, 0x73,

0x74}佑力;

-> 假設要加密的一段文本字符串是“This is an example.”式散,也轉換成字節(jié)切片是[]byte{0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e};

-> 加密的過程中打颤,先將原文字符串的第一個字節(jié)與密碼的第一個字節(jié)相加暴拄,得到加密后的第一個字節(jié)。注意如果兩個字節(jié)相加超過255编饺,將會發(fā)生“溢出”的情況乖篷,即該數(shù)據(jù)類型無法容納計算后的結果,例如一個字節(jié)最大能夠表示的整數(shù)是255透且,而如果代表原文和密碼的兩個字節(jié)分別是十進制的200和90撕蔼,則相加結果為290,超過了255秽誊,此時該結果會被去掉255鲸沮,變成35。溢出對我們的計算并不會有影響锅论,因為解密時如果把35減去90讼溺,這時候會發(fā)生“負向”的溢出,得到-55最易,由于字節(jié)必須是0至255范圍之間的整數(shù)怒坯,所以最終結果會再加上255而得到200炫狱,這正好是原數(shù)據(jù)的值。

-> 然后依次將原文的第二個字節(jié)與密碼的第二個字節(jié)相加剔猿,如此繼續(xù)下去视译,直到原文的第5個字節(jié)時,密碼已經(jīng)沒有多余的字節(jié)归敬,此時就再從頭加上密碼的第1個字節(jié)酷含,然后原文的第6個字節(jié)加上密碼的第2個字節(jié),……弄慰,如此循環(huán)往復直到所有字節(jié)加密完畢第美;

-> 為了提高一定的加密強度,我們再在之前每一次相加中再多加一個循環(huán)變量的當前值陆爽,即第一次相加(原文的第一個字節(jié)與密碼的第一個字節(jié)相加)再多加0什往,第二次相加多加1,如此一直到加密完原文最后一個字節(jié)即得到最終加密后的密文慌闭。

-> 由于密文是由字節(jié)加法而來别威,各個字節(jié)的值不一定像原文那樣是可顯示字符,因此密文一般只能以字節(jié)切片的形式存在驴剔,如果保存成文件也是二進制文件省古。

-> 解密過程與加密過程完全相反,即把密文的每個字節(jié)與密碼的每個字節(jié)循環(huán)相減丧失,再多減一個循環(huán)變量的值豺妓,這樣就會還原出原文的所有字節(jié)。

-> 這種加密解密算法布讹,顯然需要加密解密的雙方都知道密碼才可以進行正確的加密解密琳拭。


下面是實現(xiàn)該算法的代碼:


package main


import (

? t "tools"

)


// encryptBytes 是用密碼codeA來加密原文dataA的函數(shù)

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


? //獲取原始數(shù)據(jù)的長度

? dataLenT := len(dataA)


? //獲取密碼的長度

? codeLenT := len(codeA)


? //創(chuàng)建放置密文的緩沖區(qū),其大小與原文的字節(jié)長度應該是一樣的

? encBufT := make([]byte, dataLenT)


? //循環(huán)進行加密

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


?????? // codeA[i%codeLenT]可以保證循環(huán)取到合理索引范圍內的密碼字節(jié)

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

? }


? return encBufT

}


// decryptBytes 是用密碼codeA來解密密文dataA的函數(shù)

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


? //獲取密文數(shù)據(jù)的長度

? dataLenT := len(dataA)


? //獲取密碼的長度

? codeLenT := len(codeA)


? //創(chuàng)建放置還原的原文的緩沖區(qū)描验,其大小與密文的字節(jié)長度應該是一樣的

? decBufT := make([]byte, dataLenT)


? //循環(huán)進行解密

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


?????? // codeA[i%codeLenT]可以保證循環(huán)取到合理索引范圍內的密碼字節(jié)

?????? 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("加密后的字節(jié)切片是:%#v", encBytes)


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


? t.Printfln("解密后的字節(jié)切片是%#v", decBytes)

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


}

代碼 14?1crypto1/crypto1.go

代碼14?1忠實地實現(xiàn)了前述的加密解密算法白嘁,代碼很簡單,其中也有足夠的注釋膘流,運行后的結果如下:

原文是:"This is an example."

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

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

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

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

可以看到絮缅,原文經(jīng)過加密和解密兩個相反的過程之后,再次被還原如初呼股,說明整個加密和解密過程都執(zhí)行正確耕魄,算法也無誤。

這個算法和本代碼實現(xiàn)的加密解密函數(shù)實際上可以用于任何類型數(shù)據(jù)的加密彭谁,加密時只要將該種類型的數(shù)據(jù)轉換為字節(jié)切片吸奴,而解密時做反向的轉換就可以了(例如使用gob包來進行序列化和反序列化)。加密強度雖然不高,但對于非敏感數(shù)據(jù)的簡單加密需求一般也夠用了奄抽。

如果所需加密/解密的數(shù)據(jù)量很大,需要使用流式的方法甩鳄,參照文件拷貝的例子結合本節(jié)的加解密方法可以很容易地實現(xiàn)逞度。

另外,在本節(jié)代碼中加上文件的讀取和寫入操作妙啃,完全可以實現(xiàn)對任何文件的加密解密档泽,由于比較簡單,在此不再深入舉例揖赴。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末馆匿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子燥滑,更是在濱河造成了極大的恐慌渐北,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铭拧,死亡現(xiàn)場離奇詭異赃蛛,居然都是意外死亡,警方通過查閱死者的電腦和手機搀菩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門呕臂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肪跋,你說我怎么就攤上這事歧蒋。” “怎么了州既?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵谜洽,是天一觀的道長。 經(jīng)常有香客問我易桃,道長褥琐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任晤郑,我火速辦了婚禮敌呈,結果婚禮上,老公的妹妹穿的比我還像新娘造寝。我一直安慰自己磕洪,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布诫龙。 她就那樣靜靜地躺著析显,像睡著了一般。 火紅的嫁衣襯著肌膚如雪签赃。 梳的紋絲不亂的頭發(fā)上谷异,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天分尸,我揣著相機與錄音,去河邊找鬼歹嘹。 笑死箩绍,一個胖子當著我的面吹牛,可吹牛的內容都是我干的尺上。 我是一名探鬼主播材蛛,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼怎抛!你這毒婦竟也來了卑吭?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤马绝,失蹤者是張志新(化名)和其女友劉穎豆赏,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迹淌,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡河绽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了唉窃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耙饰。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖纹份,靈堂內的尸體忽然破棺而出苟跪,到底是詐尸還是另有隱情,我是刑警寧澤蔓涧,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布件已,位于F島的核電站,受9級特大地震影響元暴,放射性物質發(fā)生泄漏篷扩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一茉盏、第九天 我趴在偏房一處隱蔽的房頂上張望鉴未。 院中可真熱鬧,春花似錦鸠姨、人聲如沸铜秆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽连茧。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間啸驯,已是汗流浹背客扎。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罚斗,地道東北人虐唠。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親廊宪。 傳聞我的和親對象是個殘疾皇子损合,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355