江湖“密”事——对称加密
Posted BlockchainGo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了江湖“密”事——对称加密相关的知识,希望对你有一定的参考价值。
对称加密,即对一组数据采用相同的密钥进行加密和解密。常用的对称加密有DES、3DES、AES,下面分别来实现(实际使用注意加如err处理)。
DES对称加密,密钥长度必须为8字节,CBC模式
package mainimport (
"crypto/des"
"bytes"
"crypto/cipher"
"fmt"
)
//DES
func main() {
//原文数据
data:=[]byte("hello world")
//密钥,8位
key:=[]byte("12345678")
//调用DES加密获取加密后数据
encryptoData := DesEncrypto(data, key)
//对加密数据进行DES解密获取原文
originData := DesDecrypto(encryptoData, key)
//验证是否成功解密出原文
fmt.Println(string(originData))
}
//DES加密
func DesEncrypto(data,key []byte) []byte{
//获取密钥块
block, _ := des.NewCipher(key)
//设置加密方式(CBC模式),获取加密器
encrypter := cipher.NewCBCEncrypter(block, key)
//填充补码
paddingData := PKCS5Padding(data, block.BlockSize())
//创建填充后的明文长度的字节数组
bs := make([]byte, len(paddingData))
encrypter.CryptBlocks(bs,paddingData) return bs
}
//补码
func PKCS5Padding(data []byte,blockSize int)[]byte {
dataLen := len(data)
//补多少位数
padding:=blockSize-dataLen%blockSize
//补x位,就得到x个元素的切片[x,x,x...]
paddingBytes:=bytes.Repeat([]byte{byte(padding)},padding)
return append(data,paddingBytes...)
}
//DES解密
func DesDecrypto(data,key []byte)[]byte {
block, _ := des.NewCipher(key)
//设置解密方式(5种选1种),获取解密器
decrypter := cipher.NewCBCDecrypter(block, key)
bs := make([]byte, len(data))
decrypter.CryptBlocks(bs,data)
//去除补码
bs=PKCS5Unpadding(bs) return bs
}
//去补码
func PKCS5Unpadding(data []byte)[]byte {
length := len(data)
lastByte := int(data[length-1]) return data[:(length-lastByte)]
}
3DES对称加密,密钥长度必须为24字节,CBC模式
package mainimport (
"bytes"
"crypto/des"
"crypto/cipher"
"fmt"
)
func main() {
//明文数据
data:=[]byte("hello world")
//声明密钥,24位
key:=[]byte("123456781234567812345678")
encryptoData := TripleDesEncrypto(data, key)
originData := TripleDesDecrypto(encryptoData, key)
fmt.Println(string(originData))
}
//3DES加密
func TripleDesEncrypto(data, key []byte) []byte {
block, _ := des.NewTripleDESCipher(key)
//设置加密模式(CBC模式),获取加密器
encrypter := cipher.NewCBCEncrypter(block, key[:8])
//填充补码
paddingData := DES3PKCS5Padding(data, block.BlockSize())
//创建填充后的数据长度的数组
bs := make([]byte, len(paddingData))
encrypter.CryptBlocks(bs,paddingData)
return bs
}
//填充补码
func DES3PKCS5Padding(data []byte, blocksize int) []byte {
len := len(data)
paddingLen:=blocksize-len%blocksize
repeat := bytes.Repeat([]byte{byte(paddingLen)}, paddingLen)
return append(data,repeat...)
}
//3DES解密
func TripleDesDecrypto(data, key []byte) []byte {
block, _ := des.NewTripleDESCipher(key)
//设置解密模式(CBC),获取解密器
decrypter := cipher.NewCBCDecrypter(block, key[:8])
//创建密文数组
bs := make([]byte, len(data))
decrypter.CryptBlocks(bs,data)
//去补码
unPadding := DES3PKCS5Unpadding(bs)
return unPadding
}
//去补码
func DES3PKCS5Unpadding(data []byte)[]byte {
dataLen := len(data)
last:=data[dataLen-1]
return data[:dataLen-int(last)]
}
AES对称加密,密钥长度可以取8、24、32字节
由于DES和3DES破解难度不足,所以DES、3DES几乎完全被AES取代,所以一般
直接使用AES即可。
package mainimport (
"bytes"
"crypto/aes"
"crypto/cipher"
"fmt"
)
func main() {
data := []byte("abcde")
//密钥超度8、24、32位皆可
key:=[]byte("12345678abcdefgh")
encryptoData := AesEncrypto(data,key)
originData := AesDecrypto(encryptoData, key)
fmt.Println(string(originData))
}
//加密
func AesEncrypto(data, key []byte) []byte {
//获取秘钥块
block, _ := aes.NewCipher(key)
blockSize := block.BlockSize()
//获取加密器
encrypter := cipher.NewCBCEncrypter(block, key[:blockSize])
//填充补码
paddingData := PKCS7Padding(data, blockSize)
bs := make([]byte, len(paddingData))
//加密
encrypter.CryptBlocks(bs,paddingData)
return bs
}
//补码
func PKCS7Padding(data []byte,blocksize int)[]byte {
length := len(data)
paddingLen:=blocksize-length%blocksize
paddingBytes := bytes.Repeat([]byte{byte(paddingLen)}, paddingLen)
return append(data,paddingBytes...)
}
//解密
func AesDecrypto(data, key []byte) []byte {
block, _ := aes.NewCipher(key)
blockSize := block.BlockSize()
decrypter := cipher.NewCBCDecrypter(block, key[:blockSize])
bs := make([]byte, len(data))
//先解密
decrypter.CryptBlocks(bs,data)
//再去补码
unPaddingData := PKCS7UnPadding(bs)
return unPaddingData
}
//去补码
func PKCS7UnPadding(data []byte) []byte {
length := len(data)
lastByte := int(data[length-1])
return data[:length-lastByte]
}
AES加密,CFB模式
package mainimport (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"io"
"fmt"
)
//通过CFB模式,进行AES加密func main() {
data := []byte("abcd")
key:=[]byte("123456789abcdefg")
var encryptocode = AesEncrypto(data,key)
var decryptocode = AesDecrypto(encryptocode, key)
fmt.Print(string(decryptocode))
}
//加密
func AesEncrypto(data,key []byte) []byte {
//分组秘钥
block, _ := aes.NewCipher(key)
//创建数组
bs := make([]byte, aes.BlockSize+len(data))
//设置内存空间可读
bytes := bs[:aes.BlockSize]
io.ReadFull(rand.Reader, bytes)
//设置加密模式
encrypter := cipher.NewCFBEncrypter(block, bytes)
//加密
encrypter.XORKeyStream(bs[aes.BlockSize:], data)
return bs
}
//解密
func AesDecrypto(data []byte, key []byte) []byte {
block, _ := aes.NewCipher(key)
bytes := data[:aes.BlockSize]
data = data[aes.BlockSize:]
//设置解密方式
stream := cipher.NewCFBDecrypter(block, bytes)
//解密
stream.XORKeyStream(data, data) return data
}
AES加密,OFB模式
package mainimport (
"io"
"crypto/cipher"
"crypto/aes"
"crypto/rand"
"fmt"
)
func main() {
data:=[]byte("hello world")
key := []byte("6368616e676520746869732070617374")
// 加密
result, _ := AesEncrypt(data, key)
// 解密
originData, _ := AesDecrypt(result, key)
fmt.Println(string(originData))
}
// 加密函数
func AesEncrypt(data, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
ciphertext := make([]byte, aes.BlockSize+len(data))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv);
err != nil {
panic(err)
}
// NewOFB返回一个在输出反馈模式下使用分组密码b进行加密或解密的Stream。初始化矢量iv的长度必须等于b的块大小。
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], data)
return ciphertext, nil
}
// 解密函数
func AesDecrypt(ciphertext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
iv := ciphertext[:aes.BlockSize]
if len(ciphertext) < aes.BlockSize {
panic("ciphertext too short")
}
plaintext2 := make([]byte, len(ciphertext))
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
return plaintext2, nil
}
AES加密,CTR模式
package mainimport (
"io"
"crypto/cipher"
"crypto/aes"
"crypto/rand"
"fmt"
)
func main() {
key := []byte("6368616e676520746869732070617374")
data:=[]byte("hello world")
// 加密
result, _ := AesEncrypt(data, key)
// 解密
origData, _ := AesDecrypt(result, key)
fmt.Println(string(origData))
}
// 加密函数
func AesEncrypt(plaintext, key []byte) ([]byte, error) {
// 申明初始化获取一个新的密钥块。关键参数应该是AES密钥,16,24或32个字节来选择AES-128,AES-192或AES-256。
block, err := aes.NewCipher(key) if err != nil {
return nil, err
}
// 切片处理申明初始化一个较大长度的新字符串变量
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
// 申明初始化,同时调用加密函数得到流接口
stream := cipher.NewCTR(block, iv)
// 流处理
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
return ciphertext, nil
}
// 解密函数func AesDecrypt(ciphertext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
iv := ciphertext[:aes.BlockSize]
if len(ciphertext) < aes.BlockSize {
panic("ciphertext too short")
}
plaintext2 := make([]byte, len(ciphertext))
// 申明初始化,同时调用加密函数得到流接口
stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
return plaintext2, nil
}
以上是关于江湖“密”事——对称加密的主要内容,如果未能解决你的问题,请参考以下文章