当前位置: 首页 > 后端技术 > Python

基于wasm的openssl实践

时间:2023-03-26 15:33:12 Python

上一篇分享了WebAssembly的概念和基本使用,通过两个代码示例的分析对WebAssembly有了一个大概的了解。本文分享基于WebAssembly的加密工具实践。下面以openssl的摘要算法md5和sha1为例,在Mac上将openSSL编译成WebAssembly。环境Emscriptenversion2.0.3Opensslversion1.1.1dBrowserversion85.0.4183.121(officialversion)(64-bit)OverviewcompileopenSSLtoWebAssemblyonMac总结1.CompileopenSSLtoWebAssemblyonMacCompileOpenssltoWebAssembly整WebAssembly的流程是这样的,md5.c文件–>emscripten编译–>.wasm文件–>结合WebAssemblyJSAPI–>在浏览器中运行。1.md5.c文件//md5.c#include#include#include#include#includeEMSCRIPTEN_KEEPALIVEvoidmd5(char*str,char*result,intstrlen){MD5_CTXmd5_ctx;intMD5_BYTES=16;无符号字符md5sum[MD5_BYTES];MD5_Init(&md5_ctx);MD5_Update(&md5_ctx,str,strlen);MD5_Final(md5sum,&md5_ctx);炭温度[3]={0};内存集(结果,0,大小(字符)*32);对于(inti=0;i

计算md5
模块={};constmallocByteBuffer=len=>{constptr=Module._malloc(len)constheapBytes=newUint8Array(Module.HEAPU8.buffer,ptr,len)returnheapBytes}//点击导入按钮使文件触发点击事件,并然后完成读取文件的操作文件varselectedFile=document.getElementById('md5files').files[0];varname=selectedFile.name;//读取选中文件的文件名varsize=selectedFile.size;//读取选中文件的大小console.log("文件名:"+name+“尺寸:”+尺寸);varreader=newFileReader();//读取操作由它完成。reader.readAsArrayBuffer(selectedFile)reader.onload=function(){//读取完成时回调这个函数,然后将文件的内容存储到此时的result中,可以直接操作console.log(reader。结果);常量md5=Module.cwrap('md5',null,['number','number'])constinBuffer=mallocByteBuffer(reader.result.byteLength)varctx=newUint8Array(reader.result)inBuffer.set(ctx)constoutBuffer=mallocByteBuffer(32)md5(inBuffer.byteOffset,outBuffer.byteOffset,inBuffer.byteLength)控制台。log("md5value=",Array.from(outBuffer).map(v=>String.fromCharCode(v)).join(''))Module._free(inBuffer);Module._free(outBuffer);}}4。在浏览器中运行文件a.out,是一个二进制数据md5:0d3c57ec65e81c7ff6da72472c68d95bsha1:9ef00799a4472c71f2177fd7254faaaadedb0807一个是程序计算的md5和sha1,一个是系统上openssl计算的md5和sha1,说明用Webassembly编译openssl的实践是成功的。2.遇到的问题如下:md5.js(胶水代码)<----->md5.c<----->opensslAPI数据通信问题整个实践过程中,最头疼的问题是数据通信问题。在C/C++和JS之间传递复杂的数据结构很麻烦,需要内存操作才能实现。Javascript和C/C++交换数据typescript#md5.wasm解析wasm文件中的md5函数代码func$md5(;3;)(export"md5")(param$var0i32)(param$var1i32)(param$var2i32)因为wasm目前只能导入导出C语言函数式API,参数只有四种数据类型(i32、i64、f32、f64),都是数字,可以理解为裸二进制码,没有办法直接传递复杂类型和数据结构。因此,浏览器中的这些高级类型的API必须用JS封装,需要一种机制来跨语言转换复杂的数据结构。不管Module.buffer的编译目标是asm.js还是wasm,C/C++代码眼中的内存空间其实对应的是Emscripten提供的ArrayBuffer对象:Module.buffer、C/C内存地址和Module。缓冲区数组下标一一对应。functionmd5fileImport(){varselectedFile=document.getElementById('md5files').files[0];varname=selectedFile.name;//读取选中文件的文件名varsize=selectedFile.size;//读取选中的文件文件的大小console.log("文件名:"+name+"size:"+size);varreader=newFileReader();//这是核心,读操作由它完成。reader.readAsArrayBuffer(selectedFile).....}在代码中,我们使用reader.readAsArrayBuffer()来读取文件并返回一个ArrayBuffer数组。但是还是不能调用C函数,需要创建一个类型化的数组,比如Int8Array,UInt32Array,用它的特定格式作为这段二进制数据的视图,从而进行读写操作。Tips:C/C++代码可以直接通过地址访问的数据都在内存中(包括运行时堆,运行时栈),内存对应Module.buffer对象,C/C代码可以直接访问的数据访问实际上仅限于Module.buffer内部。WebAssembly的内存也是一个ArrayBuffer,Emscripten封装的Module提供了Module.HEAP8、Module.HEAPU8等各种视图。附图:JavaScript中访问C/C++内存计算md5/sha1需要javascript向C/C++环境输入大量数据,而C/C++无法预测数据块的大小。这时可以在JavaScript中分配和加载内存,然后传入数据指针调用C函数进行处理。Tips:这种用法可行的核心原因是:Emscripten导出了C的malloc()/free(),我把分配内存空间的方法声明为public方法。Module={};constmallocByteBuffer=len=>{constptr=Module._malloc(len)constheapBytes=newUint8Array(Module.HEAPU8.buffer,ptr,len)returnheapBytes}functionmd5fileImport(){//获取读取的我的文件的文件对象varselectedFile=document.getElementById('md5files').files[0];......varreader=newFileReader();//这里是核心,读取操作由它完成。reader.readAsArrayBuffer(selectedFile)reader.onload=function(){//读取完成后回调此函数,此时将文件内容存入result,直接操作constmd5=Module.cwrap('md5',null,['number','number'])constinBuffer=mallocByteBuffer(reader.result.byteLength)varctx=newUint8Array(reader.result)inBuffer.set(ctx)constoutBuffer=mallocByteBuffer(32)md5(inBuffer.byteOffset,outBuffer.byteOffset,inBuffer.byteLength)console.log("md5value=",Array.from(outBuffer).map(v=>String.fromCharCode(v)).join(''))Module._free(inBuffer);Module._free(outBuffer);}}Tips:C/C++内存没有gc机制。JavaScript中使用malloc()函数分配的内存后,需要使用free()释放。此外,Emscripten还提供了AsciiToString()/stringToAscii()/UTF8ArrayToString()/stringToUTF8Array()等一系列辅助函数,用于处理各种存储对象中各种格式的字符串的转换。详情请参考胶水代码。3、总结openssl基于wasm的完整调用关系:本次实践中遇到的技术问题是数据通信的问题,另外一个问题是思路的问题。一直以为把openssl整体编译成.wasm文件就可以用了嘛,结果发现在web中使用还是需要胶水代码。那我有个问题。.wasm文件本质上是一个二进制文件。有没有可以直接运行的工具?.wasm文件,WAPM(WebAssemblyPackageManager)是WebAssembly的包管理工具。下一篇文章我们一起来认识一下WebAssembly包管理工具吧。.参考资料示例代码地址:https://github.com/likai1130/...WebAssemblyAPI(中文,解决逻辑JS调用wasm问题。):https://developer.mozilla.org...Emscripten语法学习(解决C语言调用JS语法问题):https://emscripten.org/docs/a...openssl编译参考https://github.com/wapm-packa...Netwarps由国内资深的云计算和分布式技术组成开发团队在金融、电力、通信、互联网等行业具有丰富的落地经验。网华科技目前在深圳和北京设有研发中心,团队规模30+,大部分是具有十年以上开发经验的技术人员,来自互联网、金融、云计算、区块链、科研机构。Netwarps专注于安全存储技术产品的开发和应用。主要产品有去中心化文件系统(DFS)和去中心化计算平台(DCP)。致力于提供分布式存储和基于去中心化网络技术的分布式存储。该计算平台具有高可用、低功耗、低网络的技术特点,适用于物联网、工业互联网等场景。公众号:网经