Golang数据安全与常用加解密算法-对称加密算法
加密过程的每一步都是可逆的,加密和解密用的是同一组密钥,异或是最简单的对称加密算法
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
明文:我们有什么不同