diff --git a/README.md b/README.md index 66e2d3a..ecf3cde 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ Golang 中可以使用的常用辅助功能工具箱。主要配备以下功能 - [x] No Padding - [x] ZerosPadding - [x] Pkcs7Padding - - [ ] DES-CBC 便捷加解密算法 - - [ ] No Padding - - [ ] ZerosPadding - - [ ] Pkcs7Padding + - [x] DES-CBC 便捷加解密算法 + - [x] No Padding + - [x] ZerosPadding + - [x] Pkcs7Padding - [ ] 3DES-CBC 便捷加解密算法 - [ ] No Padding - [ ] ZerosPadding diff --git a/encryption/des/des.go b/encryption/des/des.go new file mode 100644 index 0000000..6dbaf60 --- /dev/null +++ b/encryption/des/des.go @@ -0,0 +1,67 @@ +// 提供DES-CBC加密解密功能。 +package des + +import ( + "crypto/cipher" + "crypto/des" + "crypto/sha256" + + "archgrid.xyz/ag/toolsbox/encryption" +) + +type KeyGenerator func([]byte) [8]byte + +// 截取所提供的密钥进行Sha256散列以后的前8个字节作为加密密钥。 +func PrefixKeyGenerator(key []byte) [8]byte { + hashKey := sha256.Sum256(key) + return ([8]byte)(hashKey[:8]) +} + +// 对所提供的密钥进行Sha256散列后,将散列值的前8个字节连续与后几个单元中对应的字节进行异或运算,最终得到的长度为8个字节的字节数组作为加密密钥。 +func XorKeyGenerator(key []byte) [8]byte { + hashKey := sha256.Sum256(key) + var compressedKey [8]byte + for i := 0; i < 8; i++ { + for j := 0; j < 4; j++ { + compressedKey[i] ^= hashKey[i+j*8] + } + } + return compressedKey +} + +// 对给定的数据进行加密。 +// DES加密IV为8字节,默认与运算后的密钥相同。 +// 参数padding指定了填充方式,可选值为NoPadding、ZeroPadding和PKCS7Padding,默认采用ZeroPadding。 +func Encrypt(data []byte, key []byte, padding encryption.PaddingMode, keyGenerator ...KeyGenerator) ([]byte, error) { + keyBytes := append(keyGenerator, XorKeyGenerator)[0](key) + block, err := des.NewCipher(keyBytes[:]) + if err != nil { + return nil, err + } + + iv := keyBytes[:] + cipherText := make([]byte, len(data)) + plainText := encryption.Padding(data, block.BlockSize(), padding) + mode := cipher.NewCBCEncrypter(block, iv) + mode.CryptBlocks(cipherText, plainText) + + return cipherText, nil +} + +// 对给定的数据进行解密。 +// DES解密IV为8字节,默认与运算后的密钥相同。 +// 参数padding指定了填充方式,可选值为NoPadding、ZeroPadding和PKCS7Padding,默认采用ZeroPadding。 +func Decrypt(data []byte, key []byte, padding encryption.PaddingMode, keyGenerator ...KeyGenerator) ([]byte, error) { + keyBytes := append(keyGenerator, XorKeyGenerator)[0](key) + block, err := des.NewCipher(keyBytes[:]) + if err != nil { + return nil, err + } + + iv := keyBytes[:] + plainText := make([]byte, len(data)) + mode := cipher.NewCBCDecrypter(block, iv) + mode.CryptBlocks(plainText, data) + + return encryption.Unpadding(plainText, padding), nil +}