常見的加密算法

在項目開發過程中,當我們利用數據庫存儲一些關于用戶的隱私信息,諸如密碼、帳戶密鑰等數據時,需要加密后才向數據庫寫入。這時,我們需要一些高效地、簡單易用的加密算法,當我們向數據庫寫數據時加密數據,然后把加密后的數據存入數據庫;當需要讀取數據時,從數據庫把加密后的數據取出來,再通過算法解密。

常用的加密算法有Base64、MD5、AES和DES。

Base64

Base64是一種任意二進制到文本字符串的編碼方法,常用于在URL、Cookie、網頁中傳輸少量二進制數據。

首先使用Base64編碼需要一個含有64個字符的表,這個表由大小寫字母、數字、+和/組成。采用Base64編碼處理數據時,會把每三個字節共24位作為一個處理單元,再分為四組,每組6位,查表后獲得相應的字符即編碼后的字符串。編碼后的字符串長32位,這樣,經Base64編碼后,原字符串增長1/3。如果要編碼的數據不是3的倍數,最后會剩下一到兩個字節,Base64編碼中會采用\x00在處理單元后補全,編碼后的字符串最后會加上一到兩個 = 表示補了幾個字節。

Base64表

    BASE64Table = "IJjkKLMNO567PQX12RVW3YZaDEFGbcdefghiABCHlSTUmnopqrxyz04stuvw89+/"

加密。函數里的第二行的代碼可以把一個輸入的字符串轉換成一個字節數組。

func Encode(data string) string {
    content := *(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&data))))
    coder := base64.NewEncoding(BASE64Table)
    return coder.EncodeToString(content)
}

解密。函數返回處的代碼可以把一個 字節數組轉換成一個字符串。

func Decode(data string) string {
    coder := base64.NewEncoding(BASE64Table)
    result, _ := coder.DecodeString(data)
    return *(*string)(unsafe.Pointer(&result))
}

測試。

    func main(){
      strTest := "I love this beautiful world!"
      strEncrypt := Encode(strTest)
      strDecrypt := Decode(strEncrypt)
      fmt.Println("Encrypted:",strEncrypt)
      fmt.Println("Decrypted:",strDecrypt)
    }
//Output:
//Encrypted: VVJmGsEBONRlFaPfDCYgcaRSEHYmONcpbCrAO2==
//Decrypted: I love this beautiful world!

MD5

MD5的全稱是Message-DigestAlgorithm 5,它可以把一個任意長度的字節數組轉換成一個定長的整數,并且這種轉換是不可逆的。對于任意長度的數據,轉換后的MD5值長度是固定的,而且MD5的轉換操作很容易,只要原數據有一點點改動,轉換后結果就會有很大的差異。正是由于MD5算法的這些特性,它經常用于對于一段信息產生信息摘要,以防止其被篡改。其還廣泛就于操作系統的登錄過程中的安全驗證,比如Unix操作系統的密碼就是經過MD5加密后存儲到文件系統中,當用戶登錄時輸入密碼后, 對用戶輸入的數據經過MD5加密后與原來存儲的密文信息比對,如果相同說明密碼正確,否則輸入的密碼就是錯誤的。

MD5以512位為一個計算單位對數據進行分組,每一分組又被劃分為16個32位的小組,經過一系列處理后,輸出4個32位的小組,最后組成一個128位的哈希值。對處理的數據進行512求余得到N和一個余數,如果余數不為448,填充1和若干個0直到448位為止,最后再加上一個64位用來保存數據的長度,這樣經過預處理后,數據變成(N+1)x 512位。

加密。Encode 函數用來加密數據,Check函數傳入一個未加密的字符串和與加密后的數據,進行對比,如果正確就返回true。

func Check(content, encrypted string) bool {
    return strings.EqualFold(Encode(content), encrypted)
}
func Encode(data string) string {
    h := md5.New()
    h.Write([]byte(data))
    return hex.EncodeToString(h.Sum(nil))
}

測試。

func main() {
    strTest := "I love this beautiful world!"
    strEncrypted := "98b4fc4538115c4980a8b859ff3d27e1"
    fmt.Println(Check(strTest, strEncrypted))
}
//Output:
//true

DES

DES是一種對稱加密算法,又稱為美國數據加密標準。DES加密時以64位分組對數據進行加密,加密和解密都使用的是同一個長度為64位的密鑰,實際上只用到了其中的56位,密鑰中的第8、16...64位用來作奇偶校驗。DES有ECB(電子密碼本)和CBC(加密塊)等加密模式。

DES算法的安全性很高,目前除了窮舉搜索破解外, 尚無更好的的辦法來破解。其密鑰長度越長,破解難度就越大。

填充和去填充函數。

func ZeroPadding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padtext := bytes.Repeat([]byte{0}, padding)
    return append(ciphertext, padtext...)
}

func ZeroUnPadding(origData []byte) []byte {
    return bytes.TrimFunc(origData,
        func(r rune) bool {
            return r == rune(0)
        })
}

加密。

func Encrypt(text string, key []byte) (string, error) {
    src := []byte(text)
    block, err := des.NewCipher(key)
    if err != nil {
        return "", err
    }
    bs := block.BlockSize()
    src = ZeroPadding(src, bs)
    if len(src)%bs != 0 {
        return "", errors.New("Need a multiple of the blocksize")
    }
    out := make([]byte, len(src))
    dst := out
    for len(src) > 0 {
        block.Encrypt(dst, src[:bs])
        src = src[bs:]
        dst = dst[bs:]
    }
    return hex.EncodeToString(out), nil
}

解密。

func Decrypt(decrypted string , key []byte) (string, error) {
    src, err := hex.DecodeString(decrypted)
    if err != nil {
        return "", err
    }
    block, err := des.NewCipher(key)
    if err != nil {
        return "", err
    }
    out := make([]byte, len(src))
    dst := out
    bs := block.BlockSize()
    if len(src)%bs != 0 {
        return "", errors.New("crypto/cipher: input not full blocks")
    }
    for len(src) > 0 {
        block.Decrypt(dst, src[:bs])
        src = src[bs:]
        dst = dst[bs:]
    }
    out = ZeroUnPadding(out)
    return string(out), nil
}

測試。在這里,DES中使用的密鑰key只能為8位。

func main() {
    key := []byte("2fa6c1e9")
    str :="I love this beautiful world!"
    strEncrypted, err := Encrypt(str, key)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Encrypted:", strEncrypted)
    strDecrypted, err := Decrypt(strEncrypted, key)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Decrypted:", strDecrypted)
}
//Output:
//Encrypted: 5d2333b9fbbe5892379e6bcc25ffd1f3a51b6ffe4dc7af62beb28e1270d5daa1
//Decrypted: I love this beautiful world!

AES

AES,即高級加密標準(Advanced Encryption Standard),是一個對稱分組密碼算法,旨在取代DES成為廣泛使用的標準。AES中常見的有三種解決方案,分別為AES-128、AES-192和AES-256。

AES加密過程涉及到4種操作:字節替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和輪密鑰加(AddRoundKey)。解密過程分別為對應的逆操作。由于每一步操作都是可逆的,按照相反的順序進行解密即可恢復明文。加解密中每輪的密鑰分別由初始密鑰擴展得到。算法中16字節的明文、密文和輪密鑰都以一個4x4的矩陣表示。

AES 有五種加密模式:電碼本模式(Electronic Codebook Book (ECB))、密碼分組鏈接模式(Cipher Block Chaining (CBC))、計算器模式(Counter (CTR))、密碼反饋模式(Cipher FeedBack (CFB))和輸出反饋模式(Output FeedBack (OFB))。下面以CFB為例。

加密。iv即初始向量,這里取密鑰的前16位作為初始向量。

func Encrypt(text string, key []byte) (string, error) {
    var iv = key[:aes.BlockSize]
    encrypted := make([]byte, len(text))
    block, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }
    encrypter := cipher.NewCFBEncrypter(block, iv)
    encrypter.XORKeyStream(encrypted, []byte(text))
    return hex.EncodeToString(encrypted), nil
}

解密。

func Decrypt(encrypted string, key []byte) (string, error) {
    var err error
    defer func() {
        if e := recover(); e != nil {
            err = e.(error)
        }
    }()
    src, err := hex.DecodeString(encrypted)
    if err != nil {
        return "", err
    }
    var iv = key[:aes.BlockSize]
    decrypted := make([]byte, len(src))
    var block cipher.Block
    block, err = aes.NewCipher([]byte(key))
    if err != nil {
        return "", err
    }
    decrypter := cipher.NewCFBDecrypter(block, iv)
    decrypter.XORKeyStream(decrypted, src)
    return string(decrypted), nil
}

測試。密鑰key只能為16位、24位或32位,分別對應AES-128, AES-192和 AES-256。

func main(){
    str := "I love this beautiful world!"
    key := []byte{0xBA, 0x37, 0x2F, 0x02, 0xC3, 0x92, 0x1F, 0x7D,
        0x7A, 0x3D, 0x5F, 0x06, 0x41, 0x9B, 0x3F, 0x2D,
        0xBA, 0x37, 0x2F, 0x02, 0xC3, 0x92, 0x1F, 0x7D,
        0x7A, 0x3D, 0x5F, 0x06, 0x41, 0x9B, 0x3F, 0x2D,
        }
    strEncrypted,err := Encrypt(str, key)
    if err != nil {
        log.Error("Encrypted err:",err)
    }
    fmt.Println("Encrypted:",strEncrypted)
    strDecrypted,err := Decrypt(strEncrypted, key)
    if err != nil {
        log.Error("Decrypted err:",err)
    }
    fmt.Println("Decrypted:",strDecrypted)
}
//Output:
//Encrypted: f866bfe2a36d5a43186a790b41dc2396234dd51241f8f2d4a08fa5dc
//Decrypted: I love this beautiful world!

參考

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,619評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,155評論 3 425
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,635評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,539評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,255評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,646評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,655評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,838評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,399評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,146評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,338評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,893評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,565評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,983評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,257評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,059評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,296評論 2 376

推薦閱讀更多精彩內容

  • 由于計算機軟件的非法復制,通信的泄密、數據安全受到威脅,解密及盜版問題日益嚴重,甚至引發國際爭端,所以在信息安全技...
    翻山越嶺的另一邊閱讀 1,652評論 0 3
  • 這篇文章主要講述在Mobile BI(移動商務智能)開發過程中,在網絡通信、數據存儲、登錄驗證這幾個方面涉及的加密...
    雨_樹閱讀 2,581評論 0 6
  • 概述 之前一直對加密相關的算法知之甚少,只知道類似DES、RSA等加密算法能對數據傳輸進行加密,且各種加密算法各有...
    Henryzhu閱讀 3,044評論 0 14
  • 首先羅列一些知識點: 1.加密算法通常分為對稱性加密算法和非對稱性加密算法:對于對稱性加密算法,信息接收雙方都需事...
    JonesCxy閱讀 1,408評論 2 4
  • “光而秒流,其速可知 昔人言之,時以喻金 金可復得,時不再來 敬告吾友,其勉之哉!” 再讀啟功的贈言,內心是否滿懷...
    XP_a61e閱讀 624評論 0 0