用go語(yǔ)言實(shí)現(xiàn)WebAssembly數(shù)據(jù)加密的示例講解
一、背景和意義
在Web開(kāi)發(fā)中,有時(shí)候?yàn)榱颂嵘踩孕枰獙?duì)數(shù)據(jù)進(jìn)行加密。由于js代碼相對(duì)比較易讀,直接在js中做加密安全性較低,而WebAssembly代碼不如js易讀,使用WebAssemply做數(shù)據(jù)加密對(duì)安全性有一定的提升(不過(guò)熟悉WebAssembly的人還是能看懂加解密過(guò)程)。本文提供一個(gè)用go語(yǔ)言實(shí)現(xiàn)的WebAssembly數(shù)據(jù)加密示例。
二、創(chuàng)建WebAssembly文件
創(chuàng)建一個(gè)空目錄,執(zhí)行如下命令初始化go模塊:
go mod init wasm-demo
接下來(lái)在當(dāng)前目錄下創(chuàng)建main.go文件,提供數(shù)據(jù)加密與解密的方法:
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
"syscall/js"
)
var aesCode = "0000000000000000" // 作為demo,這里只用16個(gè)0作為密鑰
// pkcs5Padding 對(duì)數(shù)據(jù)進(jìn)行填充,使其長(zhǎng)度為塊大小的倍數(shù)。
func pkcs5Padding(cipherText []byte, blockSize int) []byte {
padding := blockSize - len(cipherText)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(cipherText, padText...)
}
// pkcs5UnPadding 移除填充數(shù)據(jù)。
func pkcs5UnPadding(decrypted []byte) []byte {
length := len(decrypted)
unPadding := int(decrypted[length-1])
return decrypted[:(length - unPadding)]
}
// aesDecrypt 加密
func aesEncrypt(encryptStr string) (string, error) {
encryptBytes := []byte(encryptStr)
block, err := aes.NewCipher([]byte(aesCode))
if err != nil {
return "", err
}
blockSize := block.BlockSize()
encryptBytes = pkcs5Padding(encryptBytes, blockSize)
blockMode := cipher.NewCBCEncrypter(block, []byte(aesCode)[:blockSize])
encrypted := make([]byte, len(encryptBytes))
blockMode.CryptBlocks(encrypted, encryptBytes)
return hex.EncodeToString(encrypted), nil
}
// aesDecrypt 解密
func aesDecrypt(decryptStr string) (string, error) {
decryptBytes, err := hex.DecodeString(decryptStr)
if err != nil {
return "", err
}
block, err := aes.NewCipher([]byte(aesCode))
if err != nil {
return "", err
}
blockMode := cipher.NewCBCDecrypter(block, []byte(aesCode)[:block.BlockSize()])
decrypted := make([]byte, len(decryptBytes))
blockMode.CryptBlocks(decrypted, decryptBytes)
decrypted = pkcs5UnPadding(decrypted)
return string(decrypted), nil
}
func jsFunc(handler func(string) (string, error)) js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
var result string
var err error
if len(args) > 0 {
result, err = handler(args[0].String())
}
return js.ValueOf(map[string]interface{}{
"result": result,
"err": err,
})
})
}
func main() {
fmt.Println("Go wasm loaded!")
js.Global().Set("aesEncrypt", jsFunc(aesEncrypt))
js.Global().Set("aesDecrypt", jsFunc(aesDecrypt))
<-make(chan bool)
}
如果是在goland中編輯此代碼,需要在Settings中設(shè)置一下Build Tags,將OS設(shè)置為js,Arch設(shè)置為wasm,否則代碼編輯器里的syscall/js會(huì)標(biāo)紅:

接下來(lái)執(zhí)行如下命令生成wasm文件main.wasm:
GOOS=js GOARCH=wasm go build -o main.wasm
三、在前端頁(yè)面中使用WebAssemply的加解密方法
執(zhí)行如下命令將go目錄下的wasm_exec.js復(fù)制過(guò)來(lái)到當(dāng)前目錄:
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
接下來(lái)創(chuàng)建前端代碼index.html文件:
<!DOCTYPE html>
<html lang="utf8">
<head>
<title>wasm demo</title>
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then(result => {
go.run(result.instance);
const encrypt = aesEncrypt("HelloWorld");
console.log("encrypt result: ", encrypt);
console.log("decrypt result: ", aesDecrypt(encrypt.result));
});
</script>
</head>
<body></body>
</html>
將當(dāng)前目錄添加到nginx中,然后通過(guò)nginx提供的端口訪問(wèn)index.html,可以看到控制臺(tái)輸出加解密的結(jié)果如下:

到此這篇關(guān)于用go語(yǔ)言實(shí)現(xiàn)WebAssembly數(shù)據(jù)加密的示例講解的文章就介紹到這了,更多相關(guān)go WebAssembly數(shù)據(jù)加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go數(shù)據(jù)結(jié)構(gòu)之HeapMap實(shí)現(xiàn)指定Key刪除堆
這篇文章主要給大家介紹了Go語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之HeapMap實(shí)現(xiàn)指定Key刪除堆,通過(guò)使用Go語(yǔ)言中的container/heap包,我們可以輕松地實(shí)現(xiàn)一個(gè)優(yōu)先級(jí)隊(duì)列,文中有詳細(xì)的代碼示例講解,需要的朋友可以參考下2023-07-07
Go Gin框架中的binding驗(yàn)證器使用小結(jié)
Gin框架中的binding驗(yàn)證器為我們提供了簡(jiǎn)便的數(shù)據(jù)綁定和驗(yàn)證功能,通過(guò)合理使用binding和validate標(biāo)簽,我們可以確保API接口的數(shù)據(jù)合法性和完整性,這篇文章主要介紹了Go Gin框架中的binding驗(yàn)證器使用指南,需要的朋友可以參考下2024-07-07
Go語(yǔ)言針對(duì)Map的11問(wèn)你知道幾個(gè)?
Go?Map?的?11?連問(wèn),你頂?shù)昧寺?這篇文章小編為大家準(zhǔn)備了?Go?語(yǔ)言?Map?的?11?連問(wèn),相信大家看完肯定會(huì)有幫助的,感興趣的小伙伴可以收藏一波2023-05-05
Golang查詢MongoDB的實(shí)現(xiàn)步驟
本文介紹了如何使用Golang操作MongoDB數(shù)據(jù)庫(kù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-12-12
談?wù)揋o 什么時(shí)候會(huì)觸發(fā) GC問(wèn)題
Go 語(yǔ)言作為一門新語(yǔ)言,在早期經(jīng)常遭到唾棄的就是在垃圾回收(下稱:GC)機(jī)制中 STW(Stop-The-World)的時(shí)間過(guò)長(zhǎng)。下面文章就對(duì)此話題展開(kāi),感興趣的小伙伴可以參考下面文章的內(nèi)容2021-09-09

