跨平台AES 256 GCM Javascript和Elixir

3
我可以帮您翻译以下内容,涉及IT技术相关:

我一直在尝试使用AES 256与GCM在Javascript中进行加密,并在Elixir中进行解密。我从这里和那里借鉴了一些例子,得出了以下结论。

Javascript中的加密

"Original Answer" 翻译成中文为 "最初的回答"
const _crypto = require('crypto');

function encrypt(message, secret) {
  // random initialization vector
  const iv = _crypto.randomBytes(16);

  // extract the auth tag
  const cipher = _crypto.createCipheriv('aes-256-gcm', secret, iv);

  // encrypt the given text
  const encrypted = Buffer.concat([cipher.update(message, 'utf8'), cipher.final()]);

  // extract the auth tag
  const tag = cipher.getAuthTag();

  const encrypted_message = Buffer.concat([iv, tag, encrypted]).toString('base64');
  return encrypted_message;
}

const secret = _crypto.randomBytes(32);
encrypt("secret message", secret);

Decryption in Elixir

def decrypt(encrypted_message, secret) do
  secret_key = :base64.decode(secret)
  ciphertext = :base64.decode(encrypted_message)

  <<iv::binary-16, tag::binary-16, ciphertext::binary>> = ciphertext
  :crypto.block_decrypt(:aes_gcm, secret_key, iv, {"AES256GCM", ciphertext, tag})
end

# secret would be the secret from javascript encoded in base64
decrypt(encrypted_message, secret)

我的Elixir端结果一直是:error。我有一种感觉,那就是它与编码和解码有关,但我似乎找不到出了什么问题。

如果有人能指导我正确的方向,将不胜感激。

谢谢!

更新后的工作版本

对于那些打算使用相同语言的人:

Javascript加密

const _crypto = require('crypto');

function encrypt(message, secret) {
  // random initialization vector
  const iv = _crypto.randomBytes(16);

  // extract the auth tag
  const cipher = _crypto.createCipheriv('aes-256-gcm', secret, iv);

  // add the following line if you want to include "AES256GCM" on the elixir side
  // cipher.setAAD(Buffer.from("AES256GCM", 'utf8'));

  // encrypt the given text
  const encrypted = Buffer.concat([cipher.update(message, 'utf8'), cipher.final()]);

  // extract the auth tag
  const tag = cipher.getAuthTag();

  const encrypted_message = Buffer.concat([iv, tag, encrypted]).toString('base64');
  return encrypted_message;
}

const secret = _crypto.randomBytes(32);
encrypt("secret message", secret);

最初的回答:

解密Elixir

def decrypt(encrypted_message, secret) do
  secret_key = :base64.decode(secret)
  ciphertext = :base64.decode(encrypted_message)

  <<iv::binary-16, tag::binary-16, ciphertext::binary>> = ciphertext

  // make sure _AAD is an empty string "" if you didn't set it during encryption
  :crypto.block_decrypt(:aes_gcm, secret_key, iv, {_AAD, ciphertext, tag})

  // otherwise, you would need to set _AAD to whatever you set during encryption, using "AES256GCM" as example
  // Note: AAD (Associated Authenticated Data) can be whatever string you want to my knowledge, just to make sure you have the same in both encryption and decryption process
  // :crypto.block_decrypt(:aes_gcm, secret_key, iv, {"AES256GCM", ciphertext, tag})
end

# secret would be the secret from javascript encoded in base64
decrypt(encrypted_message, secret)
1个回答

2
这很简单:你的"AES256GCM"应该不出现(或为空,我对Erlang不是很熟悉)。它代表额外认证数据并包含在认证标记的计算中,显然使其与加密代码生成的认证标记不同。 :aes_gcm已经指定了模式,而密钥大小当然由secret_key的大小确定,因此这个字符串是完全不必要的。

当我将“AES256GCM”设置为“”时,它能正常工作,并且成功解码。我原以为它与JavaScript端的aes-256-gcm相对应。非常感谢! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接