brix / crypto-js

JavaScript library of crypto standards.
Other
15.8k stars 2.38k forks source link

AES decrypt in golang #373

Open sb-child opened 3 years ago

sb-child commented 3 years ago

hi, i have tried searching and trying it but nope. is it possible to decrypt a cipher text from crypto-js in Golang?

a example from README:

var CryptoJS = require("crypto-js");

// Encrypt
var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();

// Decrypt
var bytes  = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
// ^ only ciphertext and key, hasn't iv param
var originalText = bytes.toString(CryptoJS.enc.Utf8);

console.log(originalText); // 'my message'

how to decrypt it in Golang?

// js code: var ct = CryptoJS.AES.encrypt('my message', '<key>').toString();
ct := "<cipher text>"
key := "<key>"
// some decryption codes...
fmt.Println(decryptedString)

thanks for your help!

cute-angelia commented 2 years ago

这问题确实好难

文档

image

但是按这个去解码结果却解不出,原因在 iv(初始化向量) iv算法的不一致导致错误结果

===>

后面需要自定义IV规则,这里还有坑

https://stackoverflow.com/questions/29512858/cryptojs-and-key-iv-length

这里写了:If you tend to pass custom key and IV in using CryptoJS, make sure that (assuming that CryptoJS.enc.Base64.parse() gives HEX string, which is used in CryptoJS.AES.encrypt()).

js 加密代码

var crypto;
try {
  crypto = require('crypto');
} catch (err) {
  console.log('crypto support is disabled!');
}

// 写死了,测试用 32长度
var key = "5a673bd785831e2e5a673bd785831e2e" // crypto.randomBytes(32); 
// 写死了,测试用, 取了 key的 前16位, 对应golang算法也是如此, 建议一般是取内容的前16位,不足补齐。。
var iv = "5a673bd785831e2e"// crypto.randomBytes(16); 

function encrypt(text) {
  // Creating Cipheriv with its parameter
  let cipher =
    crypto.createCipheriv('aes-256-cbc', key, iv);

  // Updating text
  let encrypted = cipher.update(text);

  // Using concatenation
  encrypted = Buffer.concat([encrypted, cipher.final()]);

  // Returning iv and encrypted data
  return {
    iv: iv.toString('hex'),
    key: key.toString('hex'),
    encryptedData: encrypted.toString('hex')
  };
}

console.log(encrypt("hello world"))

/* 打印结果
{
  iv: '5a673bd785831e2e',
  key: '5a673bd785831e2e5a673bd785831e2e',
  encryptedData: 'ea17db2f3930c4f94b425141832f7f68'
}
*/

golang

func DecryptCBC2(crypted string, key []byte) ([]byte, error) {
    cipherText, err := hex.DecodeString(crypted)
    if err != nil {
        return nil, err
    }

    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }

    //AES分组长度为128位,所以blockSize=16,单位字节
    blockSize := block.BlockSize()
    iv := key[:blockSize] // 初始向量的长度必须等于块block的长度 16字节
    blockMode := cipher.NewCBCDecrypter(block, iv)
    origData := make([]byte, len(crypted))
    blockMode.CryptBlocks(origData, cipherText)

        length := len(origData)
    unpadding := int(origData[length-1])
    origData = origData[:(length - unpadding)]
    return origData, nil
}

func TestJsDecrypt(t *testing.T) {
    ikey := "5a673bd785831e2e5a673bd785831e2e"
    enstr := "ea17db2f3930c4f94b425141832f7f68"
    dd, err := DecryptCBC2(enstr, []byte(ikey), PaddingPkcs7)
    log.Println("DecryptCBC", string(dd), err)

        // hello world <nil>
}
cute-angelia commented 2 years ago

补充下, 上面回答是针对自己 js 和 golang 交互

如果是破解别人的aes加密后的密文,因为这个库没校验key长度 : https://github.com/brix/crypto-js/issues/293

所以只能以子之矛攻子之盾,用这个解出来,再发给 golang

VictorZhang2014 commented 1 year ago

This guy is super cool who has implemented the code snippet based on Golang, so that you can encrypt in Golang and decrypt in Javascript, vice versa.

check it here: https://github.com/Xiangrui2019/go-kahla-bot-server/tree/master/cryptojs https://pkg.go.dev/github.com/xiangrui2019/go-kahla-bot-server/cryptojs