用go語言實現(xiàn)WebAssembly數(shù)據(jù)加密的示例講解
一、背景和意義
在Web開發(fā)中,有時候為了提升安全性需要對數(shù)據(jù)進(jìn)行加密。由于js代碼相對比較易讀,直接在js中做加密安全性較低,而WebAssembly代碼不如js易讀,使用WebAssemply做數(shù)據(jù)加密對安全性有一定的提升(不過熟悉WebAssembly的人還是能看懂加解密過程)。本文提供一個用go語言實現(xiàn)的WebAssembly數(shù)據(jù)加密示例。
二、創(chuàng)建WebAssembly文件
創(chuàng)建一個空目錄,執(zhí)行如下命令初始化go模塊:
go mod init wasm-demo
接下來在當(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個0作為密鑰 // pkcs5Padding 對數(shù)據(jù)進(jìn)行填充,使其長度為塊大小的倍數(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
會標(biāo)紅:
接下來執(zhí)行如下命令生成wasm文件main.wasm:
GOOS=js GOARCH=wasm go build -o main.wasm
三、在前端頁面中使用WebAssemply的加解密方法
執(zhí)行如下命令將go目錄下的wasm_exec.js復(fù)制過來到當(dāng)前目錄:
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
接下來創(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中,然后通過nginx提供的端口訪問index.html,可以看到控制臺輸出加解密的結(jié)果如下:
到此這篇關(guān)于用go語言實現(xiàn)WebAssembly數(shù)據(jù)加密的示例講解的文章就介紹到這了,更多相關(guān)go WebAssembly數(shù)據(jù)加密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Golang快速構(gòu)建出命令行應(yīng)用程序
在日常開發(fā)中,大家對命令行工具(CLI)想必特別熟悉了,如果說你不知道命令工具,那你可能是個假開發(fā)。每天都會使用大量的命令行工具,例如最常用的Git、Go、Docker等,這篇文章主要介紹了使用Golang快速構(gòu)建出命令行應(yīng)用程序,需要的朋友可以參考下2023-02-02Go初學(xué)者踩坑之go?mod?init與自定義包的使用
go?mod是go的一個模塊管理工具,用來代替?zhèn)鹘y(tǒng)的GOPATH方案,下面這篇文章主要給大家介紹了關(guān)于Go初學(xué)者踩坑之go?mod?init與自定義包的使用,需要的朋友可以參考下2022-10-10