一、数据填充
进行DES、3DES、AES三种对称加密算法时,首先要对原始数据进行字节填充,使原始数据位数与所对应加密算法块数据量成倍数。
(一)常采用PKCS5Padding填充、Zeros填充(0填充)
-
block cipher(分组密码、块密码)
-
block size(块大小)
-
DEA、3DES的block size为8位
-
AES的block size为16位
-
(二)PKCS5Padding
-
每个填充的字节都记录了填充的总字节数
-
"a" 填充后:[97 7 7 7 7 7 7 7]
-
"ab" 填充后:[97 98 6 6 6 6 6 6]
-
“一a” 填充后:[228 184 128 97 4 4 4 4]
-
"12345678" 填充后:[49 50 51 52 53 54 55 56 8 8 8 8 8 8 8 8]
PKCS5Padding填充:
// 末尾填充字节
func PKCS5Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize // 要填充的值和个数
slice1 := []byte{byte(padding)} // 要填充的单个二进制值
slice2 := bytes.Repeat(slice1, padding) // 要填充的二进制数组
return append(data, slice2...) // 填充到数据末端
}
去除PKCS5Padding填充:
// 去除填充的字节
func PKCS5UnPadding(data []byte) []byte {
unpadding := data[len(data)-1] // 获取二进制数组最后一个数值
result := data[:(len(data) - int(unpadding))] // 截取开始至总长度减去填充值之间的有效数据
return result
}
(三)ZerosPadding
-
全部填充为0的字节
-
"a" 填充后:[97 0 0 0 0 0 0 0]
-
"ab" 填充后:[97 98 0 0 0 0 0 0]
-
“一a” 填充后:[228 184 128 97 0 0 0 0]
-
"12345678" 填充后:[49 50 51 52 53 54 55 56 0 0 0 0 0 0 0 0]
ZerosPadding填充:文章来源:https://www.toymoban.com/news/detail-474978.html
// 末尾填充0
func ZerosPadding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize // 要填充的个数
slice1 := []byte{0} // 要填充的单个0数据
slice2 := bytes.Repeat(slice1, padding) // 要填充的0二进制数组
return append(data, slice2...) // 填充到数据末端
}
去除ZerosPadding填充:文章来源地址https://www.toymoban.com/news/detail-474978.html
// 去除填充的0
func ZerosUnPadding(data []byte) []byte {
return bytes.TrimRightFunc(data, func(r rune) bool { // 去除满足条件的子切片
return r == 0
})
}
二、加密过程
// 对称加密(Symmetric Cryptography)
func SCEncrypt(originalBytes, key []byte, scType string) ([]byte, error) {
// 1、实例化密码器block(参数为密钥)
var err error
var block cipher.Block
switch scType {
case "des":
block, err = des.NewCipher(key)
case "3des":
block, err = des.NewTripleDESCipher(key)
case "aes":
block, err = aes.NewCipher(key)
}
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、对明文进行填充(参数为原始字节切片和密码对象的区块个数)
paddingBytes := PKCS5Padding(originalBytes, blockSize)
// 3、实例化加密模式(参数为密码对象和密钥)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
// 4、对填充字节后的明文进行加密(参数为加密字节切片和填充字节切片)
cipherBytes := make([]byte, len(paddingBytes))
blockMode.CryptBlocks(cipherBytes, paddingBytes)
return cipherBytes, nil
}
三、解密过程
// 对称解密
func SCDecrypt(cipherBytes, key []byte, scType string) ([]byte, error) {
// 1、实例化密码器block(参数为密钥)
var err error
var block cipher.Block
switch scType {
case "des":
block, err = des.NewCipher(key)
case "3des":
block, err = des.NewTripleDESCipher(key)
case "aes":
block, err = aes.NewCipher(key)
}
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、实例化解密模式(参数为密码对象和密钥)
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
// 3、对密文进行解密(参数为填充字节切片和加密字节切片)
paddingBytes := make([]byte, len(cipherBytes))
blockMode.CryptBlocks(paddingBytes, cipherBytes)
// 4、去除填充的字节(参数为填充切片)
originalBytes := PKCS5UnPadding(paddingBytes)
return originalBytes, nil
}
四、封装字符串加密解密
// 封装字符串对称加密
func SCEncryptString(originalText, key, scType string) (string, error) {
cipherBytes, err := SCEncrypt([]byte(originalText), []byte(key), scType)
if err != nil {
return "", err
}
// base64 编码(encoded)
base64str := base64.StdEncoding.EncodeToString(cipherBytes)
return base64str, nil
}
// 封装字符串对称解密
func SCDecryptString(cipherText, key, scType string) (string, error) {
// base64 解码(decode)
cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText)
cipherBytes, err := SCDecrypt(cipherBytes, []byte(key), scType)
if err != nil {
return "", err
}
return string(cipherBytes), nil
}
五、完整代码
-
DES密钥占8字节
-
3DES密钥占24字节
-
AES密钥。key长度:16,24,32 bytes 对应 AES-128,AES-192,AES-256
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"encoding/base64"
"fmt"
)
func main() {
// DES密钥
key := "12345678" // 占8字节
// 3DES密钥
// key = "abcdefgh012345678" // 占24字节
// AES密钥。key长度:16,24,32 bytes 对应 AES-128,AES-192,AES-256
// key = "01234567abcdefgh" // 占16字节
keyBytes := []byte(key)
str := "a"
cipherArr, err := SCEncrypt([]byte(str), keyBytes, "des")
if err != nil {
panic(err)
}
fmt.Printf("加密后的字节数组:%v\n", cipherArr)
fmt.Printf("加密后的字节数组:%x\n", cipherArr)
originalArr, _ := SCDecrypt(cipherArr, keyBytes, "des")
fmt.Println(string(originalArr))
fmt.Println("------------------------------------------------------")
str = "字符串加密aa12"
cipherText, _ := SCEncryptString(str, key, "des")
fmt.Println(cipherText)
originalText, _ := SCDecryptString(cipherText, key, "des")
fmt.Println(originalText)
}
// 对称加密(Symmetric Cryptography)
func SCEncrypt(originalBytes, key []byte, scType string) ([]byte, error) {
// 1、实例化密码器block(参数为密钥)
var err error
var block cipher.Block
switch scType {
case "des":
block, err = des.NewCipher(key)
case "3des":
block, err = des.NewTripleDESCipher(key)
case "aes":
block, err = aes.NewCipher(key)
}
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、对明文进行填充(参数为原始字节切片和密码对象的区块个数)
paddingBytes := PKCS5Padding(originalBytes, blockSize)
// 3、实例化加密模式(参数为密码对象和密钥)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
// 4、对填充字节后的明文进行加密(参数为加密字节切片和填充字节切片)
cipherBytes := make([]byte, len(paddingBytes))
blockMode.CryptBlocks(cipherBytes, paddingBytes)
return cipherBytes, nil
}
// 对称解密
func SCDecrypt(cipherBytes, key []byte, scType string) ([]byte, error) {
// 1、实例化密码器block(参数为密钥)
var err error
var block cipher.Block
switch scType {
case "des":
block, err = des.NewCipher(key)
case "3des":
block, err = des.NewTripleDESCipher(key)
case "aes":
block, err = aes.NewCipher(key)
}
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、实例化解密模式(参数为密码对象和密钥)
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
// 3、对密文进行解密(参数为填充字节切片和加密字节切片)
paddingBytes := make([]byte, len(cipherBytes))
blockMode.CryptBlocks(paddingBytes, cipherBytes)
// 4、去除填充的字节(参数为填充切片)
originalBytes := PKCS5UnPadding(paddingBytes)
return originalBytes, nil
}
// 封装字符串对称加密
func SCEncryptString(originalText, key, scType string) (string, error) {
cipherBytes, err := SCEncrypt([]byte(originalText), []byte(key), scType)
if err != nil {
return "", err
}
// base64 编码(encoded)
base64str := base64.StdEncoding.EncodeToString(cipherBytes)
return base64str, nil
}
// 封装字符串对称解密
func SCDecryptString(cipherText, key, scType string) (string, error) {
// base64 解码(decode)
cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText)
cipherBytes, err := SCDecrypt(cipherBytes, []byte(key), scType)
if err != nil {
return "", err
}
return string(cipherBytes), nil
}
// 末尾填充字节
func PKCS5Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize // 要填充的值和个数
slice1 := []byte{byte(padding)} // 要填充的单个二进制值
slice2 := bytes.Repeat(slice1, padding) // 要填充的二进制数组
return append(data, slice2...) // 填充到数据末端
}
// 末尾填充0
func ZerosPadding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize // 要填充的个数
slice1 := []byte{0} // 要填充的单个0数据
slice2 := bytes.Repeat(slice1, padding) // 要填充的0二进制数组
return append(data, slice2...) // 填充到数据末端
}
// 去除填充的字节
func PKCS5UnPadding(data []byte) []byte {
unpadding := data[len(data)-1] // 获取二进制数组最后一个数值
result := data[:(len(data) - int(unpadding))] // 截取开始至总长度减去填充值之间的有效数据
return result
}
// 去除填充的0
func ZerosUnPadding(data []byte) []byte {
return bytes.TrimRightFunc(data, func(r rune) bool { // 去除满足条件的子切片
return r == 0
})
}
到了这里,关于go语言对称加密使用(DES、3DES、AES)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!