当前位置: 首页 > article >正文

WASM实现加密与算法保护

随着互联网技术的发展,Web应用的安全性越来越受到开发者的重视。在Web应用中,客户端加密是一个重要的安全措施,它能够确保数据在传输过程中的安全性。然而,传统的JavaScript(JS)加密方式存在一个明显的缺点:加密算法容易被反向工程,因为JS代码是明文形式发送给用户的浏览器,任何有心人都可以轻松地通过浏览器的开发者工具查看和调试这些代码。

传统JS加密的问题

当我们在Web前端使用JS实现加密算法时,虽然可以在一定程度上保护数据的安全,但是加密算法本身的安全性却得不到保障。攻击者可以通过阅读源码来理解加密逻辑,进而尝试破解或模拟加密过程,这为安全带来了隐患。为了应对这一挑战,开发者们尝试了多种方法,如代码混淆、加密JS代码等,但这些方法的效果有限,且容易被经验丰富的攻击者破解。

WASM带来的解决方案

WebAssembly (WASM) 是一种新的编码格式,设计用于在现代Web浏览器中实现高性能的应用程序。与JS不同,WASM是一种二进制格式,其代码更加紧凑且执行效率更高。更重要的是,WASM提供了一种更为安全的方式来处理敏感操作,比如加密算法的实现。

  • 性能优势:WASM的执行速度远超JS,这对于计算密集型任务(如加密操作)尤为重要。
  • 安全性提升:由于WASM是以二进制形式分发的,即使攻击者获取了WASM文件,也很难直接读取和理解其中的逻辑。此外,WASM运行在一个沙箱环境中,进一步增强了安全性。

下面举个例子

index.html

< !DOCTYPE html >
	<html lang="en">
		<head>
			<meta charset="UTF-8">
				<meta name="viewport" content="width=device-width, initial-scale=1.0">
					<title>WebAssembly String Processing</title>

				</head>
				<body>
					<h1>WebAssembly String Processing</h1>
					<input type="text" id="inputString" placeholder="Enter string" value="a的">
						<button id="convertButton">encrypt</button>
						<p id="result"></p>
						<script src="./encrypt.js"></script>
						<script>
							let moduleInstance;
							const key = 1; // Example key for XOR

        createModule().then(instance => {
								moduleInstance = instance;
			//console.log(moduleInstance.allocateUTF8("a"))
           // document.getElementById('convertButton').onclick = () => {

								function showChatCode(input) {
									for (let i = 0; i < input.length; i++) {

										console.log(String.fromCharCode(input.charCodeAt(i)), input.charCodeAt(i));
									}

								}
			
			function bytesToString(bytes) {
				const decoder = new TextDecoder('utf-8'); // 默认使用 UTF-8 编码
							return decoder.decode(new Uint8Array(bytes));
			}

							function showChatCode2(input){
								let cc= [];
							for (let i = 0; i < input.length; i++) {
								cc.push(input[i] ^ key);
					}
							return cc;
			}
							function unsigned(signedNumber){
				return (signedNumber + 256) % 256;
			}

							const inputString = document.getElementById('inputString').value;
							var ptr1 = instance.allocate(instance.intArrayFromString(inputString), instance.ALLOC_NORMAL);
							//var ptr =moduleInstance.allocateUTF8(inputString);
							console.log(instance.intArrayFromString(inputString))
							console.log(bytesToString(showChatCode2(showChatCode2(instance.intArrayFromString(inputString)))))

							console.log("----")
							showChatCode(instance.UTF8ArrayToString(instance.intArrayFromString(inputString)))
							console.log("----")

							//showChatCode(inputString)
							console.log("----1")

							// Call the C++ function
							//const encryptedPtr = moduleInstance._encode_int(ptr1,instance.intArrayFromString(inputString).length-1, key);
							const encryptedPtr = moduleInstance._encode(ptr1,key);
							const encryptedString = moduleInstance.UTF8ToString(encryptedPtr);
							showChatCode(encryptedString)
							console.log("----2")


							// 创建 JavaScript 数组
							let array = [],cur;
							for (let i = 0; cur!==0; i++) {
								cur = moduleInstance.getValue(encryptedPtr + i * 1, 'i8');
							if(cur<0)cur=unsigned(cur)
							array.push(cur^ key); // 读取每个整数
            }
							console.log("----3")
							console.log(bytesToString(array))
							console.log("----4")

							document.getElementById('result').innerText = `Encrypted: ${encryptedString}`;

							// Free the allocated memory

							function xorEncryptDecrypt(input, key) {
					const output = [];
							for (let i = 0; i < input.length; i++) {
								output.push(String.fromCharCode(input.charCodeAt(i) ^ key));
					}
							return output.join('')
				}
							showChatCode(xorEncryptDecrypt(encryptedString,key))
							//console.log(xorEncryptDecrypt(encryptedString,key))
							//let xx = xorEncryptDecrypt("发大水",key);
							//console.log(xx);
							//console.log(xorEncryptDecrypt(xx,key))
							//console.log(xorEncryptDecrypt(encryptedPtr,key))
							moduleInstance._free_string(encryptedPtr);
				/*
                const inputString = moduleInstance.allocateUTF8(document.getElementById('inputString').value);

                // 调用 C++ 函数ptr = allocateUTF8("你好,Emscripten!");
                const upperPtr = moduleInstance._to_uppercase(inputString);
                const upperString = moduleInstance.UTF8ToString(upperPtr);

                document.getElementById('result').innerText = `Uppercase: ${upperString}`;

							// 释放分配的内存
							moduleInstance._free_string(upperPtr);*/
							// };

							var ptr =moduleInstance.allocateUTF8("发大水供奉的是");
							var ptr2 =moduleInstance.allocateUTF8("供奉");
							const res = moduleInstance._find(ptr,ptr2);
							console.log(moduleInstance.UTF8ToString(res))
        });


						</script>

				</body>
			</html>

encrypt.cpp

#include <emscripten.h>
#include <string>
#include <cstring>

#ifndef EM_PORT_API 
#   if defined(__EMSCRIPTEN__)
#      include <emscripten.h>
#      if defined(__cplusplus)
#           define EM_PORT_API(rettype) extern "C" rettype EMSCRIPTEN_KEEPALIVE
#      else
#           define EM_PORT_API(rettype) rettype EMSCRIPTEN_KEEPALIVE
#      endif
#   else
#      if defined(__cplusplus)
#           define EM_PORT_API(rettype) extern "C" rettype
#      else
#           define EM_PORT_API(rettype) rettype
#      endif
#   endif
#endif

extern "C" {
	
char* getPtr(std::string input){
	
	char* result = (char*)malloc(input.size() + 1);
    if (result == nullptr) {
        // Handle memory allocation failure
        return nullptr;
    }
    
    strcpy((char*)result, input.c_str());
    
    return result;
}

EM_PORT_API( char*) encode(char* input, char key) {
    std::string output = input;

    for (size_t i = 0; i < output.size(); ++i) {
        output[i] = output[i] ^ key;
		//printf("%d\n",(unsigned char)output[i]);
		output[i] = (unsigned char)output[i];
		//printf("%d\n",output[i]);
    }
    
    // Allocate memory for the output string
    char* result = (char*)malloc(output.size() + 1);
    if (result == nullptr) {
        // Handle memory allocation failure
        return nullptr;
    }
    
    strcpy((char*)result, output.c_str());
    
    return result; // Return the encrypted string
}

 EM_PORT_API(const char*) find(char* input, char* sub) {
        // 将输入的 C 字符串转换为 std::string
        std::string strInput(input);
        std::string strSub(sub);

        // 查找子字符串
        size_t pos = strInput.find(strSub);
		
		static const char str1[] = "找到";
		static const char str2[] = "未找到";
        std::string xx = "拉拉哈哈";
        // 如果找到,返回子字符串的起始位置
        if (pos != std::string::npos) {
            return  getPtr(xx); // 返回找到的子字符串的指针
        } else {
            return nullptr; // 如果未找到,返回 nullptr
        }
    }

EM_PORT_API(void) free_string(const char* str) {
    free((void*)str); // 释放分配的内存
}

}

编译

docker run \
  --rm \
  -v $(pwd):/src \
  -u $(id -u):$(id -g) \
  emscripten/emsdk \
emcc encrypt.cpp -o encrypt.js -s MODULARIZE=1 -s EXPORT_NAME="createModule" -s "EXPORTED_FUNCTIONS=['_encode','_find', '_free_string','allocateUTF8','UTF8ToString','getValue','intArrayFromString','intArrayToString','UTF8ArrayToString','stringToUTF8Array','stringToUTF8','allocate','ALLOC_NORMAL']" -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']"

这里面有个要注意的是,c的异或操作默认是有符号的,即异或后的结果可能是负数,不能直接使用wasm的辅助函数UTF8ToString处理,需要先转成无符号的才行。

不清楚如何编译看之前的文章。编译运行 webAssembly(wasm)-CSDN博客 

注:安全是相对的,没有绝对的安全


http://www.kler.cn/news/333106.html

相关文章:

  • 【网络安全】Cookie与ID未强绑定导致账户接管
  • 构建高效新闻推荐系统:Spring Boot的力量
  • 【WebGis开发 - Cesium】三维可视化项目教程---初始化场景
  • HTML增加文本复制模块(使用户快速复制内容到剪贴板)
  • 探索TCP协议的奥秘:Python中的网络通信
  • win11无法输入中文,任务栏中输入法消失
  • 基于ROS的激光雷达点云物体检测
  • Java面试题二
  • (Django)初步使用
  • 微信原生小程序
  • .NET Core 集成 MiniProfiler性能分析工具
  • 第十七讲-选择控件QSlider
  • Hive数仓操作(十五)
  • Windows:win11旗舰版连接无线显示器,连接失败
  • Stable Diffusion绘画 | 来训练属于自己的模型:炼丹启动
  • 【CSS in Depth 2 精译_043】6.5 CSS 中的粘性定位技术 + 本章小结
  • 泰勒图 ——基于相关性与标准差的多模型评价指标可视化比较-XGBoost、sklearn
  • centos72009源码编译R语言
  • 物联网智能项目(含案例说明)
  • Ubuntu 20.04常见配置(含yum源替换、桌面安装、防火墙设置、ntp配置)