// DES、3DES加解密示例,
|
|
package crypter
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/cipher"
|
|
"crypto/des"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"errors"
|
|
"log"
|
|
"strings"
|
|
)
|
|
|
|
const KEYS = "gfe023u_sefiel#fi32lf3z!" //必须24位
|
|
/**
|
|
* 加密并转换为base64字符串
|
|
*/
|
|
func DesEncrypt(args ...string) (string, error) { //origData, key []byte
|
|
|
|
code, keyorg, err := getArgs(args)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
key := keyorg[0:8]
|
|
|
|
block, err := des.NewCipher(key)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
origData := []byte(code)
|
|
origData = PKCS5Padding(origData, block.BlockSize())
|
|
blockMode := cipher.NewCBCEncrypter(block, key)
|
|
crypted := make([]byte, len(origData))
|
|
// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
|
|
// crypted := origData
|
|
blockMode.CryptBlocks(crypted, origData)
|
|
|
|
encode := base64.StdEncoding.EncodeToString(crypted)
|
|
return encode, nil
|
|
}
|
|
|
|
/**
|
|
* 加密并转换为16进制字符串
|
|
*/
|
|
func DesEn(code, key string) string {
|
|
|
|
block, err := des.NewCipher([]byte(key))
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
origData := []byte(code)
|
|
|
|
origData = PKCS5Padding(origData, block.BlockSize())
|
|
blockMode := cipher.NewCBCEncrypter(block, []byte(key))
|
|
crypted := make([]byte, len(origData))
|
|
// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
|
|
// crypted := origData
|
|
blockMode.CryptBlocks(crypted, origData)
|
|
|
|
return strings.ToUpper(hex.EncodeToString(crypted))
|
|
}
|
|
|
|
/**
|
|
* 解密已转为base64字符串有DES加密
|
|
*/
|
|
func DesDecrypt(args ...string) (string, error) {
|
|
|
|
decode, keyorg, err := getArgs(args)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
key := keyorg[0:8]
|
|
crypted, err := base64.StdEncoding.DecodeString(decode)
|
|
block, err := des.NewCipher([]byte(key))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
blockMode := cipher.NewCBCDecrypter(block, key)
|
|
|
|
if len(crypted)%blockMode.BlockSize() != 0 {
|
|
return "", errors.New("error,input not full blocks")
|
|
}
|
|
origData := make([]byte, len(crypted))
|
|
blockMode.CryptBlocks(origData, crypted)
|
|
origData = PKCS5UnPadding(origData)
|
|
return string(origData), nil
|
|
}
|
|
|
|
/**
|
|
* 解密已转为16进制字符串有DES加密
|
|
*/
|
|
func DesDe(code, key string) string {
|
|
|
|
crypted, err := hex.DecodeString(code)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
block, err := des.NewCipher([]byte(key))
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
blockMode := cipher.NewCBCDecrypter(block, []byte(key))
|
|
|
|
if len(crypted)%blockMode.BlockSize() != 0 {
|
|
return ""
|
|
}
|
|
origData := make([]byte, len(crypted))
|
|
blockMode.CryptBlocks(origData, crypted)
|
|
origData = PKCS5UnPadding(origData)
|
|
return string(origData)
|
|
}
|
|
|
|
// 3DES加密, 可与php MCRYPT_3DES加密方式对应
|
|
func TripleDesEncrypt(args ...string) (string, error) {
|
|
|
|
code, key, err := getArgs(args)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if code == "" {
|
|
return "", errors.New("加密数据为空")
|
|
}
|
|
|
|
block, err := des.NewTripleDESCipher(key)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
origData := []byte(code)
|
|
|
|
origData = PKCS5Padding(origData, block.BlockSize())
|
|
blockMode := cipher.NewCBCEncrypter(block, key[:8])
|
|
crypted := make([]byte, len(origData))
|
|
blockMode.CryptBlocks(crypted, origData)
|
|
|
|
encode := base64.StdEncoding.EncodeToString(crypted)
|
|
|
|
return encode, nil
|
|
}
|
|
|
|
// 3DES解密
|
|
func TripleDesDecrypt(args ...string) (string, error) {
|
|
|
|
decode, key, err := getArgs(args)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if decode == "" {
|
|
return "", errors.New("解密数据为空")
|
|
}
|
|
|
|
block, err := des.NewTripleDESCipher(key)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
crypted, decodeErr := base64.StdEncoding.DecodeString(decode)
|
|
|
|
if decodeErr != nil {
|
|
return "", decodeErr
|
|
}
|
|
|
|
blockMode := cipher.NewCBCDecrypter(block, key[:8])
|
|
origData := make([]byte, len(crypted))
|
|
|
|
if len(crypted)%blockMode.BlockSize() != 0 {
|
|
log.Println("ERROR", "TripleDesDecrypt: input not full blocks")
|
|
return "", errors.New("解密失败")
|
|
}
|
|
blockMode.CryptBlocks(origData, crypted)
|
|
origData = PKCS5UnPadding(origData)
|
|
|
|
return string(origData), nil
|
|
}
|
|
|
|
//获取参数
|
|
func getArgs(args []string) (string, []byte, error) {
|
|
if len(args) == 0 {
|
|
return "", nil, errors.New("参数不能为空")
|
|
}
|
|
|
|
origData := args[0]
|
|
|
|
var crypt_key string
|
|
|
|
if len(args) == 2 {
|
|
crypt_key = args[1]
|
|
} else {
|
|
crypt_key = KEYS
|
|
}
|
|
|
|
key := []byte(crypt_key)
|
|
|
|
return origData, key, nil
|
|
}
|
|
|
|
func ZeroPadding(ciphertext []byte, blockSize int) []byte {
|
|
padding := blockSize - len(ciphertext)%blockSize
|
|
padtext := bytes.Repeat([]byte{0}, padding)
|
|
return append(ciphertext, padtext...)
|
|
}
|
|
|
|
func ZeroUnPadding(origData []byte) []byte {
|
|
return bytes.TrimRightFunc(origData, func(r rune) bool {
|
|
return r == rune(0)
|
|
})
|
|
}
|
|
|
|
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
|
|
padding := blockSize - len(ciphertext)%blockSize
|
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
return append(ciphertext, padtext...)
|
|
}
|
|
|
|
func PKCS5UnPadding(origData []byte) []byte {
|
|
length := len(origData)
|
|
// 去掉最后一个字节 unpadding 次
|
|
unpadding := int(origData[length-1])
|
|
if length < unpadding || unpadding/8 > 3 {
|
|
//解密的是错误的数据情况下,是没有填充的
|
|
return []byte("")
|
|
}
|
|
return origData[:(length - unpadding)]
|
|
}
|