arnaucube
arnaucube/go-blindsecp256k1Public Self-hosted repository
Add WASM wrappers & compiled
arnaucube root@arnaucube.com
Sun, 10 Jan 2021 23:09:54 +0100
commit

c3e4afc5529278df8ace6dad7aeae79883ce06c8

parent

a7ea30d8154dd557ca7e11981421d8b2e412403d

M .github/workflows/lint.yml → .github/workflows/lint.yml

@@ -13,4 +13,5 @@ uses: actions/checkout@v2

- name: Lint run: | curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0 + rm -r wasm $(go env GOPATH)/bin/golangci-lint run --timeout=5m -c .golangci.yml
M .github/workflows/test.yml → .github/workflows/test.yml

@@ -16,4 +16,4 @@ go-version: ${{ matrix.go-version }}

- name: Checkout code uses: actions/checkout@v2 - name: Run tests - run: go test ./... + run: go test $(go list ./... | grep -v /wasm)
A .gitignore

@@ -0,0 +1,1 @@

+wasm_exec.js
M README.md → README.md

@@ -27,3 +27,6 @@ // signature can be verified with signer PublicKey

verified := blindsecp256k1.Verify(msg, sig, signerPublicData.Q) assert.True(t, verified) ``` + +## WASM usage +WASM wrappers for browser usage can be found at the [wasm](https://github.com/arnaucube/go-blindsecp256k1/tree/master/wasm/) directory with an example in html&js.
A wasm/README.md

@@ -0,0 +1,15 @@

+# blindsecp256k1 wasm clientlib +[blindsecp256k1](https://github.com/arnaucube/go-blindsecp256k1) lib for browsers using go WASM. + +## Wasm usage +To compile to wasm, inside the `wasm` directory, execute: +``` +./build.sh +``` + +Add the file `wasm_exec.js` in the `webtest` directory: +``` +cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" . +``` + +To see the usage from javascript, check `index.js` file.
A wasm/blindsecp256k1-wasm.go

@@ -0,0 +1,100 @@

+package main + +import ( + "blindsecp256k1" + "fmt" + "math/big" + "syscall/js" +) + +func main() { + c := make(chan struct{}, 0) + println("WASM blindsecp256k1 initialized") + registerCallbacks() + <-c +} + +func registerCallbacks() { + js.Global().Set("blind", js.FuncOf(blind)) + js.Global().Set("unblind", js.FuncOf(unblind)) +} + +func stringToBigInt(s string) *big.Int { + b, ok := new(big.Int).SetString(s, 10) + if !ok { + panic(fmt.Errorf("error parsing string *big.Int: %s", s)) + } + return b +} + +func blind(this js.Value, values []js.Value) interface{} { + mStr := values[0].String() + signerQxStr := values[1].String() + signerQyStr := values[2].String() + signerRxStr := values[3].String() + signerRyStr := values[4].String() + + m := stringToBigInt(mStr) + signerQx := stringToBigInt(signerQxStr) + signerQy := stringToBigInt(signerQyStr) + signerRx := stringToBigInt(signerRxStr) + signerRy := stringToBigInt(signerRyStr) + + signerQ := &blindsecp256k1.PublicKey{ + X: signerQx, + Y: signerQy, + } + signerR := &blindsecp256k1.Point{ + X: signerRx, + Y: signerRy, + } + + signer := &blindsecp256k1.SignerPublicData{signerQ, signerR} + mBlinded, user := blindsecp256k1.Blind(m, signer) + + r := make(map[string]interface{}) + r["mBlinded"] = mBlinded.String() + r["uA"] = user.A.String() + r["uB"] = user.B.String() + r["uC"] = user.C.String() + r["uC"] = user.C.String() + r["uFx"] = user.F.X.String() + r["uFy"] = user.F.Y.String() + return r +} + +func unblind(this js.Value, values []js.Value) interface{} { + sBlindStr := values[0].String() + mStr := values[1].String() + uBStr := values[2].String() + uCStr := values[3].String() + uFxStr := values[4].String() + uFyStr := values[5].String() + + sBlind := stringToBigInt(sBlindStr) + m := stringToBigInt(mStr) + uB := stringToBigInt(uBStr) + uC := stringToBigInt(uCStr) + uFx := stringToBigInt(uFxStr) + uFy := stringToBigInt(uFyStr) + + uF := &blindsecp256k1.Point{ + X: uFx, + Y: uFy, + } + + u := &blindsecp256k1.UserSecretData{ + // A not needed to Unblind + B: uB, + C: uC, + F: uF, + } + + sig := blindsecp256k1.Unblind(sBlind, m, u) + + r := make(map[string]interface{}) + r["s"] = sig.S.String() + r["fx"] = sig.F.X.String() + r["fy"] = sig.F.Y.String() + return r +}
A wasm/build.sh

@@ -0,0 +1,4 @@

+#!/bin/sh + +GOARCH=wasm GOOS=js go build -o blindsecp256k1.wasm blindsecp256k1-wasm.go +mv blindsecp256k1.wasm webtest/blindsecp256k1.wasm
A wasm/webtest/index.html

@@ -0,0 +1,18 @@

+<html> +<head> + <meta charset="utf-8"> + <title>blindsecp256k1 WASM wrappers</title> +</head> +<body> + <script src="wasm_exec.js"></script> + <script> + const go = new Go(); + WebAssembly.instantiateStreaming(fetch('blindsecp256k1.wasm'), go.importObject).then(function(dat) { + go.run(dat.instance); + }); + </script> + <h3>Open the browser console to see the logs</h3> + <button onClick="test();">test()</button> + <script src="index.js"></script> +</body> +</html>
A wasm/webtest/index.js

@@ -0,0 +1,16 @@

+function test() { + let m = "1952805748"; + + // Q & R would be received from the Signer + let signerQx = "26613296432153871833441195158297038913673464785502568519907582377915678491093"; + let signerQy = "81940194042971427014176158889809922552127995083760111384335138546589994227275"; + let signerRx = "59371873487402651110657306418818354906476102545298559461791300717696053835454"; + let signerRy = "98322875246066710654579302898391677189379767946198239290895789444110962324342"; + let blindRes = blind(m, signerQx, signerQy, signerRx, signerRy); + console.log("blind", blindRes); + + // sBlind would be received from the Signer + let sBlind = "7240298625621589352655632414257224668430424461224914067754717095121139699933353374227084479180038954015287518505167995306229258561275087198611946596619855"; + let unblindRes = unblind(sBlind, m, blindRes.uB, blindRes.uC, blindRes.uFx, blindRes.uFy); + console.log("unblind", unblindRes); +}