| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- package core
- import (
- "bytes"
- "crypto/aes"
- "crypto/cipher"
- "crypto/hmac"
- "crypto/md5"
- "crypto/sha1"
- "crypto/sha256"
- "crypto/sha512"
- "encoding/base64"
- "encoding/hex"
- "fmt"
- "hash"
- "github.com/dop251/goja"
- )
- func toBytes(v interface{}) []byte {
- switch v := v.(type) {
- case []byte:
- return v
- case string:
- return []byte(v)
- case *Buffer:
- return v.value
- }
- return nil
- }
- func toString(v interface{}) string {
- switch v := v.(type) {
- case []byte:
- return string(v)
- case string:
- return v
- case *Buffer:
- return string(v.value)
- }
- return ""
- }
- type Crypto struct {
- vm *goja.Runtime
- }
- type Hmac struct {
- // decode bool
- vm *goja.Runtime
- Algorithm string
- middle interface{}
- }
- func (h *Hmac) Digest(EF string) interface{} {
- var result interface{}
- var SF = ""
- switch h.Algorithm {
- case "md5", "sha1", "sha256", "sha512":
- result = h.middle.(hash.Hash).Sum(nil)
- case "aes-256-cbc":
- }
- if EF == "" {
- return &Buffer{
- value: result.([]byte),
- }
- }
- return Convert(h.vm, result, SF, EF)
- }
- func (h *Hmac) Update(data interface{}, SF, EF string) interface{} {
- switch h.Algorithm {
- case "md5", "sha1", "sha256", "sha512":
- h.middle.(hash.Hash).Write(toBytes(data))
- case "aes-256-cbc":
- if SF == "hex" {
- data = Convert(h.vm, data, "hex", "")
- }
- return Convert(h.vm, h.middle.(*AesCipher).Update(toBytes(data)), "", EF)
- }
- return nil
- }
- func (h *Hmac) Final(EF string) interface{} {
- switch h.Algorithm {
- case "md5", "sha1", "sha256", "sha512":
- case "aes-256-cbc":
- return Convert(h.vm, h.middle.(*AesCipher).Final(), "", EF)
- }
- return nil
- }
- func (c *Crypto) CreateCipheriv(algorithm string, key, iv interface{}) *Hmac {
- var middle interface{}
- var err error
- switch algorithm {
- case "aes-256-cbc":
- middle, err = NewAesCipher(c.vm, toBytes(key), toBytes(iv), false)
- if err != nil {
- panic(Error(c.vm, err))
- }
- }
- return &Hmac{
- vm: c.vm,
- // decode: true,
- middle: middle,
- Algorithm: algorithm,
- }
- }
- func (c *Crypto) CreateDecipheriv(algorithm string, key, iv interface{}) *Hmac {
- var middle interface{}
- var err error
- switch algorithm {
- case "aes-256-cbc":
- middle, err = NewAesCipher(c.vm, toBytes(key), toBytes(iv), true)
- if err != nil {
- panic(Error(c.vm, err))
- }
- }
- return &Hmac{
- // decode: true,
- vm: c.vm,
- middle: middle,
- Algorithm: algorithm,
- }
- }
- func (c *Crypto) CreateHash(algorithm string) *Hmac {
- var hashFunc func() hash.Hash
- switch algorithm {
- case "md5":
- hashFunc = md5.New
- case "sha1":
- hashFunc = sha1.New
- case "sha256":
- hashFunc = sha256.New
- case "sha512":
- hashFunc = sha512.New
- default:
- return nil
- }
- return &Hmac{
- vm: c.vm,
- middle: hashFunc(),
- Algorithm: algorithm,
- }
- }
- func (c *Crypto) CreateHmac(algorithm string, key interface{}) *Hmac {
- var hashFunc func() hash.Hash
- switch algorithm {
- case "md5":
- hashFunc = md5.New
- case "sha1":
- hashFunc = sha1.New
- case "sha256":
- hashFunc = sha256.New
- case "sha512":
- hashFunc = sha512.New
- default:
- return nil
- }
- return &Hmac{
- vm: c.vm,
- middle: hmac.New(hashFunc, toBytes(key)),
- Algorithm: algorithm,
- }
- }
- type AesCipher struct {
- block cipher.Block
- iv []byte
- mode cipher.BlockMode
- decode bool
- buffer bytes.Buffer
- vm *goja.Runtime
- }
- func NewAesCipher(vm *goja.Runtime, key, iv []byte, decode bool) (*AesCipher, error) {
- block, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- mode := cipher.NewCBCDecrypter(block, iv)
- if !decode {
- mode = cipher.NewCBCEncrypter(block, iv)
- }
- return &AesCipher{
- vm: vm,
- block: block,
- iv: iv,
- mode: mode,
- decode: decode,
- }, nil
- }
- func (ac *AesCipher) Update(text []byte) []byte {
- //fmt.Println("Update", string(text))
- if ac.decode {
- // Decrypt
- var err error
- //fmt.Println("Decrypt1", string(text))
- ac.mode.CryptBlocks(text, text)
- //fmt.Println("Decrypt2", string(text))
- text, err = pkcs7Unpadding(text)
- if err != nil {
- panic(Error(ac.vm, err))
- }
- //fmt.Println("Decrypt3", string(text), err)
- } else {
- // Encrypt
- text = pkcs7Padding(text, ac.block.BlockSize())
- ac.mode.CryptBlocks(text, text)
- }
- ac.buffer.Write(text)
- return nil
- // return text
- }
- func (ac *AesCipher) Final() []byte {
- return ac.buffer.Bytes()
- }
- func pkcs7Unpadding(data []byte) ([]byte, error) {
- length := len(data)
- unpadding := int(data[length-1])
- if unpadding > length {
- return nil, fmt.Errorf("pkcs7: invalid padding")
- }
- return data[:(length - unpadding)], nil
- }
- // type Cipher struct{}
- // func (c *Cipher) AesEncrypt(key, data string) (string, error) {
- // block, err := aes.NewCipher([]byte(key))
- // if err != nil {
- // return "", err
- // }
- // ciphertext := make([]byte, aes.BlockSize+len(data))
- // iv := ciphertext[:aes.BlockSize]
- // if _, err := io.ReadFull(rand.Reader, iv); err != nil {
- // return "", err
- // }
- // stream := cipher.NewCFBEncrypter(block, iv)
- // stream.XORKeyStream(ciphertext[aes.BlockSize:], []byte(data))
- // return base64.StdEncoding.EncodeToString(ciphertext), nil
- // }
- // func (c *Cipher) AesDecrypt(key, ciphertext string) (string, error) {
- // block, err := aes.NewCipher([]byte(key))
- // if err != nil {
- // return "", err
- // }
- // data, err := base64.StdEncoding.DecodeString(ciphertext)
- // if err != nil {
- // return "", err
- // }
- // if len(data) < aes.BlockSize {
- // return "", fmt.Errorf("ciphertext too short")
- // }
- // iv := data[:aes.BlockSize]
- // data = data[aes.BlockSize:]
- // stream := cipher.NewCFBDecrypter(block, iv)
- // stream.XORKeyStream(data, data)
- // return string(data), nil
- // }
- // func (c *Cipher) Rc4Encrypt(key, data string) (string, error) {
- // cipher, err := rc4.NewCipher([]byte(key))
- // if err != nil {
- // return "", err
- // }
- // ciphertext := make([]byte, len(data))
- // cipher.XORKeyStream(ciphertext, []byte(data))
- // return base64.StdEncoding.EncodeToString(ciphertext), nil
- // }
- // func (c *Cipher) Rc4Decrypt(key, ciphertext string) (string, error) {
- // cipher, err := rc4.NewCipher([]byte(key))
- // if err != nil {
- // return "", err
- // }
- // data, err := base64.StdEncoding.DecodeString(ciphertext)
- // if err != nil {
- // return "", err
- // }
- // cipher.XORKeyStream(data, data)
- // return string(data), nil
- // }
- func Convert(vm *goja.Runtime, data interface{}, fromFormat string, toFormat string) interface{} {
- //fmt.Println(data, fromFormat, toFormat)
- var dataBytes []byte
- switch input := data.(type) {
- case string:
- dataBytes = []byte(input)
- case []byte:
- dataBytes = input
- case *Buffer:
- dataBytes = input.value
- default:
- panic(Error(vm, fmt.Errorf("invalid data type: %T", data)))
- }
- switch fromFormat {
- case "hex":
- // 将数据从 HEX 编码格式转换为字节数组
- decodedData, err := hex.DecodeString(string(dataBytes))
- if err != nil {
- panic(Error(vm, err))
- }
- dataBytes = decodedData
- case "base64":
- // 将数据从 Base64 编码格式转换为字节数组
- decodedData, err := base64.StdEncoding.DecodeString(string(dataBytes))
- if err != nil {
- panic(Error(vm, err))
- }
- dataBytes = decodedData
- case "bytes", "binary":
- // 不需要进行转换
- case "utf8", "utf-8", "":
- default:
- panic(Error(vm, fmt.Errorf("unsupported input format: %s", fromFormat)))
- }
- //fmt.Println(string(dataBytes), fromFormat, toFormat)
- switch toFormat {
- case "hex":
- // 将数据转换为 HEX 编码格式
- //fmt.Println("hex", hex.EncodeToString(dataBytes), fromFormat, toFormat)
- return hex.EncodeToString(dataBytes)
- case "base64":
- // 将数据转换为 Base64 编码格式
- return base64.StdEncoding.EncodeToString(dataBytes)
- case "bytes", "binary":
- // 不需要进行转换
- return dataBytes
- case "utf8", "utf-8", "":
- // 将数据转换为 UTF-8 编码格式
- return string(dataBytes)
- default:
- panic(Error(vm, fmt.Errorf("unsupported output format: %s", toFormat)))
- }
- }
- func cryptoModule(vm *goja.Runtime, module *goja.Object) {
- cryto := Crypto{
- vm: vm,
- }
- o := module.Get("exports").(*goja.Object)
- o.Set("createCipheriv", cryto.CreateCipheriv)
- o.Set("createDecipheriv", cryto.CreateDecipheriv)
- o.Set("createHash", cryto.CreateHash)
- o.Set("createHmac", cryto.CreateHmac)
- }
|