115 lines
2.8 KiB
Go
Executable File
115 lines
2.8 KiB
Go
Executable File
package codec
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"crypto/sha1"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
|
|
"git.wishpal.cn/wishpal_ironfan/xframe/component/logger"
|
|
)
|
|
|
|
// CfbDecrypt decrypts src with the given key.
|
|
func CfbDecrypt(cipherText string, key string) (plainText string, err error) {
|
|
if len(cipherText) == 0 || len(cipherText) < 6 || cipherText[:6] != "crypt-" {
|
|
err = errors.New("illegal ciphertext")
|
|
return
|
|
}
|
|
cipherText = string(cipherText[6:])
|
|
var block cipher.Block
|
|
keyBytes := hashBytes(key)
|
|
cipherTextBytes, _ := hex.DecodeString(cipherText)
|
|
block, err = aes.NewCipher(keyBytes)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if len(cipherTextBytes) < aes.BlockSize {
|
|
err = errors.New("ciphertext too short")
|
|
return
|
|
}
|
|
|
|
iv := cipherTextBytes[:aes.BlockSize]
|
|
cipherTextBytes = cipherTextBytes[aes.BlockSize:]
|
|
stream := cipher.NewCFBDecrypter(block, iv)
|
|
|
|
plainTextBytes := make([]byte, len(cipherTextBytes))
|
|
stream.XORKeyStream(plainTextBytes, cipherTextBytes)
|
|
plainText = string(plainTextBytes)
|
|
return
|
|
}
|
|
|
|
// CbcEncrypt encrypts dat with the given key.
|
|
func CbcEncrypt(key []byte, dat []byte, fixed bool) ([]byte, error) {
|
|
res := cbcPadding(dat, fixed)
|
|
iv := res[:aes.BlockSize]
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
buf := res[aes.BlockSize:]
|
|
cipher.NewCBCEncrypter(block, iv).CryptBlocks(buf, buf)
|
|
return res, nil
|
|
}
|
|
|
|
// CbcDecrypt decrypts dat with the given key.
|
|
func CbcDecrypt(key, dat []byte) ([]byte, error) {
|
|
if len(dat) < aes.BlockSize*2 {
|
|
return nil, fmt.Errorf("invalid dat")
|
|
}
|
|
|
|
iv := dat[:aes.BlockSize]
|
|
padNum := int(iv[1])
|
|
if padNum <= 0 || padNum > aes.BlockSize {
|
|
return nil, fmt.Errorf("invalid dat")
|
|
}
|
|
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
res := make([]byte, len(dat)-aes.BlockSize)
|
|
decrypt := cipher.NewCBCDecrypter(block, iv)
|
|
if len(dat[aes.BlockSize:])%decrypt.BlockSize() != 0 {
|
|
logger.Warnf("decrypt_post_data, key: %v, data: %v", base64.StdEncoding.EncodeToString(key),
|
|
base64.StdEncoding.EncodeToString(dat))
|
|
return nil, fmt.Errorf("crypto/cipher: input not full blocks")
|
|
}
|
|
decrypt.CryptBlocks(res, dat[aes.BlockSize:])
|
|
return res[padNum:], nil
|
|
}
|
|
|
|
func cbcPadding(dat []byte, fixed bool) []byte {
|
|
padNum := aes.BlockSize - (len(dat) % aes.BlockSize)
|
|
|
|
//iv+padding+dat
|
|
res := make([]byte, aes.BlockSize+padNum+len(dat))
|
|
iv := res[:aes.BlockSize]
|
|
if !fixed {
|
|
io.ReadFull(rand.Reader, iv)
|
|
}
|
|
iv[1] = byte(padNum)
|
|
padding := res[aes.BlockSize : aes.BlockSize+padNum]
|
|
if !fixed {
|
|
io.ReadFull(rand.Reader, padding)
|
|
}
|
|
|
|
copy(res[aes.BlockSize+padNum:], dat)
|
|
return res
|
|
}
|
|
|
|
func hashBytes(key string) (hash []byte) {
|
|
h := sha1.New()
|
|
io.WriteString(h, key)
|
|
hashStr := hex.EncodeToString(h.Sum(nil))
|
|
hash = []byte(hashStr)[:32]
|
|
return
|
|
}
|