我试图用sjcl解密Ruby生成的AES密码.js库.

我收到一个"腐败"错误,原因未知…….我想解决这个问题.

作为参考,在CBC模式下try 加密和解密时,解密成功.

Ruby代码:

cipher = OpenSSL::Cipher.new('aes-256-gcm')
cipher.encrypt
iv = cipher.random_iv
cipher.key = Digest::SHA256.digest(password)
ciphertext = cipher.update(plaintext) + cipher.final
return Base64.strict_encode64(iv) + Base64.strict_encode64(ciphertext)

Javascript代码:

var iv = sjcl.codec.base64.toBits(IV_BASE64);
var ciphertext = sjcl.codec.base64.toBits(CIPHERTEXT_BASE64);
var key = sjcl.hash.sha256.hash(KEY_UTF8);
var decrypted = sjcl.mode.gcm.decrypt(new sjcl.cipher.aes(key), ciphertext, iv);

推荐答案

AES-GCM是一种经过身份验证的加密算法.它在加密期间自动生成身份验证标记,用于解密期间的身份验证.当前Ruby代码中考虑了not个标记.默认为16字节,可使用cipher.auth_tag检索,必须添加,例如:

ciphertext = cipher.update(plaintext) + cipher.final + cipher.auth_tag 

关于nonce/IV,请注意,Base64编码实际上应该进行after次串联(然而,对于GCM常用的12字节nonce/IV来说,这并不重要).


在JavaScript方面,缺少nonce/IV的分离.密文和标记不需要分开,因为sjcl处理两个(密文|标记)的串联:

const GCM_NONCE_LENGTH = 12 * 8
const GCM_TAG_LENGTH = 16 * 8

// Separate IV and ciptertext/tag combination
let ivCiphertextTagB64 = "2wLsVLuOJFX1pfwwjoLhQrW7f/86AefyZ7FwJEhJVIpU+iG2EITzushCpDRxgqK2cwVYvfNt7KFZ39obMMmIqhrDCIeifzs="
let ivCiphertextTag = sjcl.codec.base64.toBits(ivCiphertextTagB64)
let iv = sjcl.bitArray.bitSlice(ivCiphertextTag, 0, GCM_NONCE_LENGTH)
let ciphertextTag = sjcl.bitArray.bitSlice(ivCiphertextTag, GCM_NONCE_LENGTH)

// Derive key via SHA256
let key = sjcl.hash.sha256.hash("my password")  

// Decrypt
let cipher = new sjcl.cipher.aes(key)
let plaintext = sjcl.mode.gcm.decrypt(cipher, ciphertextTag, iv, null, GCM_TAG_LENGTH)
//let plaintext = sjcl.mode.gcm.decrypt(cipher, ciphertextTag, iv) // works also; here the defaults for the AAD ([]) and the tag size (16 bytes) are applied 
console.log(sjcl.codec.utf8String.fromBits(plaintext))
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sjcl/1.0.8/sjcl.min.js "></script>

上述代码中使用的密文是在考虑身份验证标记的情况下使用Ruby代码生成的,并且已成功解密.

请注意,带有摘要的密钥派生是不安全的.相反,应该使用可靠的密钥派生函数,如PBKDF2.

Ruby相关问答推荐

Ruby 中的 Float#floor 和 Float#to_i 有什么区别?

使用 Ruby,我如何访问和比较这些嵌套的数组值?

如何使用 gsub 删除返回字符串中的/和/i?

VS Code Prettier 打破哈希访问

如何在 rspec 中使用 `eq` 匹配器和 `hash_include` 匹配器来获取哈希数组

如何在 Ruby 中合并多个哈希?

如何找到安装 Ruby Gem 的路径(即 Gem.lib_path c.f. Gem.bin_path)

ruby命令在我的 Mac 上没有任何作用

如何在控制台中禁用 MongoDB 日志(log)消息?

Ruby:继承与类变量一起工作的代码

Ruby 哈希默认值行为

在 Ruby 中取消定义变量

. vs ::(点与双冒号)用于调用方法

从命令行使用Bundle 器将 gem 添加到 gemfile

获取下周一(或一周中的任何一天)的日期的 Ruby 代码

Ruby 中的 %w{} 和 %W{} 大写和小写百分比 W 数组文字有什么区别?

如何使用 Nokogiri 删除 node ?

Ruby 实例变量何时设置?

使用正则表达式进行 Ruby Electron邮件验证

`gem install therubyracer` 在 Mac OS X Lion 上失败