首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Javascript: AES加密速度慢

Javascript: AES加密速度慢
EN

Stack Overflow用户
提问于 2017-06-01 09:32:01
回答 2查看 2.2K关注 0票数 0

我使用锻造作为加密库,用于gulp脚本(执行加密)和前端脚本(在浏览器中进行解密)。

这台计算机是一个i5-6200 U w/ 16 10的内存,对称的enc大约需要10秒。或者解密一个15 or的json文件。

我真正的问题是解密时间对用户来说太长了(多个文件可以加载和解密这个系统上的30s+ )。

我肯定遗漏了一些关键元素(缓冲区或.无论我在这个领域缺乏经验,都可能会错过)。下面的代码有什么明显的错误吗?感谢您的关注。

  1. 获取数据 函数逻辑(Url){返回新的承诺((解决,拒绝) => { var xhr =新的XMLHttpRequest();xhr.onload =函数(事件){xhr.response;};xhr.onreject = function (err) {err(Err);} xhr.open('GET',url);xhr.send();}};
  2. 解密数据 load('data/dicom.json').then(字节=> { const tIn =新日期().getTime();const tIn=“getForge()”;const pwd = "aStringPassword";const iv = getInitVector();const tIn= getSalt();const key =bean.pkcs5.pbkdf2(pwd,salt,100,16);var = forge.cipher.createDecipher('AES-CBC',key);decipher.start({iv: iv});decipher.update(forge.util.createBuffer(bytez));decipher.finish();const tOut = decipher.output.getBytes();const tOut=新日期().getTime();console.log(decrypted in ${(tOut - tIn) / 1000 }s);// 10s为15 for的json文件返回clear;};
EN

回答 2

Stack Overflow用户

发布于 2017-06-02 04:10:09

伪造至少0.7.1使用字符串作为其内部缓冲区实现。(这段代码早于现代缓冲API和未来的Forge版本将使用更新的API。)这在处理大型输入时会产生一些后果。当输出字符串缓冲区在处理过程中变得更大时,内部JavaScript VM只需执行字符串处理就可以减慢速度。避免这种情况的一种方法是使用Forge的流功能,以便字符串缓冲区操作使用更大的数据块。输入可以用update()进行块处理,并在此过程中手动构建输出。使用getBytes()获取输出块将清除输出缓冲区,并允许Forge内部组件更有效地运行。使用这些块构建自己的输出不会产生相同的性能影响。

编写测试是为了检查使用单个update()调用、多个update()调用和本机节点API解密大型缓冲区的情况。当输入大小从1M增加到20M时,单个update()调用对本地节点API的速度从~8倍下降到了50倍以上!但是,如果使用流处理,则减速可能仅为4.6x,而不明显依赖于输入大小!对于您的15M输入大小,这等于~0.75s vs ~10.31s。作为比较,节点为~0.15s,WebCrypto API可能类似。(从I7-4790K开始计时)

还编写了一个测试,以查看块大小如何影响结果。在处理大输入时,~64k似乎是使用node.js进行优化的。根据JavaScript、VM和其他因素,这可能是不同的。关键是使用任意块大小的流(甚至是1M!)提供改进,以避免线性缓冲区减速,因为输入的大小增加。

一个具有更好和更稳定性能的示例:

代码语言:javascript
复制
const decipher = forge.cipher.createDecipher('AES-CBC', key);
decipher.start({iv: iv});
const length = bytes.length;
const chunkSize = 1024 * 64;
let index = 0;
let clear = '';
do {
  clear += decipher.output.getBytes();
  const buf = forge.util.createBuffer(bytes.substr(index, chunkSize));
  decipher.update(buf);
  index += chunkSize;
} while(index < length);
const result = decipher.finish();
assert(result);
clear += decipher.output.getBytes();

代码的另一个问题是,您希望避免在主JS线程上执行CPU密集型代码。流API将允许您通过setImmediate() (如果可用的话)或setTimeout()运行每个setImmediate()调用。这将允许用户在处理过程中与浏览器进行交互。如果您还可以流输入数据获取,那么您可以开始处理时,数据正在通过网络。更新原始代码以完成此操作是留给读者的练习。在这种情况下,更小的块大小可能有助于UI的交互性。

最后,应该注意的是,本地API可能总是比Forge更高性能。当前的WebCrypto API不提供流API,但是它的性能可能足够高,在这个用例中可能不是问题。值得一试,看看什么是最有效的。

还要注意,您应该检查decipher.finish()返回值。

加密具有与大量输入相同的缓冲区问题,并且可以使用与上面的代码相同的模式。

对于那些在未来阅读这篇文章的人来说:更新的web和Forge改进可能大大改变了性能结果。

票数 4
EN

Stack Overflow用户

发布于 2017-06-01 13:27:13

目前还不清楚,但是代码运行在基准页上,如下所示,运行速度要慢得多:(可在此获得资源)

代码语言:javascript
复制
   /*** encrypt */  
   var input = forge.util.createBuffer("plaintext");  
   var cipher = forge.aes.startEncrypting(key, iv);  
   cipher.update(input);  
   var status = cipher.finish();  
   var ciphertext = cipher.output.data;  

测试通过网页运行:35 my,相同的数据在我的吞咽脚本:165 my。目前还不知道原因。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44303784

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档