WASM实现加密与算法保护

news/2024/9/29 22:13:51 标签: javascript, 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.niftyadmin.cn/n/5683814.html

相关文章

计算机毕业论文及毕业设计题目,计算机专业大专本科学位毕业论文题目推荐大全集

目录 一 软件工程方向 二 网络安全方向 三 人工智能与机器学习方向 四 大数据方向 五 云计算与虚拟化方向 六 数据库与信息系统方向 计算机专业的毕业论文或毕业设计题目通常需要结合当前的技术趋势以及个人兴趣来确定。一个好的选题不仅能够体现学生的学术水平和技术能…

工业网关在设备数据采集中的角色-天拓四方

一、引言 在现代化工业生产和管理的浪潮中&#xff0c;设备数据采集已经成为一项至关重要的技术。它不仅能帮助企业实时了解设备的运行状态&#xff0c;还能为生产决策提供有力支持。而在设备数据采集的领域中&#xff0c;工业网关以其独特的功能和优势&#xff0c;发挥着不可…

初识chatgpt

GPT到底是什么 首先&#xff0c;我们需要了解GPT的全称&#xff1a;Generative Pre-trained Transformer&#xff0c;即三个关键词&#xff1a;生成式 预训练 变换模型。 &#xff08;1&#xff09;什么是生成式&#xff1f; 即能够生成新的文本序列。 &#xff08;2&#…

MySQL 之事务详解

想象一下&#xff0c;你正在使用银行App转账&#xff0c;将100元从你的账户转到朋友的账户。这个看似简单的操作&#xff0c;背后其实包含着多个数据库操作&#xff1a; 检查账户余额: 确保你的账户余额足够支付转账金额。 从你的账户扣除100元: 更新你的账户余额。 将100元添…

Web3Auth 如何工作?

Web3Auth 用作钱包基础设施&#xff0c;为去中心化应用程序 (dApp) 和区块链钱包提供增强的灵活性和安全性。在本文档中&#xff0c;我们将探索 Web3Auth 的功能&#xff0c;展示它如何为每个用户和应用程序生成唯一的加密密钥提供程序。 高级架构 Web3Auth SDK 完全存在于用…

【MySQL内置数据库】 mysql

目录 统计 columns_priv component db default_roles engine_cost func general_log global_grants gtid_executed help_category help_keyword help_relation help_topic innodb_index_stats innodb_table_stats ndb_binlog_index password_history plugin…

电磁兼容(EMC):整改案例(三)雷击浪涌电气间隙不够打火炸机

目录 1. 异常现象 2. 原因分析 3. 整改方案 4. 总结 1. 异常现象 某金属外壳的直流无刷风机产品按GB/T 17626.5进行雷击浪涌测试&#xff0c;在L&#xff0c;N线对PE进行2kV浪涌电压测试时&#xff0c;出现炸机现象。而L&#xff0c;N线间进行2kV的浪涌测试没问题。 2. 原…

Mysql梳理10——使用SQL99实现7中JOIN操作

10 使用SQL99实现7中JOIN操作 10.1 使用SQL99实现7中JOIN操作 本案例的数据库文件分享&#xff1a; 通过百度网盘分享的文件&#xff1a;atguigudb.sql 链接&#xff1a;https://pan.baidu.com/s/1iEAJIl0ne3Y07kHd8diMag?pwd2233 提取码&#xff1a;2233 # 正中图 SEL…