func exchange(_ js.Value, args []js.Value) interface{} {
	pass := make([]byte, args[0].Length())
	js.CopyBytesToGo(pass, args[0])
	msgA, err := base64.URLEncoding.DecodeString(args[1].String())
	if err != nil {
		return []interface{}{nil, nil}
	}
	msgB, mk, err := cpace.Exchange(string(pass), cpace.NewContextInfo("", "", nil), msgA)
	if err != nil {
		return []interface{}{nil, nil}
	}
	hkdf := hkdf.New(sha256.New, mk, nil, nil)
	key := [32]byte{}
	_, err = io.ReadFull(hkdf, key[:])
	if err != nil {
		return []interface{}{nil, nil}
	}
	dst := js.Global().Get("Uint8Array").New(32)
	js.CopyBytesToJS(dst, key[:])
	return []interface{}{
		dst,
		base64.URLEncoding.EncodeToString(msgB),
	}
}
exchange(pass, base64msgA string) (key []byte, base64msgB string)
package main
import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"io"
	"strconv"
	"syscall/js"
	"filippo.io/cpace"
	"golang.org/x/crypto/hkdf"
	"golang.org/x/crypto/nacl/secretbox"
	"rsc.io/qr"
	"webwormhole.io/wordlist"
)
var state *cpace.State
func start(_ js.Value, args []js.Value) interface{} {
	pass := make([]byte, args[0].Length())
	js.CopyBytesToGo(pass, args[0])
	msgA, s, err := cpace.Start(string(pass), cpace.NewContextInfo("", "", nil))
	if err != nil {
		return nil
	}
	state = s
	return base64.URLEncoding.EncodeToString(msgA)
}
func finish(_ js.Value, args []js.Value) interface{} {
	msgB, err := base64.URLEncoding.DecodeString(args[0].String())
	if err != nil {
		return nil
	}
	mk, err := state.Finish(msgB)
	if err != nil {
		return nil
	}
	hkdf := hkdf.New(sha256.New, mk, nil, nil)
	key := [32]byte{}
	_, err = io.ReadFull(hkdf, key[:])
	if err != nil {
		return nil
	}
	dst := js.Global().Get("Uint8Array").New(32)
	js.CopyBytesToJS(dst, key[:])
	return dst
}