How to call init_secure_api

I’m experimenting with the new v3 API. My request:
curl -0 -XPOST -u grin:cat ./owner_api_secret --data ‘{“jsonrpc”:“2.0”,“method”:“retrieve_summary_info”,“params”:[true, 10],“id”:1}’ http://127.0.0.1:3420/v3/owner

Response:
{
“error”: {
“code”: -32001,
“message”: “Encryption must be enabled. Please call 'init_secure_api` first”
},
“id”: “1”,
“jsonrpc”: “2.0”
}%

Can I get an example for init_secure_api with encrypted_request_v3 please?

Ok, I found it in the grin-wallet src docs. But I’m having trouble translating the encrypt function to go.

original:

const encrypt = (str, nonce) => {
	let key = Buffer.from(shared_secret, 'hex')
	const cipher = crypto.createCipheriv(ALGO, key, nonce)
	const enc = Buffer.concat([cipher.update(str, 'utf8'), cipher.final()])
	const tag = cipher.getAuthTag()
	return Buffer.concat([enc, tag]).toString('base64')
};

Any gophers here to show me what I’m missing here:

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"io"
)
func Encrypt(key, nonce, body []byte) (string, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	aesgcm, err := cipher.NewGCM(block)
	if err != nil {
		return "", err
	}

	cipherText := aesgcm.Seal(nil, nonce, body, nil)

	return base64.StdEncoding.EncodeToString(cipherText), nil
}

Here’s how I computed my shared key:

import (
	"encoding/json"
	"fmt"
	"os"

	ecies "github.com/ecies/go"
	log "github.com/sirupsen/logrus"
	"github.com/ybbus/jsonrpc"
)
func InitSecureApi(conf GrinConfig) ([]byte, error) {
	type Ok struct {
		PublicKey string `json:"Ok"`
	}

	privateKey, err := ecies.GenerateKey()
	if err != nil {
		return []byte{}, fmt.Errorf("generate key pair failed: %s", err)
	}

	params := struct {
		Public string `json:"ecdh_pubkey"`
	}{
		Public: privateKey.PublicKey.Hex(true),
	}

	rpcClient := jsonrpc.NewClient(conf.URL)
	response, err := rpcClient.Call("init_secure_api", &params)
	if err != nil {
		return []byte{}, fmt.Errorf("init_secure_api failed: %s", err)
	}

	var result Ok
	err = response.GetObject(&result)
	if err != nil {
		return []byte{}, fmt.Errorf("get reponse object failed: %s", err)
	}

	log.Infof("received public key result: %s", result.PublicKey)

	remotePublicKey, err := ecies.NewPublicKeyFromHex(result.PublicKey)
	if err != nil {
		return []byte{}, fmt.Errorf("failed remote public key %s", err)
	}

	sharedKey, err := privateKey.ECDH(remotePublicKey)
	if err != nil {
		return []byte{}, fmt.Errorf("failed ecdh %s", err)
	}

	return sharedKey, nil
}

@Yeastplume @quentinlesceller ^^

Hi @liberty. You are in luck :slight_smile: Everything is here in golang https://github.com/blockcypher/libgrin/blob/master/example/secure_owner_api.go :slight_smile: Tested on latest master.

2 Likes

omg, this is awesome! Thank you! I was going to contribute the wrapper if there wasn’t one, but I see you already have it!

Yes. Feel free to PR stuff in it. It might be worthwhile to move the wrapper into its own wrapper package (or something package) instead of example and add the missing functions. Enjoy :slight_smile: