preface

Last month I spent two days developing a new VSCode plug-in called “I love digging gold”, which allows all users to become tadpoles and chat in VSCode in real time. I used an open source project, Workerman-Todpole, which I made a lot of changes and optimizations from the original project. I also tried to add some room management functions, such as only the administrator can use the bright red, only the administrator can light up and so on.

But digg friends of justice soon began experimenting with ways to break the inequality, including @Naomaoxiaoshuai, who developed a variety of pond robots that could act as NPCS offering help to novice users. Now the creativity of small tadpole big eyes is also that cat small handsome classmate put forward, simply lollipop 💯.

demand

To implement the house management function, I need to implement a method to generate and activate advanced commands that give me advanced privileges. Obviously, I don’t want anyone to see how I generate and validate commands in this code.

I also didn’t want to put it on the server as a back-end interface, because it would strain the server to request the interface every time. Websocket needs to validate this high-level command every time it receives a message

So, I identified two core appeals

  • Advanced command generation and activation is done directly in the front end, avoiding the request server.
  • The core logic of generation and activation cannot be seen, otherwise it is meaningless.

After doing some research and finding that WebAssembly meets both of my needs, it’s time to get real.

WebAssembly introduction

WebAssembly has a complete set of semantics and can generate a binary.wASM format that is small and fast to load, with the goal of maximizing hardware capabilities for native execution efficiency.

It still runs in the browser, but uses a binary format of.wASM files, which is perfectly suited to my needs and is compatible with WebAssembly in mainstream browsers.

For example, you can copy and paste the following code into your browser’s debug window to get a feel for it

WebAssembly.compile(new Uint8Array(` 00 61 73 6d 01 00 00 00 01 0c 02 60 02 7f 7f 01 7f 60 01 7f 01 7f 03 03 02 00 01 07 10 02 03 61 64 64 00 00 06 73 71 75 61 72 65 00 01 0a 13 02 08 00 20 00 20 01 6a 0f 0b 08 00 20 00 20 00 6c 0f 0b`.trim().split(/[\s\r\n]+/g).map(str= > parseInt(str, 16))
)).then(module= > {
  const instance = new WebAssembly.Instance(module)
  const { add, square } = instance.exports

  console.log('2 + 4 =', add(2.4))
  console.log('3 ^ 2 =', square(3))
  console.log('(2 + 5 ^ 2 =', square(add(2 + 5)))})Copy the code

Obviously, you can’t easily tell how exactly the Uint8Array algorithm is implemented…

But writing code and compiling it into a.wasm file is not that easy. In this case, I chose C++ to write the code and compile it into a.wasm file using the emscripten tool chain.

emscripten

Install the Emscripten environment

# Get the emsdk repo git clone https://github.com/emscripten-core/emsdk.git # Enter that directory cd emsdk # Fetch the latest version of the emsdk (not needed the first time you clone) git pull # Download and install the latest SDK tools. ./emsdk install latest # Make the "latest" SDK "active" for the current user. (writes .emscripten file) ./emsdk activate  latest # Activate PATH and other environment variables in the current terminal source ./emsdk_env.shCopy the code

WebAssembly official documentation

Once the environment is installed, let’s immediately write a piece of C, compile it into.wASM and let it run in the browser.

#include <stdio.h>

int main(int argc, char ** argv) {
    printf("Dig your friends.");
    printf("\n");
    printf("This is a greeting from C.");
    printf("\n");
}
Copy the code

Compile command

emcc helloworld.c -s WASM=1 -o helloworld.html
Copy the code

After compiling, remember a service, such as live-server, because we need to read the local.wASM file. So we can see the greeting from C in the browser

But frankly, I don’t think WebAssembly can reduce the amount of code, such as the 12KB required to compile this simple code into.wASM.

Combat code protection

For example, the ORIGINAL JS logic I need is as follows: every day, the time stamp of zero is converted to 36 base to get a 6-digit string (the input experience of this length is relatively friendly). After the user enters this command, the advanced functions can be activated.

Tadpole pond algorithm has changed, don’t be naive to think I will reveal my algorithm oh: P

JS spelled

function verifyCommand(cmd){
	var t_cmd = (new Date(new Date().setHours(0.0.0.0)).getTime()/1000).toString(36);
	if(cmd == t_cmd)return 1;
	else return 0;
}
Copy the code

However, JS is completely exposed in the browser, and in browser debug mode, it is very easy to see how advanced commands are generated.

Of course, as mentioned at the beginning of this article, we can also put it into the backend interface to verify

PHP spelled

function MyEncode($var.$targetBit){    
    $dic = array(
            0= >'0'.1= >'1'.2= >'2'.3= >'3'.4= >'4'.5= >'5'.6= >'6'.7= >'7'.8= >'8'.9= >'9'.10= >'A'.11= >'B'.12= >'C'.13= >'D'.14= >'E'.15= >'F'.16= >'G'.17= >'H'.18= >'I'.19= >'J'.20= >'K'.21= >'L'.22= >'M'.23= >'N'.24= >'O'.25= >'P'.26= >'Q'.27= >'R'.28= >'S'.29= >'T'.30= >'U'.31= >'V'.32= >'W'.33= >'X'.34= >'Y'.35= >'Z'
    );
    $yushu=bcmod($var.$targetBit);
    $shang=floor(bcdiv($var.$targetBit));

    if($shang= =0) {return  $dic[$yushu];
    }
    else {
        return MyEncode($shang.$targetBit).$dic[$yushu];
    }
}

date_default_timezone_set('PRC');
$time =strtotime(date("Y-m-d 00:00:00"));
$v_cmd = MyEncode(intval($time),36);

$cmd = strtoupper($_GET["cmd"]);

if($cmd= =$v_cmd) {echo 1;
}else{
    echo 0;
}
Copy the code

However, using the server side, each verification must request the interface, which will undoubtedly cause pressure on the server.

Now let’s write it in C and compile it as a WebAssembly.wASM file

// Get today's zero time stamp, seconds
unsigned int getTodayZeroTime(a) 
{  
	// Too long, the implementation of the function see source code
}  

// Converts a number to a specified base, where decimal is a base value
void f( long int x, char *p ,int decimal)
{
	// Too long, the implementation of the function see source code
}

int verifyCommand(std::string cmd) {
  int t_time = getTodayZeroTime(a);char t_cmd[MAXN]="";
  f(t_time,t_cmd,36);

  if(strcmp(t_cmd, cmd.data()) = =0) {return 1;
  }else{
    return 0; }}Copy the code

JS calls.wasmC method and pass the parameter

To call WebAssembly functions in JS, we use an extern “C” wrapper around the function

extern "C" {
  int verifyCommand(std::string cmd) {
    int t_time = getTodayZeroTime(a);char t_cmd[MAXN]="";
    f(t_time,t_cmd,36);

    if(strcmp(t_cmd, cmd.data()) = =0) {return 1;
    }else{
      return 0; }}}Copy the code

Add commands when compiling. Wasm

emcc verify.cc -o verify.html -s EXPORTED_FUNCTIONS="['_verifyCommand']" -s EXPORTED_RUNTIME_METHODS='["ccall"]'
Copy the code

Focus on these two parameters, notice the underline and the quotes

  • -s EXPORTED_FUNCTIONS=”[‘_verifyCommand’]”
  • -s EXPORTED_RUNTIME_METHODS='[“ccall”]’

After compiling, we can use JS to call the verifyCommand function in C language

// The first argument, the function name
// The second argument, the function return value type
// The function takes an array of parameter types
// The fourth argument, the array of arguments to pass
Module.ccall("verifyCommand".'number'['string'], ['qmocg0']);
Copy the code

The following is a screenshot of the debug window. I specifically typed the correct and wrong values to see the return values

Now we have completed the verification function of this advanced command. The verification is done synchronously in the front end without requiring the background interface to obtain the verification result asynchronously. Because the core code is in binary. Wasm files, it is not easy for anyone to see how the logic in the function is implemented. Why did you highlight the word “relaxed”?

Because if you can compile, you can decompile…

This article is here, everyone tadpoles pond see, remember to click on the collection, sooner or later you will use!

Download the source code

Search “ezfullstack” on wechat, follow and reply “WebAssembly” to get the source code download link

Focus on big Handsome, a versatile old programmer