diff --git a/README.md b/README.md index 30ac54e..66e2d3a 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ Golang 中可以使用的常用辅助功能工具箱。主要配备以下功能 - 加解密算法 - [ ] 螺旋随机密钥自解密算法 - - [ ] AES-CBC 便捷加解密算法 - - [ ] No Padding - - [ ] ZerosPadding - - [ ] Pkcs7Padding + - [x] AES-CBC 便捷加解密算法 + - [x] No Padding + - [x] ZerosPadding + - [x] Pkcs7Padding - [ ] DES-CBC 便捷加解密算法 - [ ] No Padding - [ ] ZerosPadding diff --git a/encryption/aes/aes.go b/encryption/aes/aes.go new file mode 100644 index 0000000..29f2425 --- /dev/null +++ b/encryption/aes/aes.go @@ -0,0 +1,66 @@ +// 提供AES-CBC-256加密解密功能。 +package aes + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/sha256" + + "archgrid.xyz/ag/toolsbox/encryption" +) + +type IVGenerator func([32]byte) [16]byte + +// 截取给定密钥的前16字节作为IV。 +func PrefixIVGenerator(key [32]byte) [16]byte { + return ([16]byte)(key[:16]) +} + +// 对给定的密钥进行异或运算获取IV。 +func XorIVGenerator(key [32]byte) [16]byte { + var iv [16]byte + for i := 0; i < 16; i++ { + iv[i] = key[i] ^ key[i+16] + } + return iv +} + +// 对给定的密钥进行Sha256哈希运算获取用于加密算法的32字节密钥。 +func generateKey(key []byte) [32]byte { + return sha256.Sum256(key) +} + +// 对给定的数据进行AES加密。 +// 参数padding指定了填充方式,可选值为NoPadding、ZeroPadding和PKCS7Padding,默认采用ZeroPadding。 +func Encrypt(data []byte, key []byte, padding encryption.PaddingMode, ivGenerator ...IVGenerator) ([]byte, error) { + keyBytes := generateKey(key) + block, err := aes.NewCipher(keyBytes[:]) + if err != nil { + return nil, err + } + iv := append(ivGenerator, XorIVGenerator)[0](keyBytes) + plainText := encryption.Padding(data, block.BlockSize(), padding) + + cipherText := make([]byte, len(plainText)) + mode := cipher.NewCBCEncrypter(block, iv[:]) + mode.CryptBlocks(cipherText, plainText) + + return cipherText, nil +} + +// 对给定的数据进行AES解密。 +// 参数padding指定了填充方式,可选值为NoPadding、ZeroPadding和PKCS7Padding,默认采用ZeroPadding。 +func Decrypt(data []byte, key []byte, padding encryption.PaddingMode, ivGenerator ...IVGenerator) ([]byte, error) { + keyBytes := generateKey(key) + block, err := aes.NewCipher(keyBytes[:]) + if err != nil { + return nil, err + } + iv := append(ivGenerator, XorIVGenerator)[0](keyBytes) + + plainText := make([]byte, len(data)) + mode := cipher.NewCBCDecrypter(block, iv[:]) + mode.CryptBlocks(plainText, data) + + return encryption.Unpadding(plainText, padding), nil +} diff --git a/encryption/padding.go b/encryption/padding.go index ba89c72..e09c4a5 100644 --- a/encryption/padding.go +++ b/encryption/padding.go @@ -2,14 +2,16 @@ package encryption import "bytes" +type PaddingMode int + const ( - NoPadding = iota + NoPadding PaddingMode = iota ZeroPadding PKCS7Padding ) // 对给定的数据进行填充,默认采用填充零的方式(ZeroPadding),也可以采用填充PKCS#7的方式(PKCS7Padding)或者不填充(NoPadding)。 -func Padding(data []byte, blockSize int, padding ...int) []byte { +func Padding(data []byte, blockSize int, padding ...PaddingMode) []byte { paddingMethod := append(padding, ZeroPadding)[0] n := blockSize - len(data)%blockSize switch paddingMethod { @@ -29,7 +31,7 @@ func Padding(data []byte, blockSize int, padding ...int) []byte { } // 对给定的数据进行去填充,默认采用去填充零的方式(对应ZeroPadding),也可以采用去填充PKCS#7的方式(对应PKCS7Padding)或者不填充(对应NoPadding)。 -func Unpadding(data []byte, padding ...int) []byte { +func Unpadding(data []byte, padding ...PaddingMode) []byte { paddingMethod := append(padding, ZeroPadding)[0] switch paddingMethod { case PKCS7Padding: