84477401f3
some other updates
509 lines
17 KiB
Go
509 lines
17 KiB
Go
package crypto
|
||
|
||
import (
|
||
"apigo.cc/apigo/plugin"
|
||
"apigo.cc/apigo/plugins/crypto/crypt"
|
||
"crypto/md5"
|
||
"crypto/sha1"
|
||
"crypto/sha256"
|
||
"crypto/sha512"
|
||
"encoding/base64"
|
||
"encoding/hex"
|
||
"fmt"
|
||
"github.com/ZZMarquis/gm/sm3"
|
||
"github.com/ssgo/u"
|
||
"hash"
|
||
"sync"
|
||
)
|
||
|
||
var gmCrypto = &crypt.GMCrypt{}
|
||
var cmCrypto = &crypt.CMCrypt{}
|
||
var defaultCrypto crypt.Crypt = cmCrypto
|
||
var defaultCryptoLock = sync.RWMutex{}
|
||
var configKeys = map[string][][]byte{}
|
||
var configKeysLock = sync.RWMutex{}
|
||
|
||
func init() {
|
||
plugin.Register(plugin.Plugin{
|
||
Id: "apigo.cc/apigo/plugins/crypto",
|
||
Name: "加密算法",
|
||
ConfigSample: `mode: cm # 指定默认算法集,cm-通用算法(SHA256、AES、ECDSA),gm-国密算法(sm3、sm4、sm2)`,
|
||
Init: func(conf map[string]interface{}) {
|
||
defaultCryptoLock.Lock()
|
||
if conf["mode"] == "gm" {
|
||
defaultCrypto = &crypt.GMCrypt{}
|
||
} else {
|
||
defaultCrypto = &crypt.CMCrypt{}
|
||
}
|
||
defaultCryptoLock.Unlock()
|
||
}, Objects: map[string]interface{}{
|
||
"getConfigEnc": func(name string, ctx *plugin.Context) *AesWithKey {
|
||
if u.Bool(ctx.GetData("_gotConfigEnc" + name)) {
|
||
return nil
|
||
}
|
||
ctx.SetData("_gotConfigEnc"+name, true)
|
||
configKeysLock.RLock()
|
||
configKeyIv := configKeys[name]
|
||
configKeysLock.RUnlock()
|
||
if configKeyIv != nil && len(configKeyIv) == 2 {
|
||
return &AesWithKey{
|
||
crypto: defaultCrypto,
|
||
key: configKeyIv[0],
|
||
iv: configKeyIv[1],
|
||
}
|
||
}
|
||
return nil
|
||
},
|
||
"setConfigEnc": func(name string, key, iv []byte) {
|
||
if name != "" && key != nil && iv != nil {
|
||
configKeysLock.Lock()
|
||
configKeys[name] = [][]byte{key, iv}
|
||
configKeysLock.Unlock()
|
||
}
|
||
},
|
||
"removeConfigEnc": func(name string) {
|
||
if name != "" {
|
||
configKeysLock.Lock()
|
||
delete(configKeys, name)
|
||
configKeysLock.Unlock()
|
||
}
|
||
},
|
||
// base64 Base64编码
|
||
"base64": map[string]interface{}{
|
||
// encode 将字符串编码
|
||
// encode data 用于编码的数据,string类型
|
||
// encode return 编码后的结果
|
||
"encode": func(data string) string {
|
||
return base64.StdEncoding.EncodeToString([]byte(data))
|
||
},
|
||
// encodeBytes 将二进制数据编码
|
||
// encodeBytes data 用于编码的数据,二进制的字节数组
|
||
// encodeBytes return 编码后的结果
|
||
"encodeBytes": func(data []byte) string {
|
||
return base64.StdEncoding.EncodeToString(data)
|
||
},
|
||
// decode 解码为字符串,如果发生错误将抛出异常
|
||
// decode data 编码后的结果
|
||
// decode return 解码后的数据,string类型
|
||
"decode": func(data string) (string, error) {
|
||
return makeStringResult(base64.StdEncoding.DecodeString(data))
|
||
},
|
||
// decodeBytes 解码为二进制数据,如果发生错误将抛出异常
|
||
// decodeBytes data 编码后的结果
|
||
// decodeBytes return 解码后的数据,二进制的字节数组
|
||
"decodeBytes": func(data string) ([]byte, error) {
|
||
return base64.StdEncoding.DecodeString(data)
|
||
},
|
||
},
|
||
// urlBase64 Base64编码(兼容URL)
|
||
"urlBase64": map[string]interface{}{
|
||
"encode": func(data string) string {
|
||
return base64.URLEncoding.EncodeToString([]byte(data))
|
||
},
|
||
"encodeBytes": func(data []byte) string {
|
||
return base64.URLEncoding.EncodeToString(data)
|
||
},
|
||
"decode": func(data string) (string, error) {
|
||
return makeStringResult(base64.URLEncoding.DecodeString(data))
|
||
},
|
||
"decodeBytes": func(data string) ([]byte, error) {
|
||
return base64.URLEncoding.DecodeString(data)
|
||
},
|
||
},
|
||
// hex hex编码
|
||
"hex": map[string]interface{}{
|
||
"encode": func(data string) string {
|
||
return hex.EncodeToString([]byte(data))
|
||
},
|
||
"encodeBytes": func(data []byte) string {
|
||
return hex.EncodeToString(data)
|
||
},
|
||
"decode": func(data string) (string, error) {
|
||
return makeStringResult(hex.DecodeString(data))
|
||
},
|
||
"decodeBytes": func(data string) ([]byte, error) {
|
||
return hex.DecodeString(data)
|
||
},
|
||
},
|
||
// newMD5 创建MD5对象
|
||
// newMD5 return MD5对象
|
||
"newMD5": func() *Hash {
|
||
return &Hash{hash: md5.New()}
|
||
},
|
||
// md5 将字符串进行MD5编码
|
||
// md5 data 用于编码的数据,string类型
|
||
// md5 return 编码后的结果,16进制字符串
|
||
"md5": func(data string) string {
|
||
return hex.EncodeToString(makeHash(md5.New(), []byte(data)))
|
||
},
|
||
// md5 将二进制数据进行MD5编码
|
||
// md5 data 用于编码的数据,用于编码的数据,二进制的字节数组
|
||
// md5 return 编码后的结果,二进制的字节数组,如果需要转换为字符串可以使用hex.encode或者base64.encode等编码工具进行编码
|
||
"md5Bytes": func(data []byte) []byte {
|
||
return makeHash(md5.New(), data)
|
||
},
|
||
|
||
// newSHA1 创建SHA1对象
|
||
// newSHA1 return SHA1对象
|
||
"newSHA1": func() *Hash {
|
||
return &Hash{hash: sha1.New()}
|
||
},
|
||
// sha1 将字符串进行SHA1编码
|
||
// sha1 data 用于编码的数据,string类型
|
||
// sha1 return 编码后的结果,16进制字符串
|
||
"sha1": func(data string) string {
|
||
return hex.EncodeToString(makeHash(sha1.New(), []byte(data)))
|
||
},
|
||
// sha1Bytes 将二进制数据进行SHA1编码
|
||
// sha1Bytes data 用于编码的数据,用于编码的数据,二进制的字节数组
|
||
// sha1Bytes return 编码后的结果,二进制的字节数组,如果需要转换为字符串可以使用hex.encode或者base64.encode等编码工具进行编码
|
||
"sha1Bytes": func(data []byte) []byte {
|
||
return makeHash(sha1.New(), data)
|
||
},
|
||
// newSHA256 创建SHA256对象
|
||
// newSHA256 return SHA256对象
|
||
"newSHA256": func() *Hash {
|
||
return &Hash{hash: sha256.New()}
|
||
},
|
||
// sha256 将字符串进行SHA256编码
|
||
// sha256 data 用于编码的数据,string类型
|
||
// sha256 return 编码后的结果,16进制字符串
|
||
"sha256": func(data string) string {
|
||
return hex.EncodeToString(makeHash(sha256.New(), []byte(data)))
|
||
},
|
||
// sha256Bytes 将二进制数据进行SHA256编码
|
||
// sha256Bytes data 用于编码的数据,用于编码的数据,二进制的字节数组
|
||
// sha256Bytes return 编码后的结果,二进制的字节数组,如果需要转换为字符串可以使用hex.encode或者base64.encode等编码工具进行编码
|
||
"sha256Bytes": func(data []byte) []byte {
|
||
return makeHash(sha256.New(), data)
|
||
},
|
||
// newSHA512 创建SHA512对象
|
||
// newSHA512 return SHA512对象
|
||
"newSHA512": func() *Hash {
|
||
return &Hash{hash: sha512.New()}
|
||
},
|
||
// sha512 将字符串进行SHA512编码
|
||
// sha512 data 用于编码的数据,string类型
|
||
// sha512 return 编码后的结果,16进制字符串
|
||
"sha512": func(data string) string {
|
||
return hex.EncodeToString(makeHash(sha512.New(), []byte(data)))
|
||
},
|
||
// sha512Bytes 将二进制数据进行SHA512编码
|
||
// sha512Bytes data 用于编码的数据,用于编码的数据,二进制的字节数组
|
||
// sha512Bytes return 编码后的结果,二进制的字节数组,如果需要转换为字符串可以使用hex.encode或者base64.encode等编码工具进行编码
|
||
"sha512Bytes": func(data []byte) []byte {
|
||
return makeHash(sha512.New(), data)
|
||
},
|
||
// newSM3 创建SM3对象
|
||
// newSM3 return SM3对象
|
||
"newSM3": func() *Hash {
|
||
return &Hash{hash: sm3.New()}
|
||
},
|
||
// sm3 将字符串进行SM3编码
|
||
// sm3 data 用于编码的数据,string类型
|
||
// sm3 return 编码后的结果,16进制字符串
|
||
"sm3": func(data string) string {
|
||
return hex.EncodeToString(makeHash(sm3.New(), []byte(data)))
|
||
},
|
||
// sm3Bytes 将二进制数据进行SM3编码
|
||
// sm3Bytes data 用于编码的数据,用于编码的数据,二进制的字节数组
|
||
// sm3Bytes return 编码后的结果,二进制的字节数组,如果需要转换为字符串可以使用hex.encode或者base64.encode等编码工具进行编码
|
||
"sm3Bytes": func(data []byte) []byte {
|
||
return makeHash(sm3.New(), data)
|
||
},
|
||
// newHash 创建Hash对象(根据配置使用SHA256或SM3,默认为SHA256)
|
||
// newHash return Hash对象
|
||
"newHash": func() *Hash {
|
||
return &Hash{hash: defaultCrypto.NewHash()}
|
||
},
|
||
// hash 将字符串进行Hash编码(根据配置使用SHA256或SM3,默认为SHA256)
|
||
// hash data 用于编码的数据,string类型
|
||
// hash return 编码后的结果,16进制字符串
|
||
"hash": func(data string) string {
|
||
return hex.EncodeToString(makeHash(defaultCrypto.NewHash(), []byte(data)))
|
||
},
|
||
// hashBytes 将二进制数据进行Hash编码(根据配置使用SHA256或SM3,默认为SHA256)
|
||
// hashBytes data 用于编码的数据,用于编码的数据,二进制的字节数组
|
||
// hashBytes return 编码后的结果,二进制的字节数组,如果需要转换为字符串可以使用hex.encode或者base64.encode等编码工具进行编码
|
||
"hashBytes": func(data []byte) []byte {
|
||
return makeHash(defaultCrypto.NewHash(), data)
|
||
},
|
||
// aes 使用AES算法(CBC)进行加解密
|
||
"aes": &Aes{crypto: cmCrypto},
|
||
// sm4 使用SM4算法进行加解密
|
||
"sm4": &Aes{crypto: gmCrypto},
|
||
// symmetric 根据配置使用使用AES或SM4算法进行加解密(默认为AES)
|
||
"symmetric": &Aes{crypto: defaultCrypto},
|
||
// ecdsa 使用ECDSA算法进行签名或加解密
|
||
"ecdsa": &Ecdsa{crypto: cmCrypto},
|
||
// sm2 使用SM2算法进行签名或加解密
|
||
"sm2": &Ecdsa{crypto: gmCrypto},
|
||
// asymmetric 根据配置使用使用ECDSA或SM2算法进行加解密(默认为ECDSA)
|
||
"asymmetric": &Ecdsa{crypto: defaultCrypto},
|
||
},
|
||
})
|
||
}
|
||
|
||
func SetConfigEnc(name string, key, iv []byte) {
|
||
if name != "" && key != nil && iv != nil {
|
||
configKeysLock.Lock()
|
||
configKeys[name] = [][]byte{key, iv}
|
||
configKeysLock.Unlock()
|
||
}
|
||
}
|
||
|
||
type Hash struct {
|
||
hash hash.Hash
|
||
}
|
||
|
||
// Add 添加数据到Hash
|
||
// Add data 字符串格式的数据
|
||
// Add return Hash对象,方便串联操作
|
||
func (hash *Hash) Add(data string) *Hash {
|
||
hash.hash.Write([]byte(data))
|
||
return hash
|
||
}
|
||
|
||
// AddHex 添加Hex编码的数据到Hash
|
||
// AddHex data Hex编码的二进制数据
|
||
// AddHex return Hash对象,方便串联操作
|
||
func (hash *Hash) AddHex(data string) *Hash {
|
||
hash.hash.Write([]byte(data))
|
||
return hash
|
||
}
|
||
|
||
// AddBytes 添加二进制数据到Hash
|
||
// AddBytes data 二进制数据
|
||
// AddBytes return Hash对象,方便串联操作
|
||
func (hash *Hash) AddBytes(p []byte) *Hash {
|
||
hash.hash.Write(p)
|
||
return hash
|
||
}
|
||
|
||
// Make 生成Hash
|
||
// Make return Hex编码的结果
|
||
func (hash *Hash) Make() string {
|
||
return hex.EncodeToString(hash.MakeBytes())
|
||
}
|
||
|
||
// MakeBytes 生成Hash
|
||
// MakeBytes return 二进制结果
|
||
func (hash *Hash) MakeBytes() []byte {
|
||
return hash.hash.Sum(nil)
|
||
}
|
||
|
||
type Aes struct {
|
||
crypto crypt.Crypt
|
||
}
|
||
|
||
// Encrypt 将字符串加密
|
||
// Encrypt data 用于加密的数据,string类型
|
||
// Encrypt key hex编码的16位或32位密钥
|
||
// Encrypt iv hex编码的16位或32位向量
|
||
// Encrypt return 返回hex编码的加密结果
|
||
func (ae *Aes) Encrypt(data, key, iv string) (string, error) {
|
||
if keyD, err1 := hex.DecodeString(key); err1 == nil {
|
||
if ivD, err2 := hex.DecodeString(iv); err2 == nil {
|
||
return makeHexStringResult(ae.crypto.Encrypt([]byte(data), keyD, ivD))
|
||
} else {
|
||
return "", err2
|
||
}
|
||
} else {
|
||
return "", err1
|
||
}
|
||
}
|
||
|
||
// EncryptBytes 将二进制数据加密
|
||
// EncryptBytes data 用于加密的数据,二进制的字节数组
|
||
// EncryptBytes key 二进制的16位或32位密钥
|
||
// EncryptBytes iv 二进制的16位或32位向量
|
||
// EncryptBytes return 返回二进制的加密结果
|
||
func (ae *Aes) EncryptBytes(data, key, iv []byte) ([]byte, error) {
|
||
return ae.crypto.Encrypt(data, key, iv)
|
||
}
|
||
|
||
// Decrypt 解密为字符串
|
||
// Decrypt data hex编码的加密后结果
|
||
// Decrypt key hex编码的16位或32位密钥
|
||
// Decrypt iv hex编码的16位或32位向量
|
||
// Decrypt return 解密后的数据,string类型
|
||
func (ae *Aes) Decrypt(data string, key, iv string) (string, error) {
|
||
if keyD, err1 := hex.DecodeString(key); err1 == nil {
|
||
if ivD, err2 := hex.DecodeString(iv); err2 == nil {
|
||
if dataD, err3 := hex.DecodeString(data); err3 == nil {
|
||
return makeStringResult(ae.crypto.Decrypt(dataD, keyD, ivD))
|
||
} else {
|
||
return "", err3
|
||
}
|
||
} else {
|
||
return "", err2
|
||
}
|
||
} else {
|
||
return "", err1
|
||
}
|
||
}
|
||
|
||
// DecryptBytes 解密为二进制数据
|
||
// DecryptBytes data 二进制的加密后结果
|
||
// DecryptBytes key 二进制的16位或32位密钥
|
||
// DecryptBytes iv 二进制的16位或32位向量
|
||
// DecryptBytes return 解密后的数据,二进制的字节数组
|
||
func (ae *Aes) DecryptBytes(data, key, iv []byte) ([]byte, error) {
|
||
return ae.crypto.Decrypt(data, key, iv)
|
||
}
|
||
|
||
type AesWithKey struct {
|
||
crypto crypt.Crypt
|
||
key []byte
|
||
iv []byte
|
||
}
|
||
|
||
// Encrypt 将字符串加密
|
||
// Encrypt data 用于加密的数据,string类型
|
||
// Encrypt return 返回hex编码的加密结果
|
||
func (ae *AesWithKey) Encrypt(data string) (string, error) {
|
||
fmt.Println(ae.crypto.Encrypt([]byte(data), ae.key, ae.iv))
|
||
return makeHexStringResult(ae.crypto.Encrypt([]byte(data), ae.key, ae.iv))
|
||
}
|
||
|
||
// EncryptBytes 将二进制数据加密
|
||
// EncryptBytes data 用于加密的数据,二进制的字节数组
|
||
// EncryptBytes return 返回二进制的加密结果
|
||
func (ae *AesWithKey) EncryptBytes(data []byte) ([]byte, error) {
|
||
return ae.crypto.Encrypt(data, ae.key, ae.iv)
|
||
}
|
||
|
||
// Decrypt 解密为字符串
|
||
// Decrypt data hex编码的加密后结果
|
||
// Decrypt return 解密后的数据,string类型
|
||
func (ae *AesWithKey) Decrypt(data string) (string, error) {
|
||
if dataD, err3 := hex.DecodeString(data); err3 == nil {
|
||
return makeStringResult(ae.crypto.Decrypt(dataD, ae.key, ae.iv))
|
||
} else {
|
||
return "", err3
|
||
}
|
||
}
|
||
|
||
// DecryptBytes 解密为二进制数据
|
||
// DecryptBytes data 二进制的加密后结果
|
||
// DecryptBytes return 解密后的数据,二进制的字节数组
|
||
func (ae *AesWithKey) DecryptBytes(data []byte) ([]byte, error) {
|
||
return ae.crypto.Decrypt(data, ae.key, ae.iv)
|
||
}
|
||
|
||
type Ecdsa struct {
|
||
crypto crypt.Crypt
|
||
}
|
||
|
||
// GenKey 生成hex编码的公钥私钥
|
||
// GenKey priKey hex编码的私钥信息
|
||
// GenKey pubKey hex编码的公钥信息
|
||
func (ec *Ecdsa) GenKey() (priKey string, pubKey string, error error) {
|
||
buf1, buf2, err := ec.crypto.GenKey()
|
||
return hex.EncodeToString(buf1), hex.EncodeToString(buf2), err
|
||
}
|
||
|
||
// GenKeyBytes 生成二进制的公钥私钥
|
||
// GenKeyBytes priKey 二进制的私钥信息
|
||
// GenKeyBytes pubKey 二进制的公钥信息
|
||
func (ec *Ecdsa) GenKeyBytes() (priKey []byte, pubKey []byte, error error) {
|
||
return ec.crypto.GenKey()
|
||
}
|
||
|
||
// Sign 对数据进行签名,返回hex编码格式的数据
|
||
// Sign data 将要签名的数据
|
||
// Sign priKey hex编码的私钥信息
|
||
func (ec *Ecdsa) Sign(data string, priKey string) (string, error) {
|
||
if priKeyD, err2 := hex.DecodeString(priKey); err2 == nil {
|
||
return makeHexStringResult(ec.crypto.Sign([]byte(data), priKeyD))
|
||
} else {
|
||
return "", err2
|
||
}
|
||
}
|
||
|
||
// SignBytes 对数据进行签名,返回二进制的数据
|
||
// SignBytes data 将要签名的二进制数据
|
||
// SignBytes priKey 二进制的私钥信息
|
||
func (ec *Ecdsa) SignBytes(data, priKey []byte) ([]byte, error) {
|
||
return ec.crypto.Sign(data, priKey)
|
||
}
|
||
|
||
// Verify 校验签名
|
||
// Verify data 将要签名的数据
|
||
// Verify signature hex编码的签名信息
|
||
// Verify pubKey hex编码的公钥信息
|
||
// Verify return 校验结果
|
||
func (ec *Ecdsa) Verify(data string, signature string, pubKey string) (bool, error) {
|
||
if signatureD, err1 := hex.DecodeString(signature); err1 == nil {
|
||
if pubKeyD, err2 := hex.DecodeString(pubKey); err2 == nil {
|
||
return ec.crypto.Verify([]byte(data), signatureD, pubKeyD), nil
|
||
} else {
|
||
return false, err2
|
||
}
|
||
} else {
|
||
return false, err1
|
||
}
|
||
}
|
||
|
||
// VerifyBytes 校验签名
|
||
// VerifyBytes data 将要签名的二进制数据
|
||
// VerifyBytes signature 二进制的签名信息
|
||
// VerifyBytes pubKey 二进制的公钥信息
|
||
// VerifyBytes return 校验结果
|
||
func (ec *Ecdsa) VerifyBytes(data, signature, pubKey []byte) bool {
|
||
return ec.crypto.Verify(data, signature, pubKey)
|
||
}
|
||
|
||
// Encrypt pubKey hex编码的公钥信息
|
||
func (ec *Ecdsa) Encrypt(data, pubKey string) (string, error) {
|
||
if pubKeyD, err := hex.DecodeString(pubKey); err == nil {
|
||
return makeHexStringResult(ec.crypto.EncryptE([]byte(data), pubKeyD))
|
||
} else {
|
||
return "", err
|
||
}
|
||
}
|
||
|
||
// EncryptBytes pubKey 二进制的公钥信息
|
||
func (ec *Ecdsa) EncryptBytes(data, pubKey []byte) ([]byte, error) {
|
||
return ec.crypto.EncryptE(data, pubKey)
|
||
}
|
||
|
||
// Decrypt priKey hex编码的私钥信息
|
||
func (ec *Ecdsa) Decrypt(data string, priKey string) (string, error) {
|
||
if dataD, err1 := hex.DecodeString(data); err1 == nil {
|
||
if priKeyD, err2 := hex.DecodeString(priKey); err2 == nil {
|
||
return makeStringResult(ec.crypto.DecryptE(dataD, priKeyD))
|
||
} else {
|
||
return "", err2
|
||
}
|
||
} else {
|
||
return "", err1
|
||
}
|
||
}
|
||
|
||
// DecryptBytes priKey 二进制的私钥信息
|
||
func (ec *Ecdsa) DecryptBytes(data, priKey []byte) ([]byte, error) {
|
||
return ec.crypto.DecryptE(data, priKey)
|
||
}
|
||
|
||
func makeHash(h hash.Hash, data []byte) []byte {
|
||
h.Write(data)
|
||
return h.Sum(nil)
|
||
}
|
||
|
||
func makeStringResult(buf []byte, err error) (string, error) {
|
||
if err == nil {
|
||
return string(buf), nil
|
||
} else {
|
||
return "", err
|
||
}
|
||
}
|
||
|
||
func makeHexStringResult(buf []byte, err error) (string, error) {
|
||
if err == nil {
|
||
return hex.EncodeToString(buf), nil
|
||
} else {
|
||
return "", err
|
||
}
|
||
}
|