加密過程的每一步都是可逆的,加密和解密用的是同一組密鑰,異或是最簡單的對稱加密算法
DES
DES數組分級
- DES(Data Encryption Standard)數據加密標准,是目前最為流行的加密算法之一。
- 對原始數據(明文)進行分組,每組64位,最后一組不足64位時按一定規則填充。
- 每一組上單獨施加DES算法。
DES子秘鑰生成
- 初始密鑰64位,實際有效位56位,每隔7位有一個校驗位
- 根據初始密鑰生成16個48位的子秘鑰
初始秘鑰【64位】 -> 密鑰置換 -> K0【56位】
置換表
57 | 49 | 41 | 33 | 25 | 17 | 9 | 1 | 58 | 50 | 42 | 34 | 26 | 18 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
10 | 2 | 59 | 51 | 43 | 35 | 27 | 19 | 11 | 3 | 60 | 52 | 44 | 36 |
63 | 55 | 47 | 39 | 31 | 23 | 15 | 7 | 62 | 54 | 46 | 38 | 30 | 22 |
14 | 6 | 61 | 53 | 45 | 37 | 29 | 21 | 13 | 5 | 28 | 20 | 12 | 4 |
DES加密過程
S盒替換
輸入48位,輸出32位,各分為8組,每組6位,輸出每組4位。分別在每組上施加S盒替換,一共8個S盒。
分組模式
CBC(Cipher Block Chaining)密文分組組鏈接模式,將當前明文分組與前一個密文分組進行異或運算,然后再進行加密。
第一組的明文,得到了第一組的密文,使用第一組的密文與第二組的明文進行異或運算,然后在進行DES加密算法,得到第二組的密文… … 所以就沒辦法並行執行,加密更加安全,前后組之間相互聯系。
其他分組模式還有BCE、CTR、CFR、OFB
示例代碼:
package main
import (
"bytes"
"crypto/cipher"
"crypto/des"
"encoding/hex"
"fmt"
)
// XOR 異或運算加解密
func XOR(plain string, key []byte) string {
bPlain := []byte(plain)
bCipher := make([]byte, len(key))
for i, k := range key {
bCipher[i] = k ^ bPlain[i]
}
cipherText := string(bCipher)
return cipherText
}
// ZeroPadding 填充
func ZeroPadding(cipherText []byte, blockSize int) []byte {
padding := blockSize - len(cipherText)%blockSize
padText := bytes.Repeat([]byte{0}, padding) //剩余用0填充
return append(cipherText, padText...)
}
// ZeroUnPadding 反填充
func ZeroUnPadding(origData []byte) []byte {
return bytes.TrimFunc(origData, func(r rune) bool {
return r == rune(0)
})
}
// DesEncrypt DES加密,秘鑰必須是64位,所以key必須是長度為8的byte數組
func DesEncrypt(text string, key []byte) (string, error) {
src := []byte(text)
block, err := des.NewCipher(key) //用des創建一個加密器cipher
if err != nil {
return "", err
}
blockSize := block.BlockSize() //分組的大小,blockSize = 8
src = ZeroPadding(src, blockSize) //填充
out := make([]byte, len(src)) //密文和明文的長度一致
dst := out
for len(src) > 0 {
//分組加密
block.Encrypt(dst, src[:blockSize]) //對src進行加密,加密結果放到dst里
//移到下一組
src = src[blockSize:]
dst = dst[blockSize:]
}
return hex.EncodeToString(out), nil
}
// DesDecrypt
func DesDecrypt(text string, key []byte) (string, error) {
src, err := hex.DecodeString(text) //轉成[]byte
if err != nil {
return "", err
}
block, err := des.NewCipher(key)
if err != nil {
return "", err
}
blockSize := block.BlockSize()
out := make([]byte, len(src))
dst := out
for len(src) > 0 {
//分組解密
block.Decrypt(dst, src[:blockSize]) //對src進行解密,解密結果放到dst里
//移到下一組
src = src[blockSize:]
dst = dst[blockSize:]
}
out = ZeroUnPadding(out) //反填充
return string(out), nil
}
//DesEncryptCBC
func DesEncryptCBC(text string, key []byte) (string, error) {
src := []byte(text)
block, err := des.NewCipher(key) //用des創建一個加密cipher
if err != nil {
return "", err
}
blockSize := block.BlockSize() //分組的大小,blockSize = 8
src = ZeroPadding(src, blockSize) //填充
out := make([]byte, len(src)) //密文和明文的長度一致
encrypted := cipher.NewCBCEncrypter(block, key) //CBC分組模式加密
encrypted.CryptBlocks(out, src) //對src進行加密,加密結果放到out里
return hex.EncodeToString(out), nil
}
// DesDecryptCBC
func DesDecryptCBC(text string, key []byte) (string, error) {
src, err := hex.DecodeString(text) //轉成[]byte
if err != nil {
return "", err
}
block, err := des.NewCipher(key)
if err != nil {
return "", err
}
out := make([]byte, len(src)) //密文和明文長度一致
encrypted := cipher.NewCBCDecrypter(block, key) //CBC分組模式解密
encrypted.CryptBlocks(out, src) //對src進行解密,解密結果放到out里
out = ZeroUnPadding(out) //反填充
return string(out), nil
}
func main() {
plain := "ABCD"
key := []byte{1, 2, 3, 4}
cipherText := XOR(plain, key)
plain = XOR(cipherText, key)
fmt.Printf("明文:%s\n", plain)
fmt.Println("---------------分割線----------------------")
fmt.Println("Golang crypto package")
key = []byte("2022aBc!")
plain = "我們都一樣沒什么不同"
cipherText, _ = DesEncrypt(plain, key)
fmt.Printf("DES密文:%s\n", cipherText)
plain, _ = DesDecrypt(cipherText, key)
fmt.Printf("DES明文:%s\n", plain)
cipherText, _ = DesEncryptCBC(plain, key)
fmt.Printf("DES-CBC密文:%s\n", cipherText)
plain, _ = DesDecryptCBC(cipherText, key)
fmt.Printf("DES-CBC明文:%s\n", plain)
}
>>>>>>>>>>output
明文:ABCD
---------------分割線----------------------
Golang crypto package
DES密文:1fa13fa924245362452305714eb960a024c0a393c509e40120fd1f0900c02e68
DES明文:我們都一樣沒什么不同
DES-CBC密文:8f8ad928e0bcf060a5f8711c2f0ff6677714a1b38a56c26489ed50443200eca6
DES-CBC明文:我們都一樣沒什么不同
AES
AES(Advanced Encryption Stadnard)高級加密標准,皆在取代DES。
示例代碼:
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
)
// ZeroPadding 填充零
func ZeroPadding(cipherText []byte, blockSize int) []byte {
padding := blockSize - len(cipherText)%blockSize
padText := bytes.Repeat([]byte{0}, padding) //剩余用0填充
return append(cipherText, padText...)
}
// ZeroUnPadding 反填充
func ZeroUnPadding(origData []byte) []byte {
return bytes.TrimFunc(origData, func(r rune) bool {
return r == rune(0)
})
}
func AESEncrypt(text string, key []byte) (string, error) {
blockSize := aes.BlockSize //AES的分組大小為16位
src := []byte(text)
src = ZeroPadding(src, blockSize) //填充
out := make([]byte, len(src))
block, err := aes.NewCipher(key) //用aes創建一個加密器cipher
if err != nil {
return "", err
}
encrypted := cipher.NewCBCEncrypter(block, key) //CBC分組模式加密
encrypted.CryptBlocks(out, src) //對src進行加密,加密結果放到dst里
return hex.EncodeToString(out), nil
}
func AESDecrypt(text string, key []byte) (string, error) {
src, err := hex.DecodeString(text) //轉為[]byte
if err != nil {
return "", err
}
out := make([]byte, len(src))
block, err := aes.NewCipher(key) //用aes創建一個加密器cipher
if err != nil {
return "", err
}
decrypted := cipher.NewCBCDecrypter(block, key) //CBC分組模式解密
decrypted.CryptBlocks(out, src) //對src進行解密,解密結果放到dst里
out = ZeroUnPadding(out) //反填充
return string(out), nil
}
func main() {
key := []byte("2022aBc!2022aBc!")
plain := "我們有什么不同"
cipherText,_ := AESEncrypt(plain, key)
fmt.Printf("密文:%s\n", cipherText)
plain, _ = AESDecrypt(cipherText, key)
fmt.Printf("明文:%s\n", plain)
}
>>>>>>>>>>output
密文:94b14fe8380c20dfe2f3e2964275f47052a177d3280b025d6e9700cac04a5ef8
明文:我們有什么不同