【问题标题】:Cross Platform AES 256 GCM Javascript & Elixir跨平台 AES 256 GCM Javascript 和 Elixir
【发布时间】:2019-09-14 00:53:33
【问题描述】:

我一直在尝试使用带有 GCM 的 AES 256 在 Javascript 中加密并在 Elixir 中解密。我从这里和那里借用了一些例子,并想出了以下内容。

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);

  // 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
  :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);

灵药解密

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)

【问题讨论】:

    标签: javascript react-native cryptography erlang elixir


    【解决方案1】:

    这很简单:你的"AES256GCM" 不应该出现(或者为null,我对Erlang 不太熟悉)。它代表了额外的认证数据,并包含在认证标签的计算中,显然与加密代码生成的认证标签不同。

    :aes_gcm已经指定了模式,密钥大小当然是由secret_key的大小决定的,所以无论如何这个字符串是不必要的。

    【讨论】:

    • 有效!当我将“AES256GCM”设置为“”时,它成功解码。我认为它在那里与 javascript 端的aes-256-gcm 相对应。非常感谢!!
    猜你喜欢
    • 2021-09-23
    • 2018-10-29
    • 1970-01-01
    • 2021-04-12
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2019-02-27
    相关资源
    最近更新 更多