【问题标题】:Crypto JS: Can you slow down decryption, without an exponential file size increase?Crypto JS:你能在不增加文件大小的情况下减慢解密速度吗?
【发布时间】:2021-04-05 18:50:53
【问题描述】:

我有以下:

let original = 'something'
let passphrase = uuidv4()

// will take place on the server
let encrypted = CryptoJS.AES.encrypt(original, passphrase)

// will take place on the browser
// I want this part to take  ≈ 10 minutes *minimum*
let decrypted = CryptoJS.AES.decrypt(encrypted, passphrase)

我尝试了一种迭代方法。控制所需的解密迭代意味着您还可以在一定程度上控制解密时间:

// increase this until we reach the desired decryption time on the browser
let numberOfEncryptions = 2

// will take place on the server
let encrypted = CryptoJS.AES.encrypt(original, passphrase).toString()

let i = 0

while (i < numberOfEncryptions) {
  encrypted = CryptoJS.AES.encrypt(encrypted, passphrase).toString()
  i++
}


// will take place on the browser:

let decrypted = CryptoJS.AES.decrypt(encrypted, passphrase).toString(CryptoJS.enc.Utf8)

i = 0

while (i < numberOfEncryptions) {
  decrypted = CryptoJS.AES.decrypt(decrypted, passphrase).toString(CryptoJS.enc.Utf8)
  i++
}

await checkWithServer(decrypted) // returns true

结果令人失望。

增加服务器上的加密次数也会增加浏览器上的解密时间,这很棒,因为这正是我想要的。

但它也成倍地增加了加密文件的大小,这太可怕了,因为用户不可能下载这么大的文件来解密它。

还有其他解决办法吗?

更新:

@SlavaKnyazev 建议我应该对用于加密数据的密码进行加密,并向最终用户发送提示,让他们暴力破解密码。

用户将花时间暴力破解密码,而不是花时间解密数据本身。

这就是我尝试实现的方式(作为测试):

  const KEY = 'ab' // uuidv4()
  const dataToEncrypt = 'The Message'
  const md5key = CryptoJS.MD5(KEY).toString()
  const encrypted = CryptoJS.AES.encrypt(dataToEncrypt, md5key)

  const sha1keyHint = CryptoJS.SHA1(KEY).toString()

  let pool = 'abcdefghijklmnopqrstuvwxyz'.split('')
  let before = Date.now()
  let after
  let md5keyFromHint

  bruteForce(pool, (value) => {
    if(CryptoJS.SHA1(value).toString() === sha1keyHint) {
      md5keyFromHint = CryptoJS.MD5(value).toString()
      after = Date.now()
      console.log(`KEY is ${value}`)
      console.log(`Found after ${(after - before) / 1000} seconds`)
      return true
    }
    return false
  })

  const decrypted = CryptoJS.AES.decrypt(encrypted, md5keyFromHint).toString(CryptoJS.enc.Utf8)
  console.log(dataToEncrypt === decrypted) // returns true

我发现KEY 必须相当“简单”,而不是我最初想的uuidv4()。否则,它可能需要永远。另外,我使用的 brute)forcing 方法需要一个字符“池”来查看,我猜池越大,需要的时间越长。

我的问题再次是用户不会花时间解密实际数据。所以感觉就像是 PoW,即伪装。

但我会考虑这次回答的问题,并会在此停止。 :-)

我最初的目标显然是不可能的。感谢您的帮助。

【问题讨论】:

  • 您能否详细说明为什么您需要这个?可能有更好的方法。
  • 我猜你没有把Rani's advice from the previous question放在心上:“不要向用户提供完整的解密密码。只提供部分密钥,让他们猜测/搜索其余的关键。”
  • 我做到了,但现在交给我的要求是这个最短时间限制。无论我要求用户解密什么类型的数据,我如何控制它?希望这篇文章的格式更清晰,而不仅仅是重复:)
  • @SlavaKnyazev 我更新了更多细节

标签: javascript encryption cryptography cryptojs brute-force


【解决方案1】:

不要给出密钥,给出密钥的哈希值。暴力破解密钥的长度将为您提供所需的粒度。

加密过程:

  1. 生成密钥(例如:hunter2)并使用它加密您的数据。
  2. Hash Hunter2 使用 SHA1 等算法 (f3bbbd66a63d4bf1747940578ec3d0103530e21d)
  3. 让客户端暴力破解密钥

密钥越长,找到它所需的时间就越长,而有效负载的大小保持不变。

但是,这有一个缺陷 - 暴力破解不是必需的,因为暴力破解 AES 加密将同样简单明了。这可以通过将密钥设置为哈希来解决。

不使用“hunter2”,而是使用MD5(hunter2)(使用不同的算法)加密您的数据。

在哈希中添加一些盐以防止彩虹表的有效使用。

伪代码:

// Encrypt
let key = "password";
let aesKey = md5(password);
let hint = sha1(password);

let encryptedData = data.encrypt(aesKey);

let decryptedData = data.decrypt(md5(bruteForceSha1(hint));

【讨论】:

  • 如果可能的话,您能否为我提供一个简短的示例(在 Javascript 中),其中交给用户的密钥然后被暴力破解(使用某种方法)以及暴力破解所需的时间在普通浏览器/机器上完成大约 10-20'。如果太多了,无论如何我都会接受你的回答:-)(我不会再问另一个 OP - 很抱歉产生噪音)
  • 我的 CryptoJs 知识非常有限
  • 如何“在哈希中加入一些盐”?还有一个好的 Js 暴力破解模块可以用来测试吗? :)
  • 加盐哈希意味着在值中添加一个常量。这是因为hunter2的hash值是众所周知的,可以在数据库中查到。 “hunter2sfsavvgdarfsaf”的哈希值不是。
  • 哈希在本地被暴力破解,无需提出任何请求。
猜你喜欢
  • 2019-01-12
  • 2014-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多