我使用锻造作为加密库,用于gulp脚本(执行加密)和前端脚本(在浏览器中进行解密)。
这台计算机是一个i5-6200 U w/ 16 10的内存,对称的enc大约需要10秒。或者解密一个15 or的json文件。
我真正的问题是解密时间对用户来说太长了(多个文件可以加载和解密这个系统上的30s+ )。
我肯定遗漏了一些关键元素(缓冲区或.无论我在这个领域缺乏经验,都可能会错过)。下面的代码有什么明显的错误吗?感谢您的关注。
decrypted in ${(tOut - tIn) / 1000 }s);// 10s为15 for的json文件返回clear;};发布于 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!)提供改进,以避免线性缓冲区减速,因为输入的大小增加。
一个具有更好和更稳定性能的示例:
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改进可能大大改变了性能结果。
发布于 2017-06-01 13:27:13
目前还不清楚,但是代码运行在基准页上,如下所示,运行速度要慢得多:(可在此获得资源)
/*** 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。目前还不知道原因。
https://stackoverflow.com/questions/44303784
复制相似问题