diff --git a/README.md b/README.md index e959ce1..e745986 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,58 @@ -# utils +# utils通用包 -通用包 \ No newline at end of file + +* [utils通用包](#utils通用包) + * [安装](#安装) + * [通用包](#通用包) + * [pagination](#pagination) + * [transport:通用http ResponseEncoder](#transport通用http-responseencoder) + * [meta:跨服务meta信息设置和获取](#meta跨服务meta信息设置和获取) + * [encrypt:对称加密](#encrypt对称加密) + + +## 安装 + +1. 设置私有仓库 + +```shell +go env -w GOPRIVATE=gitea.drugeyes.vip +``` + +2. 设置git + +```shell +git config --global url."ssh://gitea@gitea.drugeyes.vip".insteadOf "https://gitea.drugeyes.vip" +``` + +3. 拉取对应版本 + +```shell +go get gitea.drugeyes.vip/pharnexbase/tools@v1.0.0 +``` + +## 通用包 + +### pagination + +* v1 + + > 说明 + +### transport:通用http ResponseEncoder + +* v1 + + > 通用http ResponseEncoder + +### meta:跨服务meta信息设置和获取 + +* v1 + + > 跨服务meta信息设置和获取 + > - user(基础用户信息) + +### encrypt:对称加密 + +* v1 + + > 对称加密,目前包含:SHA1PRNG \ No newline at end of file diff --git a/encrypt/v1/encrypt.go b/encrypt/v1/encrypt.go new file mode 100644 index 0000000..65988e1 --- /dev/null +++ b/encrypt/v1/encrypt.go @@ -0,0 +1,102 @@ +package encrypt + +import ( + "crypto/aes" + "crypto/hmac" + "crypto/sha1" + "errors" +) + +//AesEncryptECBSha1prng java AES 加密 SHA1PRNG +func AesEncryptECBSha1prng(src []byte, key []byte) ([]byte, error) { + sha1prngKey, err := GetSha1prngKey(key, 128) + if err != nil { + return nil, err + } + + return AesEncryptECB(src, sha1prngKey), nil +} + +//AesDecryptECBSha1prng java AES 解密 SHA1PRNG +func AesDecryptECBSha1prng(encrypted []byte, key []byte) ([]byte, error) { + sha1prngKey, err := GetSha1prngKey(key, 128) + if err != nil { + return nil, err + } + + return AesDecryptECB(encrypted, sha1prngKey), nil +} + +//AesEncryptECB AES-128-ECB 加密,(php:openssl_encrypt($string, 'AES-128-ECB', $key, OPENSSL_RAW_DATA)) +func AesEncryptECB(src []byte, key []byte) []byte { + c, _ := aes.NewCipher(generateKey(key)) + length := (len(src) + aes.BlockSize) / aes.BlockSize + plain := make([]byte, length*aes.BlockSize) + copy(plain, src) + pad := byte(len(plain) - len(src)) + for i := len(src); i < len(plain); i++ { + plain[i] = pad + } + encrypted := make([]byte, len(plain)) + // 分组分块加密 + for bs, be := 0, c.BlockSize(); bs <= len(src); bs, be = bs+c.BlockSize(), be+c.BlockSize() { + c.Encrypt(encrypted[bs:be], plain[bs:be]) + } + + return encrypted +} + +//AesDecryptECB AES-128-ECB 解密 +func AesDecryptECB(encrypted []byte, key []byte) []byte { + c, _ := aes.NewCipher(generateKey(key)) + decrypted := make([]byte, len(encrypted)) + + for bs, be := 0, c.BlockSize(); bs < len(encrypted); bs, be = bs+c.BlockSize(), be+c.BlockSize() { + c.Decrypt(decrypted[bs:be], encrypted[bs:be]) + } + + trim := 0 + if len(decrypted) > 0 { + trim = len(decrypted) - int(decrypted[len(decrypted)-1]) + } + + return decrypted[:trim] +} + +// GetSha1prngKey 模拟 java SHA1PRNG 处理,(php:substr(openssl_digest(openssl_digest($key, 'sha1', true), 'sha1', true), 0, 16)) +func GetSha1prngKey(keyBytes []byte, encryptLength int) ([]byte, error) { + hashs := Sha1(Sha1(keyBytes)) + maxLen := len(hashs) + realLen := encryptLength / 8 + if realLen > maxLen { + return nil, errors.New("invalid length") + } + + return hashs[0:realLen], nil +} + +//Sha1 Sha1 +func Sha1(data []byte) []byte { + h := sha1.New() + h.Write(data) + return h.Sum(nil) +} + +// HmacSha1 HmacSha1 +func HmacSha1(string, secret string) []byte { + mac := hmac.New(sha1.New, []byte(secret)) + mac.Write([]byte(string)) + + return mac.Sum(nil) +} + +func generateKey(key []byte) (genKey []byte) { + genKey = make([]byte, 16) + copy(genKey, key) + for i := 16; i < len(key); { + for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 { + genKey[j] ^= key[i] + } + } + return genKey +} diff --git a/meta/v1/user.go b/meta/v1/user.go new file mode 100644 index 0000000..b14f8bb --- /dev/null +++ b/meta/v1/user.go @@ -0,0 +1,75 @@ +package meta + +import ( + "context" + "encoding/json" + "errors" + "github.com/go-kratos/kratos/v2/metadata" +) + +const ( + userMetaKey = "x-md-global-user" +) + +var UserErr = errors.New("userinfo error") + +// User 用户信息 +type User struct { + // 用户id + Id int32 `json:"id"` + // 邮箱 + Email string `json:"email"` + // 账号 + Username string `json:"username"` + // 手机号 + Phone string `json:"phone"` + // 昵称 + Nickname string `json:"nickname"` + // 头像 + Avatar string `json:"avatar"` + // 状态 1=正常;2=封禁 + Status int32 `json:"status"` +} + +// SetUserMetaClient 设置用户meta信息 +func SetUserMetaClient(ctx context.Context, user *User) context.Context { + userInfo, _ := json.Marshal(user) + return metadata.AppendToClientContext(ctx, userMetaKey, string(userInfo)) +} + +// GetUserMetaClient 获取用户meta信息 +func GetUserMetaClient(ctx context.Context) (*User, error) { + if meta, ok := metadata.FromClientContext(ctx); ok { + user := &User{} + if json.Unmarshal([]byte(meta.Get(userMetaKey)), user) != nil { + return nil, UserErr + } + return user, nil + } + return nil, UserErr +} + +// SetUserMetaServer 设置用户meta信息 +func SetUserMetaServer(ctx context.Context, user *User) context.Context { + userInfo, _ := json.Marshal(user) + + var meta metadata.Metadata + var ok bool + if meta, ok = metadata.FromServerContext(ctx); ok { + meta.Set(userMetaKey, string(userInfo)) + } + + return metadata.NewServerContext(ctx, meta) +} + +// GetUserMetaServer 获取用户meta信息 +func GetUserMetaServer(ctx context.Context) (*User, error) { + if meta, ok := metadata.FromServerContext(ctx); ok { + user := &User{} + if json.Unmarshal([]byte(meta.Get(userMetaKey)), user) != nil { + return nil, UserErr + } + return user, nil + } + return nil, UserErr +}