goutil/encoding.go

146 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package goutil
import (
"bytes"
"compress/gzip"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"encoding/json"
"encoding/xml"
"errors"
"io"
"unicode"
"github.com/speps/go-hashids"
)
// EncodeJSON encode anything to json string
func EncodeJSON(v interface{}) string {
b, _ := json.Marshal(v)
return string(b)
}
// EncodeJSON encode anything to json string
func EncodeJSONIndent(v interface{}) string {
b, _ := json.MarshalIndent(v, " ", " ")
return string(b)
}
// EncodeJSON encode anything to json string
func EncodeXML(v interface{}) string {
b, _ := xml.Marshal(v)
return string(b)
}
// EncodeJSON encode anything to json string
func EncodeXMLIndent(v interface{}) string {
b, _ := xml.MarshalIndent(v, " ", " ")
return string(b)
}
func HasChinese(str string) bool {
for _, r := range str {
if unicode.Is(unicode.Han, r) {
return true
}
}
return false
}
func EncryptID(data int64, salt string) string {
hd := hashids.NewData()
hd.Salt = salt
h, _ := hashids.NewWithData(hd)
e, _ := h.Encode([]int{int(data)})
return e
}
func DecryptID(data, salt string) int64 {
hd := hashids.NewData()
hd.Salt = salt
h, _ := hashids.NewWithData(hd)
e, _ := h.DecodeWithError(data)
return int64(e[0])
}
// 先压缩再加密(适合长文本)
func Encrypt(plaintext string, key string) (string, error) {
// 1. 压缩
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
if _, err := gz.Write([]byte(plaintext)); err != nil {
return "", err
}
if err := gz.Close(); err != nil {
return "", err
}
compressed := buf.Bytes()
// 2. 加密使用AES-GCM
block, err := aes.NewCipher([]byte(Md5(key)))
if err != nil {
return "", err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return "", err
}
ciphertext := gcm.Seal(nonce, nonce, compressed, nil)
// 使用RawURLEncoding
return base64.RawURLEncoding.EncodeToString(ciphertext), nil
}
func Decrypt(encoded string, key string) (string, error) {
data, err := base64.RawURLEncoding.DecodeString(encoded)
if err != nil {
return "", err
}
block, err := aes.NewCipher([]byte(Md5(key)))
if err != nil {
return "", err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
nonceSize := gcm.NonceSize()
if len(data) < nonceSize {
return "", errors.New("数据太短")
}
nonce := data[:nonceSize]
ciphertext := data[nonceSize:]
compressed, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return "", err
}
// 解压缩
reader, err := gzip.NewReader(bytes.NewReader(compressed))
if err != nil {
return "", err
}
defer reader.Close()
result, err := io.ReadAll(reader)
if err != nil {
return "", err
}
return string(result), nil
}