用go语言实现WebAssembly数据加密的示例讲解

 更新时间:2024年03月18日 10:50:29   作者:qinyuan15  
在Web开发中,有时候为了提升安全性需要对数据进行加密,由于js代码相对比较易读,直接在js中做加密安全性较低,而WebAssembly代码不如js易读,本文提供一个用go语言实现的WebAssembly数据加密示例,需要的朋友可以参考下

一、背景和意义

在Web开发中,有时候为了提升安全性需要对数据进行加密。由于js代码相对比较易读,直接在js中做加密安全性较低,而WebAssembly代码不如js易读,使用WebAssemply做数据加密对安全性有一定的提升(不过熟悉WebAssembly的人还是能看懂加解密过程)。本文提供一个用go语言实现的WebAssembly数据加密示例。

二、创建WebAssembly文件

创建一个空目录,执行如下命令初始化go模块:

go mod init wasm-demo

接下来在当前目录下创建main.go文件,提供数据加密与解密的方法:

package main

import (
   "bytes"
   "crypto/aes"
   "crypto/cipher"
   "encoding/hex"
   "fmt"
   "syscall/js"
)

var aesCode = "0000000000000000" // 作为demo,这里只用16个0作为密钥

// pkcs5Padding 对数据进行填充,使其长度为块大小的倍数。
func pkcs5Padding(cipherText []byte, blockSize int) []byte {
   padding := blockSize - len(cipherText)%blockSize
   padText := bytes.Repeat([]byte{byte(padding)}, padding)
   return append(cipherText, padText...)
}

// pkcs5UnPadding 移除填充数据。
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中设置一下Build Tags,将OS设置为js,Arch设置为wasm,否则代码编辑器里的syscall/js会标红:

接下来执行如下命令生成wasm文件main.wasm:

GOOS=js GOARCH=wasm go build -o main.wasm

三、在前端页面中使用WebAssemply的加解密方法

执行如下命令将go目录下的wasm_exec.js复制过来到当前目录:

cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .

接下来创建前端代码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>

将当前目录添加到nginx中,然后通过nginx提供的端口访问index.html,可以看到控制台输出加解密的结果如下:

到此这篇关于用go语言实现WebAssembly数据加密的示例讲解的文章就介绍到这了,更多相关go WebAssembly数据加密内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang 之区分类型别名与类型定义的方法

    Golang 之区分类型别名与类型定义的方法

    这篇文章主要介绍了Golang 之区分类型别名与类型定义的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Go语言中的闭包详解

    Go语言中的闭包详解

    本文详细讲解了Go语言中的闭包,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • Go语言context test源码分析详情

    Go语言context test源码分析详情

    这篇文章主要介绍了Go语言context test源码分析详情,关于context test,测试对象是context包,测试包的包名是context_test,下面将对context test源码进行分析,需要的朋友可以参考一下,希望对你有所帮助
    2022-02-02
  • 为什么GO不支持循环引用

    为什么GO不支持循环引用

    这篇文章主要介绍的是为什么GO不支持循环引用,学习 Go 语言的开发者越来越多了,很多小伙伴在使用时,就会遇到种种不理解的问题,其中一点就是包的循环引用的报错,下main文章我们一起来看看学习原因
    2021-10-10
  • Go Gorm 示例详解

    Go Gorm 示例详解

    Gorm是一款高性能的Golang ORM库,便于开发人员提高效率,本文介绍了Gorm的基本概念、数据库连接、基本操作(创建表、新增记录、查询记录、修改记录、删除记录)等,本文介绍Go Gorm的相关知识,感兴趣的朋友一起看看吧
    2025-01-01
  • Go1.21新增slices包的用法详解

    Go1.21新增slices包的用法详解

    Go 1.21新增的 slices 包提供了很多和切片相关的函数,可以用于任何类型的切片,这篇文章主要来和大家介绍一下slices包中相关函数的用法,需要的可以参考一下
    2023-08-08
  • 使用Golang快速构建出命令行应用程序

    使用Golang快速构建出命令行应用程序

    在日常开发中,大家对命令行工具(CLI)想必特别熟悉了,如果说你不知道命令工具,那你可能是个假开发。每天都会使用大量的命令行工具,例如最常用的Git、Go、Docker等,这篇文章主要介绍了使用Golang快速构建出命令行应用程序,需要的朋友可以参考下
    2023-02-02
  • go语言中slice,map,channl底层原理

    go语言中slice,map,channl底层原理

    这篇文章主要介绍了go语言中slice,map,channl底层原理,slice,map,channl是我们Go语言中最最常用的几个数据结构,对于其更多相关内容需要的小伙伴可以参考下面文章详细内容
    2022-06-06
  • Go初学者踩坑之go mod init与自定义包的使用

    Go初学者踩坑之go mod init与自定义包的使用

    go mod是go的一个模块管理工具,用来代替传统的GOPATH方案,下面这篇文章主要给大家介绍了关于Go初学者踩坑之go mod init与自定义包的使用,需要的朋友可以参考下
    2022-10-10
  • 如何在Go中使用Casbin进行访问控制

    如何在Go中使用Casbin进行访问控制

    这篇文章主要介绍了如何在Go中使用Casbin进行访问控制,Casbin是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型,Casbin只负责访问控制
    2022-08-08

最新评论