對稱加密算法以及使用方法

加密的原因:保證數據安全

加密必備要素:1、明文/密文? ? 2、秘鑰? ? 3、算法

秘鑰:在密碼學中是一個定長的字符串、需要根據加密算法確定其長度

加密算法解密算法一般互逆、也可能相同


常用的兩種加密方式:

對稱加密:秘鑰:加密解密使用同一個密鑰、數據的機密性雙向保證、加密效率高、適合加密于大數據大文件、加密強度不高(相對于非對稱加密)

非對稱加密:秘鑰:加密解密使用的不同秘鑰、有兩個密鑰、需要使用密鑰生成算法生成兩個秘鑰、數據的機密性只能單向加密、如果想解決這個問題、雙向都需要各自有一對秘鑰、加密效率低、加密強度高

?? ??? ??? ??? ?? ? 公鑰:可以公開出來的密鑰、公鑰加密私鑰解密

?? ??? ??? ??? ?? ? 私鑰:需要自己妥善保管、不能公開、私鑰加密公鑰解密

安全程度高:多次加密

按位異或運算


凱撒密碼:加密方式? ? 通過將銘文所使用的字母表按照一定的字數平移來進行加密


加密為向右平移三個字符


算法為

mod:取余

加密三要素:明文/密文(字母)、秘鑰(3)、算法(向右平移3/-3)

安全常識:不要使用自己研發的算法、不要鉆牛角尖、沒必要研究底層實現、了解怎么應用;低強度的密碼比不進行任何加密更危險;任何密碼都會被破解;密碼只是信息安全的一部分

保證數據的機密性、完整性、認證、不可否認性


計算機操作對象不是文字、而是由0或1排列而成的比特序列、程序存儲在磁盤是二進制的字符串、為比特序列、將現實的東西映射為比特序列的操作稱為編碼、加密又稱之為編碼、解密稱之為解碼、根據ASCII對照表找到對應的數字、轉換成二進制

三種對稱加密算法:DES\3DES\ AES??

DES:已經被破解、除了用它來解密以前的明文、不再使用

密鑰長度為56bit/8、為7byte、每隔7個bit會設置一個用于錯誤檢查的比特、因此實際上是64bit

分組密碼(以組為單位進行處理):加密時是按照一個單位進行加密(8個字節/64bit為一組)、每一組結合秘鑰通過加密算法得到密文、加密后的長度不變


3DES:三重DES為了增加DES的強度、將DES重復三次所得到的一種加密算法? ?密鑰長度24byte、分成三份? 加密--解密--加密 目的:為了兼容DES、秘鑰1秘鑰2相同==三個秘鑰相同? ---加密一次?? ?? ? 密鑰1秘鑰3相同--加密三次? ? 三個密鑰不相同最好、此時解密相當于加密、中間的一次解密是為了有三個密鑰相同的情況


此時的解密操作與加密操作互逆,安全、效率低

數據先解密后加密可以么?可以、解密相當于加密、加密解密說的是算法

AES:(首選推薦)底層算法為Rijndael? ?分組長度為128bit、密鑰長度為128bit到256bit范圍內就可以? ?但是在AES中、密鑰長度只有128bit\192bit\256bit?? ??在go提供的接口中、只能是16字節(128bit)、其他語言中秘鑰可以選擇

目前為止最安全的、效率高

底層算法

分組密碼的模式:

按位異或、對數據進行位運算、先將數據轉換成二進制、按位異或操作符^、相同為真、不同為假、非0為假? ? 按位異或一次為加密操作、按位異或兩次為解密操作:a和b按位異或一次、結果再和b按位異或

ECB?: 如果明文有規律、加密后的密文有規律不安全、go里不提供該接口、明文分組分成固定大小的塊、如果最后一個分組不滿足分組長度、則需要補位

CBC:密碼鏈

問題:如何對字符串進行按位異或?解決了ECB的規律可查缺點、但是他不能并行處理、最后一個明文分組也需要填充 、初始化向量長度與分組長度相同

CFB:密文反饋模式

不需要填充最后一個分組、對密文進行加密

OFB:

不需要對最后一組進行填充

CTR計數器:

不需要對最后一組進行填充、不需要初始化向量??? ?


Go中的實現

官方文檔中:

在創建aes或者是des接口時都是調用如下的方法、返回的block為一個接口

func NewCipher(key []byte) (cipher.Block,error)

type Block interface {

????// 返回加密字節塊的大小

????BlockSize() int

????// 加密src的第一塊數據并寫入dst,src和dst可指向同一內存地址

????Encrypt(dst, src []byte)

????// 解密src的第一塊數據并寫入dst,src和dst可指向同一內存地址

????Decrypt(dst, src []byte)

}

Block接口代表一個使用特定密鑰的底層塊加/解密器。它提供了加密和解密獨立數據塊的能力。

Block的Encrypt/Decrypt也能進行加密、但是只能加密第一組、因為aes的密鑰長度為16、所以進行操作的第一組數據長度也是16

如果分組模式選擇的是cbc

func NewCBCEncrypter(b Block, iv []byte) BlockMode? ? 加密

func NewCBCDecrypter(b Block, iv []byte) BlockMode? ? 解密

加密解密都調用同一個方法CryptBlocks()

并且cbc分組模式都會遇到明文最后一個分組的補充、所以會用到加密字節的大小

返回一個密碼分組鏈接模式的、底層用b加密的BlockMode接口,初始向量iv的長度必須等于b的塊尺寸。iv自己定義

返回的BlockMode同樣也是一個接口類型

type BlockMode interface {

????// 返回加密字節塊的大小

????BlockSize() int

????// 加密或解密連續的數據塊,src的尺寸必須是塊大小的整數倍,src和dst可指向同一內存地址

????CryptBlocks(dst, src []byte)

}

BlockMode接口代表一個工作在塊模式(如CBC、ECB等)的加/解密器

返回的BlockMode其實是一個cbc的指針類型中的b和iv

# 加密流程:?

1. 創建一個底層使用des/3des/aes的密碼接口 "crypto/des" func NewCipher(key []byte) (cipher.Block, error) # -- des func NewTripleDESCipher(key []byte) (cipher.Block, error) # -- 3des "crypto/aes" func NewCipher(key []byte) (cipher.Block, error) # == aes?

2. 如果使用的是cbc/ecb分組模式需要對明文分組進行填充

3. 創建一個密碼分組模式的接口對象 - cbc func NewCBCEncrypter(b Block, iv []byte) BlockMode # 加密 - cfb func NewCFBEncrypter(block Block, iv []byte) Stream # 加密 - ofb - ctr

?4. 加密, 得到密文

流程:

填充明文:

先求出最后一組中的字節數、創建新切片、長度為新切片、值也為切片的長度、然后利用bytes.Reapet將長度換成字節切片、追加到原明文中

//明文補充

func padPlaintText(plaintText []byte,blockSize int)[]byte{

????//1、求出需要填充的個數

????padNum := blockSize-len(plaintText) % blockSize

????//2、對填充的個數進行操作、與原明文進行合并

????newPadding := []byte{byte(padNum)}

????newPlain := bytes.Repeat(newPadding,padNum)

????plaintText = append(plaintText,newPlain...)

????return plaintText

}

去掉填充數據:

拿去切片中的最后一個字節、得到尾部填充的字節個數、截取返回

//解密后的明文曲調補充的地方

func createPlaintText(plaintText []byte,blockSize int)[]byte{


????//1、得到最后一個字節、并將字節轉換成數字、去掉明文中此數字大小的字節

????padNum := int(plaintText[len(plaintText)-1])

????newPadding := plaintText[:len(plaintText)-padNum]


????return newPadding

}

des加密:

1、創建一個底層使用des的密碼接口、參數為秘鑰、返回一個接口

2、對明文進行填充

3、創建一個cbc模式的接口、需要創建iv初始化向量、返回一個blockmode對象

4、加密、調用blockmode中的cryptBlock函數進行加密、參數為目標參數和源參數

//des利用分組模式cbc進行加密

func EncryptoText(plaintText []byte,key []byte)[]byte{

????//1、創建des對象

????cipherBlock,err := des.NewCipher(key)

????if err != nil {

????????panic(err)

????}


????//2、對明文進行填充

????newText := padPlaintText(plaintText,cipherBlock.BlockSize())


????//3、選擇分組模式、其中向量的長度必須與分組長度相同

????iv := make([]byte,cipherBlock.BlockSize())

????blockMode := cipher.NewCBCEncrypter(cipherBlock,iv)


????//4、加密

????blockMode.CryptBlocks(newText,newText)

????return newText

}

des解密:

1、創建一個底層使用des的密碼接口、參數為秘鑰、返回一個接口

2、創建一個cbc模式的接口、需要創建iv初始化向量,返回一個blockmode對象

3、加密、調用blockmode中的cryptBlock函數進行解密、參數為目標參數和源參數

4、調用去掉填充數據的方法

//des利用分組模式cbc進行解密

func DecryptoText(cipherText []byte, key []byte)[]byte{

????//1、創建des對象

????cipherBlock,err := des.NewCipher(key)

????if err != nil {

????????panic(err)

????}

????//2、創建cbc分組模式接口

????iv := []byte("12345678")

????blockMode := cipher.NewCBCDecrypter(cipherBlock,iv)

????//3、解密

????blockMode.CryptBlocks(cipherText,cipherText)

????//4、將解密后的數據進行去除填充的數據

????newText := clearPlaintText(cipherText,cipherBlock.BlockSize())

????return newText

}

Main函數調用

func main(){

????//需要進行加密的明文

????plaintText := []byte("CBC--密文沒有規律、經常使用的加密方式,最后一個分組需要填充,需要初始化向量" +

????????"(一個數組、數組的長度與明文分組相等、數據來源:負責加密的人提供,加解密使用的初始化向量必須相同)")

????//密鑰Key的長度需要與分組長度相同、且加密解密的密鑰相同

????key := []byte("1234abcd")

????//調用加密函數

????cipherText := EncryptoText(plaintText,key)

????newPlaintText := DecryptoText(cipherText,key)

????fmt.Println(string(newPlaintText))

}

AES加密解密相同、所以只需要調用一次方法就可以加密、調用兩次則解密

推薦是用分組模式:cbc、ctr

aes利用分組模式cbc進行加密

//對明文進行補充

func paddingPlaintText(plaintText []byte , blockSize int ) []byte {

????//1、求出分組余數

????padNum := blockSize - len(plaintText) % blockSize

????//2、將余數轉換為字節切片、然后利用bytes.Repeat得出有該余數的大小的字節切片

????padByte := bytes.Repeat([]byte{byte(padNum)},padNum)

????//3、將補充的字節切片添加到原明文中

????plaintText = append(plaintText,padByte...)

????return plaintText

}

//aes加密

func encryptionText(plaintText []byte, key []byte) []byte {

????//1、創建aes對象

????block,err := aes.NewCipher(key)

????if err != nil {

????????panic(err)

????}

????//2、明文補充

????newText := paddingPlaintText(plaintText,block.BlockSize())

????//3、創建cbc對象

????iv := []byte("12345678abcdefgh")

????blockMode := cipher.NewCBCEncrypter(block,iv)

????//4、加密

????blockMode.CryptBlocks(newText,newText)

????return newText

}

//解密后的去尾

func clearplaintText(plaintText []byte, blockSize int) []byte {

????//1、得到最后一個字節、并轉換成整型數據

????padNum := int(plaintText[len(plaintText)-1])

????//2、截取明文字節中去掉得到的整型數據之前的數據、此處出錯、沒有用len-padNum

????newText := plaintText[:len(plaintText)-padNum]

????return newText

}

//aes解密

func deCryptionText(crypherText []byte, key []byte ) []byte {

????//1、創建aes對象

????block, err := aes.NewCipher(key)

????if err != nil {

????????panic(err)

????}

????//2、創建cbc對象

????iv := []byte("12345678abcdefgh")

????blockMode := cipher.NewCBCDecrypter(block,iv)

????//3、解密

????blockMode.CryptBlocks(crypherText,crypherText)

????//4、去尾

????newText := clearplaintText(crypherText,block.BlockSize())

????return newText

}

func main(){

????//需要進行加密的明文

????plaintText := []byte("CBC--密文沒有規律、經常使用的加密方式,最后一個分組需要填充,需要初始化向量")

????//密鑰Key的長度需要與分組長度相同、且加密解密的密鑰相同

????key := []byte("12345678abcdefgh")

????//調用加密函數

????cipherText := encryptionText(plaintText,key)

????//調用解密函數

????newPlaintText := deCryptionText(cipherText,key)

????fmt.Println("解密后",string(newPlaintText))

}

//aes--ctr加密

func encryptionCtrText(plaintText []byte, key []byte) []byte {


????//1、創建aes對象

????block,err := aes.NewCipher(key)

????if err != nil {

????????panic(err)

????}


????//2、創建ctr對象,雖然ctr模式不需要iv,但是go中使用ctr時還是需要iv

????iv := []byte("12345678abcdefgh")

????stream := cipher.NewCTR(block,iv)

????stream.XORKeyStream(plaintText,plaintText)


????return plaintText

}

func main() {

//aes--ctr加密解密、調用兩次即為解密、因為加密解密函數相同stream.XORKeyStream

????ctrcipherText := encryptionCtrText(plaintText, key)

????ctrPlaintText := encryptionCtrText(ctrcipherText,key)

????fmt.Println("aes解密后", string(ctrPlaintText))

}

英文單詞:

明文:plaintext? ? ?密文:ciphertext? ?填充:padding/fill? ? 去掉clear? 加密Encryption? 解密Decryption

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 目錄一、對稱加密?1、對稱加密是什么?2、對稱加密的優點?3、對稱加密的問題?4、對稱加密的應用場景?5、對稱加密...
    意一ineyee閱讀 62,134評論 8 110
  • 在介紹加密算法之前, 先介紹一下 base64: 0. base64 Base64要求把每三個8Bit的字節轉換為...
    reboot_q閱讀 13,367評論 3 8
  • 作者:文/郭敏 圖/楊釗 4月23日下午,由圖書館、校團委和校學生會主辦,社團聯合會、讀者協會承辦的第十一屆讀書...
    貓耳郵筒閱讀 243評論 0 0
  • 有人愛的沉默、有人愛的激昂 有人愛的平凡、有人愛的浪漫 有人愛的卑微、有人愛的高尚 有人愛的艱難、有人愛的幸福 有...
    夏L天閱讀 329評論 0 0
  • 2017年11月19日 星期天 晴 今早我上班把孩子一個人關在家里,其實我還有點不放心,走的時...
    宋雯楠媽媽閱讀 270評論 0 0