|
|
package encrypt
|
|
|
|
|
|
import (
|
|
|
"bytes"
|
|
|
"crypto/aes"
|
|
|
"crypto/cipher"
|
|
|
"crypto/md5"
|
|
|
"encoding/base64"
|
|
|
"encoding/hex"
|
|
|
"fmt"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
)
|
|
|
|
|
|
type KeySizeError int
|
|
|
|
|
|
func (k KeySizeError) Error() string {
|
|
|
return "fastEncryptDecode/fastEnDeCode: invalid key size " + strconv.Itoa(int(k)) + " | key size must be 16"
|
|
|
}
|
|
|
|
|
|
type ecbEncrypter ecb
|
|
|
|
|
|
type ecb struct {
|
|
|
b cipher.Block
|
|
|
blockSize int
|
|
|
}
|
|
|
|
|
|
func newECB(b cipher.Block) *ecb {
|
|
|
return &ecb{
|
|
|
b: b,
|
|
|
blockSize: b.BlockSize(),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// byte array to string
|
|
|
func ByteArr2Str(p []byte) string {
|
|
|
lp := len(p)
|
|
|
for i := 0; i < lp; i++ {
|
|
|
if p[i] == 0 {
|
|
|
return string(p[0:i])
|
|
|
}
|
|
|
}
|
|
|
return string(p)
|
|
|
}
|
|
|
|
|
|
func ByteArr2HexStr(bArr []byte) string {
|
|
|
buf := new(bytes.Buffer)
|
|
|
for _, b := range bArr {
|
|
|
s := strconv.FormatInt(int64(b&0xff), 16)
|
|
|
if len(s) == 1 {
|
|
|
buf.WriteString("0")
|
|
|
}
|
|
|
buf.WriteString(s)
|
|
|
}
|
|
|
return buf.String()
|
|
|
}
|
|
|
|
|
|
func Uint16ToBytes(n uint16) []byte {
|
|
|
return []byte{
|
|
|
byte(n),
|
|
|
byte(n >> 8),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func Uint32ToBytes(n uint32) []byte {
|
|
|
return []byte{
|
|
|
byte(n),
|
|
|
byte(n >> 8),
|
|
|
byte(n >> 16),
|
|
|
byte(n >> 24),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func Uint64ToBytes(n uint64) []byte {
|
|
|
return []byte{
|
|
|
byte(n),
|
|
|
byte(n >> 8),
|
|
|
byte(n >> 16),
|
|
|
byte(n >> 24),
|
|
|
byte(n >> 32),
|
|
|
byte(n >> 40),
|
|
|
byte(n >> 48),
|
|
|
byte(n >> 56),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func ByteArr2HexStrArr(bArr []byte) []string {
|
|
|
length := len(bArr)
|
|
|
slice := make([]string, length)
|
|
|
buf := new(bytes.Buffer)
|
|
|
for i := 0; i < length; i++ {
|
|
|
buf.Reset()
|
|
|
buf.WriteString("0x")
|
|
|
s := strconv.FormatInt(int64(bArr[i]&0xff), 16)
|
|
|
if len(s) == 1 {
|
|
|
buf.WriteString("0")
|
|
|
}
|
|
|
buf.WriteString(s)
|
|
|
slice[i] = buf.String()
|
|
|
}
|
|
|
return slice
|
|
|
}
|
|
|
|
|
|
func HexStr2ByteArr(hexString string) ([]byte, error) {
|
|
|
length := len(hexString) / 2
|
|
|
slice := make([]byte, length)
|
|
|
rs := []rune(hexString)
|
|
|
for i := 0; i < length; i++ {
|
|
|
s := string(rs[i*2 : i*2+2])
|
|
|
value, err := strconv.ParseInt(s, 16, 10)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
slice[i] = byte(value & 0xFF)
|
|
|
}
|
|
|
return slice, nil
|
|
|
}
|
|
|
|
|
|
func Utf82Unicode(code string) string {
|
|
|
cover := strconv.QuoteToASCII(code)
|
|
|
res := cover[1 : len(cover)-1]
|
|
|
return res
|
|
|
}
|
|
|
|
|
|
func Unicode2Utf8(code string) string {
|
|
|
unicodeTemp := strings.Split(code, "\\u")
|
|
|
var context string
|
|
|
for _, v := range unicodeTemp {
|
|
|
if len(v) < 1 {
|
|
|
continue
|
|
|
}
|
|
|
temp, err := strconv.ParseInt(v, 16, 32)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
context += fmt.Sprintf("%c", temp)
|
|
|
}
|
|
|
return context
|
|
|
}
|
|
|
|
|
|
//string to md5
|
|
|
func String2MD5(code string) string {
|
|
|
h := md5.New()
|
|
|
h.Write([]byte(code))
|
|
|
rs := hex.EncodeToString(h.Sum(nil))
|
|
|
return rs
|
|
|
}
|
|
|
|
|
|
func MD5Verify(code string, md5Str string) bool {
|
|
|
return 0 == strings.Compare(String2MD5(code), md5Str)
|
|
|
}
|
|
|
|
|
|
//MD5 hash
|
|
|
func MD5hash(code []byte) string {
|
|
|
h := md5.New()
|
|
|
h.Write(code)
|
|
|
rs := hex.EncodeToString(h.Sum(nil))
|
|
|
return rs
|
|
|
}
|
|
|
|
|
|
func checkKeySize(key []byte) error {
|
|
|
len := len(key)
|
|
|
if len != 16 {
|
|
|
return KeySizeError(len)
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
// AES encrypt pkcs7padding CBC, key for choose algorithm
|
|
|
func AES_CBC_PKCS7_Encrypt(plantText, key string) (string, error) {
|
|
|
res, err := AES_CBC_PKCS7_EncryptByte([]byte(plantText), []byte(key))
|
|
|
return ByteArr2Str(res), err
|
|
|
}
|
|
|
|
|
|
// AES encrypt pkcs7padding CBC, key for choose algorithm
|
|
|
func AES_CBC_PKCS7_EncryptByte(plantText, key []byte) ([]byte, error) {
|
|
|
err := checkKeySize(key)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
block, err := aes.NewCipher(key)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
plantText = pKCS7Padding(plantText, block.BlockSize())
|
|
|
|
|
|
blockModel := cipher.NewCBCEncrypter(block, key)
|
|
|
|
|
|
cipherText := make([]byte, len(plantText))
|
|
|
|
|
|
blockModel.CryptBlocks(cipherText, plantText)
|
|
|
return cipherText, nil
|
|
|
}
|
|
|
|
|
|
func AES_CBC_PKCS7_Decrypt(cipherText, key string) (string, error) {
|
|
|
result, err := AES_CBC_PKCS7_DecryptByte([]byte(cipherText), []byte(key))
|
|
|
str := ByteArr2Str(result)
|
|
|
return str, err
|
|
|
}
|
|
|
|
|
|
func AES_CBC_PKCS7_DecryptByte(cipherText, key []byte) ([]byte, error) {
|
|
|
err := checkKeySize(key)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
keyBytes := []byte(key)
|
|
|
block, err := aes.NewCipher(keyBytes)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
blockModel := cipher.NewCBCDecrypter(block, keyBytes)
|
|
|
plantText := make([]byte, len(cipherText))
|
|
|
blockModel.CryptBlocks(plantText, cipherText)
|
|
|
plantText = pKCS7UnPadding(plantText, block.BlockSize())
|
|
|
return plantText, nil
|
|
|
}
|
|
|
|
|
|
//AES Decrypt pkcs7padding CBC, key for choose algorithm
|
|
|
func pKCS7UnPadding(plantText []byte, blockSize int) []byte {
|
|
|
length := len(plantText)
|
|
|
unPadding := int(plantText[length-1])
|
|
|
return plantText[:(length - unPadding)]
|
|
|
}
|
|
|
|
|
|
func pKCS7Padding(cipherText []byte, blockSize int) []byte {
|
|
|
padding := blockSize - len(cipherText)%blockSize
|
|
|
padText := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
|
return append(cipherText, padText...)
|
|
|
}
|
|
|
|
|
|
func AES_ECB_PKCS5_Encrypt(cipherText, key string) (string, error) {
|
|
|
result, err := AES_ECB_PKCS5_EncryptByte([]byte(cipherText), []byte(key))
|
|
|
str := ByteArr2Str(result)
|
|
|
return str, err
|
|
|
}
|
|
|
|
|
|
func AES_ECB_PKCS5_EncryptByte(cipherText, key []byte) ([]byte, error) {
|
|
|
err := checkKeySize(key)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
block, err := aes.NewCipher(key)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
ecb := newECBEncrypter(block)
|
|
|
content := cipherText
|
|
|
content = PKCS5Padding(content, block.BlockSize())
|
|
|
crypted := make([]byte, len(content))
|
|
|
ecb.CryptBlocks(crypted, content)
|
|
|
// 普通base64编码加密 区别于urlsafe base64
|
|
|
return crypted, nil
|
|
|
}
|
|
|
|
|
|
func AES_ECB_PKCS5_Decrypt(cipherText, key string) (string, error) {
|
|
|
result, err := AES_ECB_PKCS5_DecryptByte([]byte(cipherText), []byte(key))
|
|
|
str := ByteArr2Str(result)
|
|
|
return str, err
|
|
|
}
|
|
|
|
|
|
func AES_ECB_PKCS5_DecryptByte(cipherText, key []byte) ([]byte, error) {
|
|
|
err := checkKeySize(key)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
block, err := aes.NewCipher(key)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
blockMode := newECBDecrypter(block)
|
|
|
origData := make([]byte, len(cipherText))
|
|
|
blockMode.CryptBlocks(origData, cipherText)
|
|
|
origData = PKCS5UnPadding(origData)
|
|
|
return origData, nil
|
|
|
}
|
|
|
|
|
|
func Base64UrlSafeEncode(source []byte) string {
|
|
|
// Base64 Url Safe is the same as Base64 but does not contain '/' and '+' (replaced by '_' and '-') and trailing '=' are removed.
|
|
|
bytearr := base64.StdEncoding.EncodeToString(source)
|
|
|
safeurl := strings.Replace(string(bytearr), "/", "_", -1)
|
|
|
safeurl = strings.Replace(safeurl, "+", "-", -1)
|
|
|
safeurl = strings.Replace(safeurl, "=", "", -1)
|
|
|
return safeurl
|
|
|
}
|
|
|
|
|
|
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)]
|
|
|
}
|
|
|
|
|
|
// NewECBEncrypter returns a BlockMode which encrypts in electronic code book
|
|
|
// mode, using the given Block.
|
|
|
func newECBEncrypter(b cipher.Block) cipher.BlockMode {
|
|
|
return (*ecbEncrypter)(newECB(b))
|
|
|
}
|
|
|
func (x *ecbEncrypter) BlockSize() int {
|
|
|
return x.blockSize
|
|
|
}
|
|
|
func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
|
|
|
if len(src)%x.blockSize != 0 {
|
|
|
panic("crypto/cipher: input not full blocks")
|
|
|
}
|
|
|
if len(dst) < len(src) {
|
|
|
panic("crypto/cipher: output smaller than input")
|
|
|
}
|
|
|
for len(src) > 0 {
|
|
|
x.b.Encrypt(dst, src[:x.blockSize])
|
|
|
src = src[x.blockSize:]
|
|
|
dst = dst[x.blockSize:]
|
|
|
}
|
|
|
}
|
|
|
|
|
|
type ecbDecrypter ecb
|
|
|
|
|
|
// NewECBDecrypter returns a BlockMode which decrypts in electronic code book
|
|
|
// mode, using the given Block.
|
|
|
func newECBDecrypter(b cipher.Block) cipher.BlockMode {
|
|
|
return (*ecbDecrypter)(newECB(b))
|
|
|
}
|
|
|
func (x *ecbDecrypter) BlockSize() int {
|
|
|
return x.blockSize
|
|
|
}
|
|
|
func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
|
|
|
if len(src)%x.blockSize != 0 {
|
|
|
panic("crypto/cipher: input not full blocks")
|
|
|
}
|
|
|
if len(dst) < len(src) {
|
|
|
panic("crypto/cipher: output smaller than input")
|
|
|
}
|
|
|
for len(src) > 0 {
|
|
|
x.b.Decrypt(dst, src[:x.blockSize])
|
|
|
src = src[x.blockSize:]
|
|
|
dst = dst[x.blockSize:]
|
|
|
}
|
|
|
} |
...
|
...
|
|