1 Star 0 Fork 0

clearluo/gotools

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
codec.go 7.28 KB
一键复制 编辑 原始数据 按行查看 历史
clearluo 提交于 2020-09-27 18:08 . modify
package util
import (
"bytes"
"crypto/cipher"
"crypto/des"
"crypto/hmac"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"fmt"
"io/ioutil"
"net/url"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"gitee.com/clearluo/gotools/log"
)
// url encode string, is + not %20
func UrlEncode(str string) string {
return url.QueryEscape(str)
}
// url decode string
func UrlDecode(str string) (string, error) {
return url.QueryUnescape(str)
}
// base64 encode
func Base64Encode(str string) string {
return base64.StdEncoding.EncodeToString([]byte(str))
}
// base64 decode
func Base64Decode(str string) (string, error) {
s, e := base64.StdEncoding.DecodeString(str)
return string(s), e
}
// rsa加密
func RsaEncrypt(publicKey []byte, data []byte) (string, error) {
// 解密pem格式的公钥
block, _ := pem.Decode(publicKey)
if block == nil {
return "", fmt.Errorf("public key error")
}
// 解析公钥
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return "", err
}
// 类型断言
pub, ok := pubInterface.(*rsa.PublicKey)
if !ok {
return "", fmt.Errorf("public key is not *rsa.Public")
}
// 加密
enData, err := rsa.EncryptPKCS1v15(rand.Reader, pub, data)
if err != nil {
return "", err
}
// base64返回
return base64.StdEncoding.EncodeToString(enData), nil
}
// rsa解密
func RsaDecrypt(privateKey []byte, origData string) ([]byte, error) {
// base64解密
data, err := base64.StdEncoding.DecodeString(origData)
if err != nil {
return nil, err
}
// 解密pem格式私钥
block, _ := pem.Decode(privateKey)
if block == nil {
return nil, fmt.Errorf("private key error")
}
// 解析PKCS1格式的私钥
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
// 解密
return rsa.DecryptPKCS1v15(rand.Reader, priv, data)
}
func GetMd5(data string) string {
h := md5.New()
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil)) // 输出加密结果
}
// 加密哈希
func GetHmac(key string, data string) string {
h := hmac.New(md5.New, []byte(key))
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil))
}
func GetHmacSha256(key string, data string) string {
h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil))
}
func GetSha1(data string) string {
s := sha1.New()
s.Write([]byte(data))
return hex.EncodeToString(s.Sum(nil))
}
// 3des加密
func Des3Encrypt(key3Des []byte, source string) (string, error) {
result, err := TripleDesEncrypt([]byte(source), key3Des)
if err != nil {
log.Warn(err)
return "", err
}
return Base64Encode(string(result)), nil
}
// 3des解密
func Des3Decrypt(key3Des []byte, sec string) (string, error) {
c, err := Base64Decode(sec)
if err != nil {
log.Warn(err)
return "", err
}
origData, err := TripleDesDecrypt([]byte(c), key3Des)
if err != nil {
log.Warn(err)
return "", err
}
return string(origData), nil
}
func DesEncrypt(origData, key []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
origData = PKCS5Padding(origData, block.BlockSize())
// origData = ZeroPadding(origData, block.BlockSize())
blockMode := cipher.NewCBCEncrypter(block, key)
crypted := make([]byte, len(origData))
// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
// crypted := origData
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
func DesDecrypt(crypted, key []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
blockMode := cipher.NewCBCDecrypter(block, key)
origData := make([]byte, len(crypted))
// origData := crypted
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
// origData = ZeroUnPadding(origData)
return origData, nil
}
// 3DES加密
func TripleDesEncrypt(origData, key []byte) ([]byte, error) {
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
origData = PKCS5Padding(origData, block.BlockSize())
// origData = ZeroPadding(origData, block.BlockSize())
blockMode := cipher.NewCBCEncrypter(block, key[:8])
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
// 3DES解密
func TripleDesDecrypt(crypted, key []byte) ([]byte, error) {
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
blockMode := cipher.NewCBCDecrypter(block, key[:8])
origData := make([]byte, len(crypted))
// origData := crypted
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
// origData = ZeroUnPadding(origData)
return origData, 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])
return origData[:(length - unpadding)]
}
func GbkToUtf8(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewDecoder())
d, e := ioutil.ReadAll(reader)
if e != nil {
return nil, e
}
return d, nil
}
func Utf8ToGbk(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewEncoder())
d, e := ioutil.ReadAll(reader)
if e != nil {
return nil, e
}
return d, nil
}
func IsGBK(data []byte) bool {
length := len(data)
var i int = 0
for i < length {
if data[i] <= 0x7f {
//编码0~127,只有一个字节的编码,兼容ASCII码
i++
continue
} else {
//大于127的使用双字节编码,落在gbk编码范围内的字符
if data[i] >= 0x81 &&
data[i] <= 0xfe &&
data[i+1] >= 0x40 &&
data[i+1] <= 0xfe &&
data[i+1] != 0xf7 {
i += 2
continue
} else {
return false
}
}
}
return true
}
func preNUm(data byte) int {
var mask byte = 0x80
var num int = 0
//8bit中首个0bit前有多少个1bits
for i := 0; i < 8; i++ {
if (data & mask) == mask {
num++
mask = mask >> 1
} else {
break
}
}
return num
}
func IsUtf8(data []byte) bool {
i := 0
for i < len(data) {
if (data[i] & 0x80) == 0x00 {
// 0XXX_XXXX
i++
continue
} else if num := preNUm(data[i]); num > 2 {
// 110X_XXXX 10XX_XXXX
// 1110_XXXX 10XX_XXXX 10XX_XXXX
// 1111_0XXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// 1111_10XX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// 1111_110X 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// preNUm() 返回首个字节的8个bits中首个0bit前面1bit的个数,该数量也是该字符所使用的字节数
i++
for j := 0; j < num-1; j++ {
//判断后面的 num - 1 个字节是不是都是10开头
if (data[i] & 0xc0) != 0x80 {
return false
}
i++
}
} else {
//其他情况说明不是utf-8
return false
}
}
return true
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/clearluo/gotools.git
git@gitee.com:clearluo/gotools.git
clearluo
gotools
gotools
v1.1.1

搜索帮助

0d507c66 1850385 C8b1a773 1850385