当前位置: 首页 > Web前端 > JavaScript

crypto-js-wasm:当crypto-js遇上WebAssembly

时间:2023-03-27 17:14:19 JavaScript

提到WebAssembly(简称Wasm)技术,你会想起什么?“新技术”、“在新闻中看到”、“需要用非JS语言编写”,还是“根本没听说过”?那么,今天我们就来介绍一个Wasm技术实践:crypto-js-wasm。什么是WebAssembly(Wasm)?Wiki上对Wasm的定义是:WebAssembly或wasm是一种实验性的低级编程语言,应用于浏览器中的客户端。WebAssembly是一种可移植的抽象语法树[1],旨在提供比JavaScript更快的编译和执行。WebAssembly将允许开发人员使用他们熟悉的编程语言(最初针对C/C++)进行编译,然后使用虚拟机引擎在浏览器中执行。简单地说,Wasm使开发人员能够使用Javacript以外的语言开发可以在浏览器或Node.js中运行的二进制应用程序。Wasm技术的优势那么,为什么我们使用其他编程语言通过Wasm而不是JS来开发前端应用呢?Wasm官网列出了它的几个优点,其中最重要的两个是:性能:JS作为一种解释型语言,性能自然不如以二进制形式提前编译好的Wasm。应用安全:Wasm提供了一个内存安全的沙箱运行环境。与JS不同,Wasm代码的运行过程是不可见的。另外,从Wasm官网提供的Roadmap可以看出,Wasm的大部分标准API已经被目前主流浏览器(Chrome、Firefox、Safari)和Node.js所采用,也就是说主流JavaScript运行时环境现在支持Wasm。目前,支持编译为Wasm二进制的编程语言包括:C/C++、Rust、AssemblyScript(一种专门为Wasm编写的类TypeScript语言)、C#、Go等(具体列表)。Wasm技术的劣势那么,Wasm技术是否完全超越了JavaScript?当然不是。目前,Wasm还存在以下不足:Wasm应用的运行时内存与JS隔离,因此在开始运行前,需要将内存从JS运行时复制到Wasm运行时,运行后再从Wasm复制到JS。中间的工作主要是通过“胶水代码”来实现的。虽然Wasm的运行速度优于JavaScript,但内存复制非常耗时。在再次使用Wasm应用程序之前,需要将应用程序转换为二进制,然后通过JS运行时(浏览器或Node.js)提供的API加载到应用程序中。JS运行时的Wasm技术目前还不成熟,各种生态有待完善,开发体验有待提升。换句话说,尽管Wasm运行速度比JavaScript快,但如果开发者为一个应用程序重复调用Wasm,则频繁启动会耗费时间。通过内存复制操作,Wasm应用程序可以比JavaScript运行得更慢。总结总结起来,Wasm的特点是:安全。与JavaScript相比,Wasm在运行时具有不可见的内存,执行更安全的内存复制操作的速度更慢。因此,为了获得比JS更好的性能,应该尽可能减少对Wasm应用程序的调用次数。结合这些特点,我们认为该加密算法非常适合Wasm应用:该加密算法计算量大,性能要求高;并且加密算法可以通过一次输入,进行复杂的计算后得到输出,调用次数少;通过加密算法对运行时安全性也有一定的要求。在加密算法方面,已经有另外一款基于JS加密算法的开源软件crypto-js,在npm上下载量非常大。crypto-js支持主流的哈希算法(如SHA-256、SHA-3、MD5等)、加密算法(AES、RC4等),以及一些编码和填充算法。因此,我们在功能比较完善的crypto-js的基础上,结合Wasm技术开发了crypto-js-wasm。Crypto-js-wasm简介除了使用Wasm技术,我们还按照ES6标准重写了crypto-js,并增加了jest测试、大宝等。目前crypto-js-wasm已经在npm上发布了1.0.0版本,它支持所有现有的crypto-jsAPI接口。可以通过npm命令安装crypto-js-wasm:npminstall@originjs/crypto-js-wasm由于Wasm技术的限制(前面介绍过),不像crypto-js,在使用crypto-js-wasm之前算法,需要异步加载一次(justonce)对应的Wasm二进制,也可以直接调用一次我们提供的loadAllWasm来加载所有算法的Wasm二进制:importCryptoJSWfrom'crypto-js-wasm';//(可选)加载所有wasm文件awaitCryptoJSW.loadAllWasm();//通过异步/等待语法调用awaitCryptoJSW.MD5.loadWasm();constrstMD5=CryptoJSW.MD5('message').toString();console.log(rstMD5);//CryptoJSW.SHA256.loadWasm().then(()=>{constrstSHA256=CryptoJSW.SHA256('消息').toString();console.log(rstSHA256);})Benchmarkfor为了测试我们写的crypto-js-wasm的性能,我们还专门开发了一个Benchmark,方便在浏览器和Node.js中进行性能测试(你可以下载源码后在本地运行测试);通过我们提供的在线Benchmark,可以直接在浏览器中进行性能测试。在我们的测试设备(台式机、i5-4590、16GBRAM、Windows10Version21H2(OSBuild19044、1466))上,crypto-js-wasm和crypto-js的性能比较如下:可以看到ChromeFirefoxNode.js发现crypto-js-wasm在大部分场景下都有性能提升,在一些更复杂的算法中甚至可以实现16倍以上的性能提升。同时,得益于Wasm技术,crypto-js-wasm的运行时内存是不可见的,一定程度上提高了加密算法的安全性(当然内存还是需要通过胶水代码进行交换)用JavaScript写的,所以只是加密过程内存不可见,并不是整个过程内存不可见)。综上所述,各位用过crypto-js,或者需要使用JavaScript加密算法的开发者,欢迎试用crypto-js-wasm。未来我们还计划在crypto-js-wasm中提供更复杂的加密算法,比如RSA。欢迎大家积极提交Issue和PR!