ReCOVER

CoinCover provides a safe, non-custodial way to store private keys and data.

Data must always be encrypted prior to it being sent to CoinCover.

This can be achieved by a combination of two methods:

  1. Symmetric encryption with a password

  2. Asymmetric encryption with a public key

The usage is dependent on what is being encrypted.

Where the data relates to a private key or seed that can be used to access funds, then this must be double-encrypted, using both methods sequentially.

The customer or end-user holds the password for decryption. CoinCover holds the private key to decrypt. Importantly, the data should be encrypted with a password first and then the public key.

Once the data has been encrypted, it can be sent to CoinCover and stored within the secure platform.

In the event of a disaster, CoinCover can work with the holder of the password to recover access to the underlying data.

At the end of this section you’ll find some test data and keys that you can use to get to grips with our API.


Authentication Token

Our Access Protection endpoints are secured via a Bearer token. This will be supplied by your relevant contact at CoinCover at the time of integration.

Different tokens are required for our Test and Production environments. (Please find test keys at the end of this section, as well as test environment variables in the Docker section below.)


Set up Docker

CoinCover provides Access Protection tooling via a Docker image to enable simplified integration.

This enables a consistent approach to the following services.

  • Pulling and verification of CoinCover public keys

  • Registering users and posting coverage

  • Symmetric encryption of assets

  • Asymmetric encryption of assets

  • Sending encrypted data to CoinCover secure services


Hot and Cold environments

The Docker image can be used in both hot and cold setup, specific to certain conditions. All services are available when connected in a hot environment.

Where flows are not automated and encryption is required in a manual and cold environment, the Docker image can be exported/imported to carry out the encryption functions.

It is important to note that public keys must be retrieved from a hot environment first, as these are required to encrypt asymmetrically. Only CoinCover approved public keys can be used with the Docker image.

Setup

Prerequisites

  • Docker must be installed on any machines that will run the service.

  • Access token supplied to the organisation to enable the Docker image to communicate with the CoinCover services

Pulling and running the Docker image

docker pull coincover/crypt

To run the Docker image in an offline environment, the image needs to be exported from the hot machine and then imported into the cold environment.

docker save -o .

For example:

docker save -o crypt coincover/crypt:latest

This will output a file called 'crypt' in the directory that the command was run from. This file can then be transferred to the cold environment.

Once in the cold machine, the image can be imported.

docker load -i crypt

To validate that the import has run correctly, run docker images which will show 'coincover/crypt' if the image has been imported correctly.

Configuring the Environment Variables

To enable the Docker image to connect to CoinCover services, an environment file needs to be created and details set up to enable the connections.

In the directory where the Docker image will be launched from, create a file called .env

Edit the file and setup the following environment variables appropriate to either the CoinCover Production or Test environments:

TEST

PORT=3030
COINCOVER_SERVICES_BASE_URL=https://test-services.coincover.com
COINCOVER_TOKEN=(access token supplied to Org)
ENVIRONMENT=test

PRODUCTION

PORT=3030
COINCOVER_SERVICES_BASE_URL=https://services.coincover.com
COINCOVER_TOKEN=(access token supplied to Org)
ENVIRONMENT=production

Running the Docker image

docker run -p 3030:3030 --env-file .env coincover/crypt

This will run a service on the local machine providing a connection session to:

http://localhost:3030

Encrypt and Store

POST Retrieve a Public Key

{{HOST}}/encryption-key

Retrieves a RSA4096 public key which has been signed by CoinCover to ensure its validity.

Each public key request must be associated with a wallet and a user. This information is provided with the GET.

The response will include a signature and publicKey.

These should be saved against the user, as are required when encrypting data or storing encrypted data with CoinCover.

Field Information

Field Description Mandatory

userEmail

Email of end-user

Yes

userId

User Id of the partners end-user relevant to the partner’s systems

Yes

walletId

Wallet Id associated with the user. Where an on-chain reference is available, this should be used

Yes

Response Codes

Code Description

201

Created

400

Bad request

500

Missing mandatory field

AUTHORIZATION Bearer Token


Body raw (json)


{
  "userEmail":"joebloggs@coincover.com",
  "userId":"jb001",
  "walletId":"2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn"
}

Example Request

cURL - cURL
curl --location -g '{{HOST}}/encryption-key' \
--data-raw '{
  "userEmail":"joebloggs@coincover.com",
  "userId":"jb001",
  "walletId":"2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn"
}
'
C# - HttpClient
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "{{HOST}}/encryption-key");
var content = new StringContent("{\n\t\"userEmail\":\"joebloggs@coincover.com\",\n\t\"userId\":\"jb001\",\n\t\"walletId\":\"2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn\"\n}\n", null, "text/plain");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Go - Native
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "{{HOST}}/encryption-key"
  method := "POST"

  payload := strings.NewReader(`{
  "userEmail":"joebloggs@coincover.com",
  "userId":"jb001",
  "walletId":"2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn"
  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
JavaScript - Fetch
var raw = "{\n	\"userEmail\":\"joebloggs@coincover.com\",\n	\"userId\":\"jb001\",\n	\"walletId\":\"2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn\"\n}\n";

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

fetch("{{HOST}}/encryption-key", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Example Response

{
  "signature": "IHjvXcK9cB625yzfsm6GHix2nLB+TTaCff+wowjaRvypLo5SGuDFcgMJ6EfDoXi96SGr9IeB7sOU3lZF3ThvQMo=",
  "publicKey": "string",
  "userEmail": "joebloggs@coincover.com",
  "userId": "jb001",
  "walletId": "2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn",
  "verified": true
}

POST Encrypt with a password

{{HOST}}/encrypt-pwd

Any private key / seed data must be encrypted with a password before it is encrypted with the CoinCover public key and sent to CoinCover.

Set the password used to encrypt and provide confirmation to the end-user. This password will be required to decrypt the data in the event that they have to recover directly with CoinCover.

The encryption will return a cipher which is the encrypted data.

This encrypted data can then be passed into the encrypt-rsa function, along with the public key and signature requested in /encryption-key.

Field Information

Field Description Mandatory

plain

Data to be encrypted

Yes

password

Password to encrypt the data

Yes

Response Codes

Code Description

200

OK

400

Bad request

Body raw (json)


{
    "plain": "xE4t6Kv0/ThIIaZnyukmEJWse8EXkutDii29qQrapY/JNI69JMH57nKY7DN31oIJ",
    "password": "2FKzRrl%*hA#1FWz"
}

Example Request

cURL - cURL
curl --location -g '{{HOST}}/encrypt-pwd' \
--data '{
    "plain": "xE4t6Kv0/ThIIaZnyukmEJWse8EXkutDii29qQrapY/JNI69JMH57nKY7DN31oIJ",
    "password": "2FKzRrl%*hA#1FWz"
}
'
C# - HttpClient
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "{{HOST}}/encrypt-pwd");
var content = new StringContent("{\n    \"plain\": \"xE4t6Kv0/ThIIaZnyukmEJWse8EXkutDii29qQrapY/JNI69JMH57nKY7DN31oIJ\",\n    \"password\": \"2FKzRrl%*hA#1FWz\"\n}\n", null, "text/plain");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Go - Native
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "{{HOST}}/encrypt-pwd"
  method := "POST"

  payload := strings.NewReader(`{
    "plain": "xE4t6Kv0/ThIIaZnyukmEJWse8EXkutDii29qQrapY/JNI69JMH57nKY7DN31oIJ",
    "password": "2FKzRrl%*hA#1FWz"
  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
JavaScript - Fetch
var raw = "{\n    \"plain\": \"xE4t6Kv0/ThIIaZnyukmEJWse8EXkutDii29qQrapY/JNI69JMH57nKY7DN31oIJ\",\n    \"password\": \"2FKzRrl%*hA#1FWz\"\n}\n";

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

fetch("{{HOST}}/encrypt-pwd", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Example Response

{
  "cipher": "628e4a6b814882df9353069585c15bf2f23a439650293e0f34784d9c95997190398a64d589e8c71cdb0cf689408c289d79adca7396ffd56013efd4dce0ea5445b0052b911ad15eeb2e9ecf069c7d0405119b5a4d199428bb3e6152fcddd2aa0dd9149d153ee4b1ff0433418f4df3ae0b0c5e7553c007e6daa7e56f42"
}

POST Encrypt with a public key

{{HOST}}/encrypt-rsa

This call is used to encrypt data with a public key and signature.

Public keys and signatures must originate from CoinCover and be retrieved using /encryption-key end-point.

Note that the size of the plain field is limited to 190 bytes.

Field Information

Field Description Mandatory

pub

Public key from /encryption-key response

Yes

signature

Signature from /encryption-key response

Yes

plain

Data to be asymmetrically encrypted

Yes

Response Codes

Code Description

200

OK

400

Bad request

Body raw (json)


{
    "pub": "r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a",
    "signature":"IHjvXcK9cB625yzfsm6GHix2nLB+TTaCff+wowjaRvypLo5SGuDFcgMJ6EfDoXi96SGr9IeB7sOU3lZF3ThvQMo=",
    "plain": "be3111cbfb2c07ce04d792d20121791c56d9e3d5ed6ba216f6ae21ba467b97ba8513d2c24ba4303bdb9de432682680748003ce52401c57ffc33542bd7a376268dadc57f572ab76651287d37618e507023964bf85b85a8afeb68f1259ff4172e0dd621ffe8f9d2027432a3d801c0dcac431b92cf42a55defa43eed93e"
}

Example Request

cURL - cURL
curl --location -g '{{HOST}}/encrypt-rsa' \
--data '{
    "pub": "r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a",
    "signature":"IHjvXcK9cB625yzfsm6GHix2nLB+TTaCff+wowjaRvypLo5SGuDFcgMJ6EfDoXi96SGr9IeB7sOU3lZF3ThvQMo=",
    "plain": "be3111cbfb2c07ce04d792d20121791c56d9e3d5ed6ba216f6ae21ba467b97ba8513d2c24ba4303bdb9de432682680748003ce52401c57ffc33542bd7a376268dadc57f572ab76651287d37618e507023964bf85b85a8afeb68f1259ff4172e0dd621ffe8f9d2027432a3d801c0dcac431b92cf42a55defa43eed93e"
}
'
C# - HttpClient
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "{{HOST}}/encrypt-rsa");
var content = new StringContent("{ \n    \"pub\": \"r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a\",\n    \"signature\":\"IHjvXcK9cB625yzfsm6GHix2nLB+TTaCff+wowjaRvypLo5SGuDFcgMJ6EfDoXi96SGr9IeB7sOU3lZF3ThvQMo=\",\n    \"plain\": \"be3111cbfb2c07ce04d792d20121791c56d9e3d5ed6ba216f6ae21ba467b97ba8513d2c24ba4303bdb9de432682680748003ce52401c57ffc33542bd7a376268dadc57f572ab76651287d37618e507023964bf85b85a8afeb68f1259ff4172e0dd621ffe8f9d2027432a3d801c0dcac431b92cf42a55defa43eed93e\"\n}\n", null, "text/plain");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Go - Native
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "{{HOST}}/encrypt-rsa"
  method := "POST"

  payload := strings.NewReader(`{
    "pub": "r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a",
    "signature":"IHjvXcK9cB625yzfsm6GHix2nLB+TTaCff+wowjaRvypLo5SGuDFcgMJ6EfDoXi96SGr9IeB7sOU3lZF3ThvQMo=",
    "plain": "be3111cbfb2c07ce04d792d20121791c56d9e3d5ed6ba216f6ae21ba467b97ba8513d2c24ba4303bdb9de432682680748003ce52401c57ffc33542bd7a376268dadc57f572ab76651287d37618e507023964bf85b85a8afeb68f1259ff4172e0dd621ffe8f9d2027432a3d801c0dcac431b92cf42a55defa43eed93e"
  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
JavaScript - Fetch
var raw = "{ \n    \"pub\": \"r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a\",\n    \"signature\":\"IHjvXcK9cB625yzfsm6GHix2nLB+TTaCff+wowjaRvypLo5SGuDFcgMJ6EfDoXi96SGr9IeB7sOU3lZF3ThvQMo=\",\n    \"plain\": \"be3111cbfb2c07ce04d792d20121791c56d9e3d5ed6ba216f6ae21ba467b97ba8513d2c24ba4303bdb9de432682680748003ce52401c57ffc33542bd7a376268dadc57f572ab76651287d37618e507023964bf85b85a8afeb68f1259ff4172e0dd621ffe8f9d2027432a3d801c0dcac431b92cf42a55defa43eed93e\"\n}\n";

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

fetch("{{HOST}}/encrypt-rsa", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Example Response

{
  "cipher": "628e4a6b814882df9353069585c15bf2f23a439650293e0f34784d9c95997190398a64d589e8c71cdb0cf689408c289d79adca7396ffd56013efd4dce0ea5445b0052b911ad15eeb2e9ecf069c7d0405119b5a4d199428bb3e6152fcddd2aa0dd9149d153ee4b1ff0433418f4df3ae0b0c5e7553c007e6daa7e56f42"
}

POST Store encrypted data

{{HOST}}/store

Encrypted data can be sent to CoinCover to be stored on our secure platform. Ensure that any data has been encrypted in line with requirements before it is posted to CoinCover.

Field Information

Field Description Mandatory

endUserId

User Id of the partners end-user relevant to the partners systems

Yes

data

Data to be stored securely with CoinCover

Yes

backupKey

Public key used to encrypt the data

Yes

Response Codes

Code Description

201

Created

400

Bad request

Body raw (json)


{
    "endUserId": "jb001",
    "data": "2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab",
    "backupKey": "r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a"
}

Example Request

cURL - cURL
curl --location -g '{{HOST}}/store' \
--data '{
    "endUserId": "jb001",
    "data": "2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab",
    "backupKey": "r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a"
}
'
C# - HttpClient
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "{{HOST}}/store");
var content = new StringContent("{\n    \"endUserId\": \"jb001\",\n    \"data\": \"2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab\",\n    \"backupKey\": \"r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a\"\n}\n", null, "text/plain");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Go - Native
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "{{HOST}}/store"
  method := "POST"

  payload := strings.NewReader(`{
    "endUserId": "jb001",
    "data": "2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab",
    "backupKey": "r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a"
  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
JavaScript - Fetch
var raw = "{\n    \"endUserId\": \"jb001\",\n    \"data\": \"2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab\",\n    \"backupKey\": \"r2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541743448436e5057366f3332794a744d334d77586b0a2f7242715253375a457a586a374a584e316757356e4862323850654b51316f4c6862345a44323159386e6d4c3479736a74635678726966384d5472662f676f550a65706d74586e6f6a683143432b5845597a47346a6e4e493142434d745151332b66656e713769324e384d742f4c6256724b70486865584b59413157364c4c616a0a536f644a6c642b7a6d4d4a2b766a34786744414a372f4b44764267522f6e5034456a50646d667a66566f516c42614e3046684d67356a6a6870636766516f79380a72306b754e55556f6a732b6e6c30546d2f61673449695367474b476f6f2b32736e2b4743366c6143386842493951695042794a462b724c5a715953692f5252660a2b756c582b5876574a392b36577a646c474c4a71474d506e515451732f646239306f7431487664304346332b3753384f63772f4f7439796f6b365531535a42300a756b73374a394678706c71642b546e38534f3641384a6261534d504d62366269767665636736355658565264446e7968776d56425536445365756379334758370a7a64756a543774443946633870584e4a785546786543326d4d5474653255616e77724d31656c6b4a4349612b3246455a54476f4576484363694c4a45374f72340a64582b372f587a575156526b446b52342b6a76736b77517074784b2f6d6657704d3058506c4a5a4548463152666d514f573867462f56736150563668695337390a6a697842366d5832346766672f5062517556695245416c4a5a32534a36496b4a484a4c627a44397964494154374d4b36307033384c4a45376b365845373666630a653551466571746c696a78753163614765314b655250652f7175436a65746d526e77546c476f765056625a5a4b7467634a6a4a56366a31776c675238526e55520a494e48314e7a4364375847323650394c44414b394a6a63434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a\"\n}\n";

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

fetch("{{HOST}}/store", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Example Response

            No response body
This request doesn't return any response body

POST Store encrypted PII data

{{HOST}}/store-kyc

Field Information

Field Description Mandatory

endUserId

User Id of the partners end-user relevant to the partners systems

Yes

pii

Data to be stored securely with CoinCover. json body

Yes

Body raw (json)


{
    "endUserId": "jb001",
    "pii": {"": ""}

}

Example Request

cURL - cURL
curl --location -g '{{HOST}}/store-kyc' \
--data '{
    "endUserId": "jb001",
    "pii": {"": ""}

}'
C# - HttpClient
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "{{HOST}}/store-kyc");
var content = new StringContent("{\n    \"endUserId\": \"jb001\",\n    \"pii\": {\"\": \"\"}\n    \n}", null, "text/plain");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Go - Native
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "{{HOST}}/store-kyc"
  method := "POST"

  payload := strings.NewReader(`{
    "endUserId": "jb001",
    "pii": {"": ""}

  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
JavaScript - Fetch
var raw = "{\n    \"endUserId\": \"jb001\",\n    \"pii\": {\"\": \"\"}\n    \n}";

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

fetch("{{HOST}}/store-kyc", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Example Response

            No response body
This request doesn't return any response body

POST Store file

{{HOST}}/store-file

You can send a file to be stored in the CoinCover secure platform against an end user ID.

The endUserId Header is required

Response Codes

Code Description

201

Created

400

Bad request

403

Unauthorized

HEADERS


endUserId
backupkey

Body formdata


file

Example Request

cURL - cURL
curl --location -g '{{HOST}}/store-file' \
--header 'endUserId;' \
--header 'backupKey;' \
--form 'file=@"/path/to/file"'
C# - HttpClient
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "{{HOST}}/store-file");
request.Headers.Add("endUserId", "");
request.Headers.Add("backupKey", "");
var content = new MultipartFormDataContent();
content.Add(new StreamContent(File.OpenRead("")), "file", "");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Go - Native
package main

import (
  "fmt"
  "bytes"
  "mime/multipart"
  "os"
  "path/filepath"
  "io"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "{{HOST}}/store-file"
  method := "POST"

  payload := &bytes.Buffer{}
  writer := multipart.NewWriter(payload)
  file, errFile1 := os.Open("/path/to/file")
  defer file.Close()
  part1,
        errFile1 := writer.CreateFormFile("file",filepath.Base("/path/to/file"))
  _, errFile1 = io.Copy(part1, file)
  if errFile1 != nil {
    fmt.Println(errFile1)
    return
  }
  err := writer.Close()
  if err != nil {
    fmt.Println(err)
    return
  }


  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  req.Header.Add("endUserId", "")
  req.Header.Add("backupKey", "")

  req.Header.Set("Content-Type", writer.FormDataContentType())
  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
JavaScript - Fetch
var myHeaders = new Headers();
myHeaders.append("endUserId", "");
myHeaders.append("backupKey", "");

var formdata = new FormData();
formdata.append("file", fileInput.files[0], "file");

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: formdata,
  redirect: 'follow'
};

fetch("{{HOST}}/store-file", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Example Response

            No response body
This request doesn't return any response body

POST Post Sale

{{HOST}}/update-product

For a Customer’s Disaster Recovery to become active, a sale needs to be posted to our API.

This applies for new sales and cancellations. This is also the mechanism for end-user KYC data to be shared with CoinCover.

At the end of each month, CoinCover will review the data and retrospectively bill, based what has been posted to the API and in line with contractual terms.

It is important to note that with these posts, we require essential user details as well as declarations that they have been verified via suitable KYC practices and that 2FA is active on an account.

Save the response

When a successful post is received, it returns an Id.
This Id must be saved.

Field Information

Field Description Mandatory

userId

User Id of the partners end-user relevant to the partners systems

Yes

firstName

First name

Yes

lastName

Last name

Yes

dob

Date of Birth

Yes

company

Company of user where related to a business

No

residenceCountry

Yes

kycCompleted

Declaration of true is required

Yes

2faActive

Declaration of true is required

Yes

nationality

Nationality of end-user https://www.iso.org/obp/ui/#search for supported format

Yes

productType

For DR this will always be DPG

Yes

requestType

new or cancel

Yes

orderId

Partner unique reference for the post to support additional reconciliation

Yes

levelUSD

Set this to 0

Yes

startDate

Date that the policy starts. Set data to the following format as per the example format.
YYYY-MM-DDT00:00:00Z

Yes

endDate

Date that the policy ends. Set data to the following format as per the example format.
YYYY-MM-DDT00:00:00Z

Yes

walletId

Yes

backupKey

Public key used to encrypt the data

Yes

Response Codes

Code Description

201

OK with response ID.
Save this ID for reference

400

Bad request

Body raw


{
    "userId": "jb001",
    "firstName": "Joe",
    "lastName": "Blogs",
    "dob": "1975-05-01T00:00:00Z",
    "company": "",
    "residenceCountry": "US",
    "nationality": "US",
    "kycCompleted": true,
    "2faActive": true,
    "productType": "DPG",
    "requestType": "NEW",
    "orderId": "5926",
    "levelUSD": 0,
    "startDate": "2022-01-01T00:00:00Z",
    "endDate": "2023-01-01T00:00:00Z",
    "walletId": "2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn",
    "backupKey": "2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab"
}

Example Request

cURL - cURL
curl --location -g '{{HOST}}/update-product' \
--data '{
    "userId": "jb001",
    "firstName": "Joe",
    "lastName": "Blogs",
    "dob": "1975-05-01T00:00:00Z",
    "company": "",
    "residenceCountry": "US",
    "nationality": "US",
    "kycCompleted": true,
    "2faActive": true,
    "productType": "DPG",
    "requestType": "NEW",
    "orderId": "5926",
    "levelUSD": 0,
    "startDate": "2022-01-01T00:00:00Z",
    "endDate": "2023-01-01T00:00:00Z",
    "walletId": "2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn",
    "backupKey": "2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab"
}
'
C# - HttpClient
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "{{HOST}}/update-product");
var content = new StringContent("{\n    \"userId\": \"jb001\",\n    \"firstName\": \"Joe\",\n    \"lastName\": \"Blogs\",\n    \"dob\": \"1975-05-01T00:00:00Z\",\n    \"company\": \"\",\n    \"residenceCountry\": \"US\",\n    \"nationality\": \"US\",\n    \"kycCompleted\": true,\n    \"2faActive\": true,\n    \"productType\": \"DPG\",\n    \"requestType\": \"NEW\",\n    \"orderId\": \"5926\",\n    \"levelUSD\": 0,\n    \"startDate\": \"2022-01-01T00:00:00Z\",\n    \"endDate\": \"2023-01-01T00:00:00Z\",\n    \"walletId\": \"2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn\",\n    \"backupKey\": \"2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab\"\n}\n", null, "text/plain");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Go - Native
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "{{HOST}}/update-product"
  method := "POST"

  payload := strings.NewReader(`{
    "userId": "jb001",
    "firstName": "Joe",
    "lastName": "Blogs",
    "dob": "1975-05-01T00:00:00Z",
    "company": "",
    "residenceCountry": "US",
    "nationality": "US",
    "kycCompleted": true,
    "2faActive": true,
    "productType": "DPG",
    "requestType": "NEW",
    "orderId": "5926",
    "levelUSD": 0,
    "startDate": "2022-01-01T00:00:00Z",
    "endDate": "2023-01-01T00:00:00Z",
    "walletId": "2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn",
    "backupKey": "2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab"
  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
JavaScript - Fetch
var raw = "{\n    \"userId\": \"jb001\",\n    \"firstName\": \"Joe\",\n    \"lastName\": \"Blogs\",\n    \"dob\": \"1975-05-01T00:00:00Z\",\n    \"company\": \"\",\n    \"residenceCountry\": \"US\",\n    \"nationality\": \"US\",\n    \"kycCompleted\": true,\n    \"2faActive\": true,\n    \"productType\": \"DPG\",\n    \"requestType\": \"NEW\",\n    \"orderId\": \"5926\",\n    \"levelUSD\": 0,\n    \"startDate\": \"2022-01-01T00:00:00Z\",\n    \"endDate\": \"2023-01-01T00:00:00Z\",\n    \"walletId\": \"2MwUiWHwh8NYtGyDed1pamSM72DSBYm2qAn\",\n    \"backupKey\": \"2e49d511ea4f7fd5be49fc7de58d400818bea812d96cdb6f1fba3590305ed504665ce507922d9c6a9a7e74abafc7b3c2caf322eb419a8d56edc6280501ca0994526d98f60b149d70521346140e8382f5b474b52968d80f8e7d13011df0d39f9fac49653271f2f98bd1060bc8bbc99b6adcfabce720098d622f082bbe6ea43ec6f631ba81e5d08c282ba591eb7a25aaef305410b07bdf0bd07fa3492f1dad91004d9a3e26f47fffce1a6938d86d42de48f6ba4283d8bb0e77c65b7e8b97f5c87e73020d2a3437c30c6d410d7764147e33e84d02182f17a2ccd1ccc6d59a5b4fa484350320f15f95bcd42f1fc026404fba98235c33c7fdec49f7fb5b388bb4e69f6fe5fdb2bde59f7c650a657f15a91ba9298b70a70b65bf9cb04a723b700ee5252f53f04d0d9b451886eb5795534d82a0a390cc01c33307e04f427eb8b10066c6adab538105356c7445a34b96d99f35d3d5885b93cb1b0e8b8ff28cc9820d5ebe9ac60f28b6fee3852eb48e2dfed5bcbc2d1f1ebe805cdc418e7c45fbedf583505998eec917f65a226b208d0a8375066ca79ca9324116d7846f8b9351deba6523b5179af829803c58f98af3c7f8302c7cb5a009f50cb4d84a5a24e309ee975956916371b5d102ddb7789e0217fe73e155c35d5739e94200a7f37be8267c04503cec815f10df922f65b78836e5ff061ec7c48c83c0bf029232fc95f4d36e32ffab\"\n}\n";

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

fetch("{{HOST}}/update-product", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Example Response

{
  "id": "string"
}

Decrypt

POST Decrypt using private key

{{HOST}}/decrypt-rsa

At no point is a private key returned as part of this end-point. We manually return data to the customer based on successful identity verification. Also due to the cold nature of storing our private keys it would not be possible for this end-point to return data.

Field Information

Field Description Mandatory

priv

Private key associated with the public key used to encrypt the data

Yes

cipher

Encrypted data to be decrypted

Yes

Response Codes

Code Description

201

OK

Body raw


{
    "priv": "<Private Key>",
    "cipher": "<Public Key Encrypted Data>"
}

Example Request

cURL - cURL
curl --location -g '{{HOST}}/decrypt-rsa' \
--data '{
    "priv": "<Private Key>",
    "cipher": "<Public Key Encrypted Data>"
}
'
C# - HttpClient
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "{{HOST}}/decrypt-rsa");
var content = new StringContent("{\n    \"priv\": \"<Private Key>\",\n    \"cipher\": \"<Public Key Encrypted Data>\"\n}\n", null, "text/plain");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Go - Native
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "{{HOST}}/decrypt-rsa"
  method := "POST"

  payload := strings.NewReader(`{
    "priv": "<Private Key>",
    "cipher": "<Public Key Encrypted Data>"
  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
JavaScript - Fetch
var raw = "{\n    \"priv\": \"<Private Key>\",\n    \"cipher\": \"<Public Key Encrypted Data>\"\n}\n";

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

fetch("{{HOST}}/decrypt-rsa", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Example Response

{
  "plain": "string"
}

POST Decrypt using password

{{HOST}}/decrypt-pwd

Field Information

Field Description Mandatory

password

Password used to decrypt the data. It must be the same password that was used to encrypt it

Yes

cipher

Encrypted data to be decrypted

Yes

Response Codes

Code Description

201

OK

Body raw


{
    "password": "<Decryption password>",
    "cipher": "<Encrypted Data>"
}

Example Request

cURL - cURL
curl --location -g '{{HOST}}/decrypt-pwd' \
--data '{
    "password": "<Decryption password>",
    "cipher": "<Encrypted Data>"
}
'
C# - HttpClient
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "{{HOST}}/decrypt-pwd");
var content = new StringContent("{\n    \"password\": \"<Decryption password>\",\n    \"cipher\": \"<Encrypted Data>\"\n}\n", null, "text/plain");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Go - Native
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "{{HOST}}/decrypt-pwd"
  method := "POST"

  payload := strings.NewReader(`{
    "password": "<Decryption password>",
    "cipher": "<Encrypted Data>"
  }`)

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
    return
  }
  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}
JavaScript - Fetch
var raw = "{\n    \"password\": \"<Decryption password>\",\n    \"cipher\": \"<Encrypted Data>\"\n}\n";

var requestOptions = {
  method: 'POST',
  body: raw,
  redirect: 'follow'
};

fetch("{{HOST}}/decrypt-pwd", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Example Response

{
  "plain": "string"
}

Test Keys and Data

The following provides example test data, public and private keys, which can be used to stub and test the endpoints without having to engage CoinCover.

The following keys are TEST keys only and should be used for encrypting and decrypting TEST data only.

Public Key

2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494943496a414e42676b71686b6947397730424151454641414f43416738414d49494343674b4341674541744133336d692b534c2b2f6761466655414e62480a776d796d556f345455565031643850507a53755042374c774e3444545a2b61412b432b70635579546f4a3554624b6c786d334d355230346e636b74627649536b0a725132445633494642343537716a43506165346d654837764f5873634a4f3671704f342b3972745362773661364e4f6a2f31436e345056612f6c7259686678480a6362304d594e726d6d4853463377715854316b395151306f7a564e4e67656b69483262316d386359506a4745536b366153796443685568374c72513958416a6c0a6a50524a4a6267745458755a76486539327245654768796d7277506f4b316970637436695763694c665a636d786a525a4b464b524c7745686d63514353536e4c0a7047362b697834773543342f7a61534f6e7975455a7651686653715636663532755876666a6d654d356f726474714d7058775433683453416f6e5435464450340a6f577a744977457a766e5130346a484253494c7a6c45734635337a577252337237503250385273542b45646867454c30385a5a734f4474436d3973766d6a50390a4247515866636441435274437131754576652f59715163313151563333796159345966614e42386b526752745a41327958774769464a782b465358302f6f67610a4b716f3758513152697748736a43476f5a56544a43612f66305a687636346c72704859426a4c6e69704f555449483452503632626847324d49387763526635640a3059316b5264524c33464f4175344a7a7962502f354b364b595738596d78586e6b33587a57384f79735553566a655775443465593068735967552f6b767a365a0a417532625142646a3669594d42626d6857683730547933394b376843306f4938432f696f6f4e68744f6966633739633359524a326574636d3331586a577377770a6971714c4e356d716953454547744c72396c736a6c3363434177454141513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a

Signature

IKY3TAEs4FsK9rpCUsLFgeAy0mtkrIS0NpHe7Q8S7Un5Ufnk73mD5VEiZR4owdSKAxX7lR1iZ184/Bcpxl8iyJA=

Private Key

2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d49494a4b41494241414b4341674541744133336d692b534c2b2f6761466655414e6248776d796d556f345455565031643850507a53755042374c774e3444540a5a2b61412b432b70635579546f4a3554624b6c786d334d355230346e636b74627649536b725132445633494642343537716a43506165346d654837764f5873630a4a4f3671704f342b3972745362773661364e4f6a2f31436e345056612f6c7259686678486362304d594e726d6d4853463377715854316b395151306f7a564e4e0a67656b69483262316d386359506a4745536b366153796443685568374c72513958416a6c6a50524a4a6267745458755a76486539327245654768796d7277506f0a4b316970637436695763694c665a636d786a525a4b464b524c7745686d63514353536e4c7047362b697834773543342f7a61534f6e7975455a765168665371560a36663532755876666a6d654d356f726474714d7058775433683453416f6e5435464450346f577a744977457a766e5130346a484253494c7a6c45734635337a570a7252337237503250385273542b45646867454c30385a5a734f4474436d3973766d6a50394247515866636441435274437131754576652f5971516331315156330a33796159345966614e42386b526752745a41327958774769464a782b465358302f6f67614b716f3758513152697748736a43476f5a56544a43612f66305a68760a36346c72704859426a4c6e69704f555449483452503632626847324d49387763526635643059316b5264524c33464f4175344a7a7962502f354b364b595738590a6d78586e6b33587a57384f79735553566a655775443465593068735967552f6b767a365a417532625142646a3669594d42626d6857683730547933394b3768430a306f4938432f696f6f4e68744f6966633739633359524a326574636d3331586a577377776971714c4e356d716953454547744c72396c736a6c336343417745410a41514b43416742356b365449753635654a2f374339657230316848304f69446b52594c4e7533395836795035535a772b6570697849592b6437497252436e33440a5077322f757168694374666e4f78704742344f6a4c546334522b685a345848364c6363766e776e706c506942636f6b5065385a55626368484e39434a7055566d0a6e48334139332b71447034423235672f306577724b335267704551706a4a6b37485250766856365069447337484f713762674e4c4153436f773536437a6161790a4650464e72576e434d756b454c664a4178507849515050646e545243785142504d396d444a4235656f4176574378706b5430784e694c6e5036774966796979640a7130686b2b5262355a6f64394c714e527464585757662b6848314f654b426b4a48733273685834586754473855456f4b716e5769616f726e675362786636386f0a484d754c4c2b45645858616c376c696c624e62653231554553304e7075685647414c72654363644e674a514b6c6a4a35625638514f525164354f39442f456c6a0a44445a46704653334f34537170382f445430786a5069714b2b6e76692f564776775564596f477656484a4c384c774368426176696f715446464f4843693338740a4469424f4c4a50584150643563442f5547347964636a58485270584c756c416e6e674d76304544414b6873756c586d482f4147344f776a424c5138636268376c0a65534b727554324b33372f737656796377716e332b5454306349704c47783562777068316630714872733756392b2b5a2f756a6d4a4c394f61436535483861430a744a6e41323969432b7069674b524d2f6b663961576b474a7146482f3653345841624768664f622f366d4433493741613638304f4f3044463146345455786c390a617547447935543845316c4243304c412f436866494248644f35757555557133735441434b34686e3848596774446a6641514b4341514541343170364a4d704b0a663577385557547443396d7732456c482b69385573574264387a4d4e68714c375847373037704e424c38555268665141757a6233567a3264505443447a62724c0a6165484c4754302b4a635a44765361342f312f636d42656476764a6a335338527043682f7a70634b3231696b7a336c52323169452f305673726e39383253472b0a4173464452736d76707970584a3267652f7a6e50316232344c32635a7337636c624e75576c6e5630342b5069696e78484870506d3875525462316131475041360a3852375135465359525352796a6d6759493263472b5353396f3533554d6b39562b7151387435304f4b4d31373567453247474b464d32587332584d6f786e51670a4f3330696b47325057524a756c3377336b55364d4e5537456e325a47494a363230676231484e354338627454335069616245654655444167666467734e777a4b0a2b49654f493743624f50716631774b4341514541797233517968527861414d48454f42344d5549454238325a534f72385547785162507036516e4b77696b454a0a304155765a45466f71636a30354f4a4d6e4f4d6c5957742b675378712b7362477a57584a436970655a30473348692b704c66357539515966764a6650484152620a497479444a683458303037397147636d734d504b5253694e32385a692b4c756269702b67495946657a5933704c6f31774a7a47504655573256726859367957670a704f45534d50416139653233434a57425946425a39746854685546414177574743756d596a59677a422b4f766e4c4c347a47667534715a70304a54535a384d750a72743333472f33777a4d4952416f71616e73512b5452665369335264474b78366d775961773833596a77312b326b766d6547686f30324e78485a5664535658730a624f506a486778487866494b466d7a78774e43324c7a306a744d502f544f726370756d654f665a5259514b43415141613634757137346b43737930784e6849620a5a527462674e48552f64346c59704f39534435427775716764304c70504f5a72455a71526b654c4553433368567070587448626d3155646773697571515759710a63743979646a4e52696268464367625470542f4e344e546c36795733414974346a585a325770636d7363534e7456713544723970746d555a546d6a34364d697a0a736e2b2f577354513037655952323658726b324d79684c55594f766a784f536956306c72764774765933506c4c73507957774832676674347358317169396d370a3169543656376b442b42384c5152357a55537a66434358574637785977572f37784e6a323077336b74555777594645374c6a65567941704a4150676d77644a480a6162644f6d4a61377a6545734c72643561464c4661675762754e6374492b517057315543785330447854517a326e372b5a3670556d6c38754c6c37574f774d6d0a4c416268416f494241466e417747374673424c677a44372f634a593136487a66327730353469746b57424a32724b7441424d476632303035446d7275766676300a46393541424c5372706a2f4469385235756e35386730516f3347426773317734376d30786f6b3758525a3235635646585433765376646e6f447a4e5076544a780a314c2b3573706f7367783473767568646f6a45464e4f32676a77356d4c47634a66514a373450756f352f503934615077686f544c4b70767a6538386f624863560a48714e784e4535454a422b77557745364372474c7633535452314c597965616a4f4870426a50314977617562436c73706c7941536531633073704730304f61450a763230466d542f5346746167526a6777636f706179516861496e30755973477073732f484c43642f3658417a704c373541637857656f30574d6452366b55656a0a53433333577573474f7245632b764b716c686f69477a3756533550545a4f454367674542414a3775624a62776c39396261696d4b4b79337358643530554752450a586f7267526e3068375079626a457a706763356d4b71754c61634d5734386b343679454a56704135664c4c52355a356c4336794e7972707a5947762b586734720a664e556152686b435268764862617353796d694965754c344d4c4742685043326e345a3555514c7643524657794764766c6e5078587347696f4b672b5437764a0a53766b6f6e30417653762f70624b6468496d383744526a584c4f344e34337375647266706b44763659616b63544e482f41307373686365626f55786c544131440a6576655a6b2b72476e797a5167647a4a795872475148416e65326d4f765a7639755977555141304d3047774b6d63727473744f706464554f52504d48392b49450a373842576356364c757242502b6871696f793876765238434e315a4e73675a45474d6663536133466b2b494a666d31626e7377562f70323344736b3d0a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a

Key Signature Verification

When pulling a key from CoinCover using the /encryption-key endpoint, the response object contains a signature & public key property.

The signature & public key can be used in conjunction with a CoinCover provided signing key to verify that the key has indeed come from CoinCover.

Below, is a small Node.js example of how this may be achieved:

const bitcoinMessage = require('bitcoinjs-message');
const bjs = require('bitcoinjs-lib');
const { BIP32Factory } = require('bip32');
const ecc = require("tiny-secp256k1");
const verifyKeyIsFromCoincover = (publicKey, signature, signingKey) => {
    const bip32 = BIP32Factory(ecc);
    const signingPublicKey = bip32.fromBase58(signingKey).publicKey
    let signingKeyAddress = bjs.payments.p2pkh({ pubkey: signingPublicKey }).address;
    const verified = bitcoinMessage.verify(publicKey, signingKeyAddress, signature)
    console.log({ verified })
}
const PUBLIC_KEY_HEX = "YOUR_PUBLIC_KEY"
const SIGNATURE = "YOUR_PUBLIC_KEY_SIGNATURE"
const COIN_COVER_PROVIDED_PUBLIC_SIGNING_KEY = "REQUEST_SIGNING_KEY_FROM_COINCOVER"
verifyKeyIsFromCoincover(PUBLIC_KEY_HEX, SIGNATURE, COIN_COVER_PROVIDED_PUBLIC_SIGNING_KEY)

NOTE:
In order for this script to work, a test signing key will need to be requested from CoinCover & assigned to:

COIN_COVER_PROVIDED_PUBLIC_SIGNING_KEY

The PUBLIC_KEY_HEX & SIGNATURE must be assigned the value of the public key & signature retrieved from the /encryption-key endpoint.