加密
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

230 lines
5.0 KiB

// 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)]
}