【问题标题】:Encrypt AES string with Go and decrypt with Crypto-js使用 Go 加密 AES 字符串并使用 Crypto-js 解密
【发布时间】:2021-02-16 09:01:31
【问题描述】:

我正在我的 Go 应用程序中寻找加密字符串并使用 Crypto-js 解密编码的字符串。

我已经尝试了几个小时但没有成功,尝试了 Stackoverflow、github 或 gist 提供的许多解决方案。

如果有人有解决方案,他们会让我免于某种神经衰弱,哈哈

我的 Go 加密代码:

func EncryptBody() (encodedmess string, err error) {
  key := []byte("6368616e676520746869732070617373")

  // Create the AES cipher
  block, err := aes.NewCipher(key)
  if err != nil {
      panic(err)
  }
  plaintext, _ := pkcs7Pad([]byte("exampletext"), block.BlockSize())
  // The IV needs to be unique, but not secure. Therefore it's common to
  // include it at the beginning of the ciphertext.
  ciphertext := make([]byte, aes.BlockSize+len(plaintext))
  iv := ciphertext[:aes.BlockSize]
  if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    panic(err)
  }
  bm := cipher.NewCBCEncrypter(block, iv)
  bm.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)

  return fmt.Sprintf("%x", ciphertext), nil
 }

我的 pkcs7Pad 功能:

 func pkcs7Pad(b []byte, blocksize int) ([]byte, error) {
  if blocksize <= 0 {
      return nil, errors.New("invalid blocksize")
  }
  if b == nil || len(b) == 0 {
      return nil, errors.New("invalid PKCS7 data (empty or not padded)")
  }
  n := blocksize - (len(b) % blocksize)
  pb := make([]byte, len(b)+n)
  copy(pb, b)
  copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
  return pb, nil
}

我的 Crypto-JS 解密代码:

public decryptData() {
  const data = "3633fbef042b01da5fc4b69d8f038a83130994a898137bb0386604cf2c1cbbe6"
  
  const key = "6368616e676520746869732070617373"
  const decrypted = CryptoJS.AES.decrypt(data, key, {
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })

  console.log("Result : " + decrypted.toString(CryptoJS.enc.Hex))
  return decrypted.toString(CryptoJS.enc.Hex)
 }

【问题讨论】:

  • 为了解密,你剥离 IV 并将其用作解密的输入,但随后你将 complete 数据提供给“CryptoJS.AES.decrypt(data, key”) - 恕我直言,输入应该是剩余的数据(在切断 IV 之后)。由于我不是 Go 专家,加密看起来很奇怪 - 你是在结合 CBC 模式加密和 CFB 模式加密吗?如果是这样的话您还需要在 cryptojs 端扭转这一点。
  • 两种代码在功能上非常不同。在 CryptoJS 代码中,密钥作为字符串传递,这就是应用密钥派生函数的原因。为避免这种情况,必须使用 Utf8 编码器解析密钥。在 CryptoJS 代码中,由于是十六进制编码,IV 必须使用 32 个字符。此外,密文必须在没有 IV 的情况下传递给 CryptoJS.AES.decrypt()(迈克尔费尔的评论),并且还必须作为 CipherParams` 对象(或 Base64 编码)。
  • 在Go代码中,先进行了一次CBC加密,但是结果被后面的CFB加密覆盖了。 CFB 作为流密码模式不需要填充,但两种代码都使用填充。顺便说一句,CFB 并非不重要,因为库通常不会默认使用相同的段大小。在这里你很幸运,在这两种情况下都应用了 CFB128。
  • 您好,感谢您的回复。我已经用你的建议更新了我的代码,但没有结果。您能对我的新版本发表意见吗?
  • 感谢@Topaco 的帮助!

标签: go encryption cryptography aes cryptojs


【解决方案1】:

感谢@Topaco 的帮助!

解决方案:

转码:

func EncryptBody(data string) (encodedmess string, err error) {
  key := []byte("6368616e676520746869732070617373")

  // Create the AES cipher
  block, err := aes.NewCipher(key)
  if err != nil {
      panic(err)
  }
  plaintext, _ := pkcs7Pad([]byte(data), block.BlockSize())
  // The IV needs to be unique, but not secure. Therefore it's common to
  // include it at the beginning of the ciphertext.
  ciphertext := make([]byte, aes.BlockSize+len(plaintext))
  iv := ciphertext[:aes.BlockSize]
  if _, err := io.ReadFull(rand.Reader, iv); err != nil {
      panic(err)
  }
  bm := cipher.NewCBCEncrypter(block, iv)
  bm.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)


  return fmt.Sprintf("%x", ciphertext), nil

 }

NodeJS 代码:

protected decryptData(data: string) {

  const iv = CryptoJS.enc.Hex.parse(data.substr(0,32))
  const ct = CryptoJS.enc.Hex.parse(data.substr(32))
  const key = CryptoJS.enc.Utf8.parse("6368616e676520746869732070617373")
  // @ts-ignore !!!!!!!! IMPORTANT IF YOU USE TYPESCRIPT COMPILER
  const decrypted = CryptoJS.AES.decrypt({ciphertext: ct}, key, {
    mode: CryptoJS.mode.CBC,
    iv: iv
  })

  console.log("Result : " + decrypted.toString(CryptoJS.enc.Utf8))
  return decrypted.toString(CryptoJS.enc.Utf8)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-16
    • 2022-09-27
    • 2020-11-24
    • 2021-11-04
    • 2012-12-28
    • 2014-09-12
    • 2020-06-16
    相关资源
    最近更新 更多