在ruby中使用sjcl.js创建的AES解密
嗨,假设客户端有一个密钥不通过与加密数据相同的通道传输。
我想要完成的是在ruby中解密Stanford Javascript Crypto Library(sjcl)的结果。 或者用于具有支持AES的加密库的任何其他语言的泛化。
这是我在javascript中所做的事情:
sjcl.encrypt('stack-password', 'overflow-secret')
这就是我得到的回报:
{ "iv": "Tbn0mZxQcroWnq4g/Pm+Gg", "v": 1, "iter": 1000, "ks": 128, "ts": 64, "mode": "ccm", "adata": "", "cipher": "aes", "salt": "pMQh7m9Scds", "ct": "H6JRpgSdEzKUw2qEO1+HwIzAdxGTgh0" }
所以我实际要问的是,我需要哪些参数(假设服务器已经有“stack-password”密钥)才能解密秘密服务器端,我应该使用哪个库? 可能有AES解密库是不够的?
对于那些来自谷歌的人,我设法使用sjcl库加密Appcelerator的Titanium并在Ruby / Rails上解密。
加密(javascript):
var data = SJCL.encrypt('your key here', 'plain text', { mode: 'gcm', iv: SJCL.random.randomWords(3, 0) });
重要的是使用较小的IV。
解密(ruby):
def self.decrypt(h) h = HashWithIndifferentAccess.new(JSON.parse(h)) key = OpenSSL::PKCS5.pbkdf2_hmac('your key here', Base64.decode64(h[:salt]), 1000, h[:ks]/8, 'SHA256') puts "Key: #{key.unpack('H*')}" puts "Salt: #{Base64.decode64(h[:salt]).unpack('H*')}" c = OpenSSL::Cipher.new("#{h[:cipher]}-#{h[:ks]}-#{h[:mode]}") c.decrypt c.key = key c.iv = Base64.decode64(h[:iv]) puts "IV: #{Base64.decode64(h[:iv]).unpack('H*')}" c.auth_data = "" c.update(Base64.decode64(h[:ct])) end
以下内容无法协商(或硬编码)。
-
ct
:显然是加密数据的加密文本 -
iv
:初始化向量,应该是唯一的,不能与AES-CCM使用相同的密钥重用 -
salt
:random,用于通过Pbkdf2从密码创建密钥 -
adata
:其他经过身份validation的数据,是您要包含的纯文本数据,但要确保在使用AES-CCM时未被篡改。 如果你不打算包含任何数据,那么你可以忽略它(你必须用sjcl中的明文传递它)。
以下您可以协商一个时间段(或硬编码),实际上您不应该在服务器加密api中插入这些值,当传输未经身份validation并期望安全性时。 如果您希望adata
可以根据客户端进行更改,那么adata
对于v
, iter
或ks
来说不会是一个糟糕的地方
-
iter
:对于Pbkdf2的迭代, 这只需要足够高以减慢你的密码的暴力需要随着未来的硬件速度而改变。 -
ks
:keysize知道用Pbkdf2生成什么大小的密钥,需要随着未来的安全量而改变 -
ts
:tagsize以了解认证标记的大小是密文的一部分 -
cipher
:如果您只支持AES,那么您可以假设。 -
mode
:如果您只支持AES-CCM ,那么您可以假设。 -
v
:如果你将来只支持一个版本的sjcl,那么你可以假设。
使用OpenSSL库的 ruby似乎只要你的OpenSSL支持AES-128-CCM
puts OpenSSL::Cipher.ciphers
进行检查。 它确实支持使用pbkdf2生成密钥 ,但您需要使用Sha256摘要与sjcl兼容,这又取决于您的openssl版本。
或者,我将SJCL的翻译写入纯Ruby(至少对于CCM部分)。 这不需要更新OpenSSL,但速度有点慢。
您可以在https://github.com/mdp/sjcl_rb找到它
希望这可以帮助