# Create Multisignature Keys

Source: https://developers.bitgo.com/docs/wallets-create-multisig-keys

## Overview

For self-custody multisignature wallets, you can create your own user and backup keys. Key creation occurs entirely client side. At no point does BitGo have access to your private user or backup keys for self-custody wallets. However, BitGo always creates and stores the BitGo key.

The following are the differences between keys for cold and hot wallets:

* **Cold wallets** - Enhance your security by creating keys on an air-gapped machine, either programmatically (using the steps below) or through the Offline Vault Console ([OVC](/docs/ovc)). When you create a cold wallet, you send to BitGo only your public keys.
* **Hot wallets** - Quickly create keys, client side, on an internet-connected machine. When you create a hot wallet, you send to BitGo your public key and versions of your private keys encrypted using your passphrase.

> 📘 **Note**
>
> If you want to store your own keys for your self-custody wallets, follow the steps in [Set Up External-Signing Mode](/docs/wallets-external-signer-mode).

## Prerequisites

[Get Started](/docs/get-started-intro)

## Cookbook

Need just the steps? Expand the cookbook below to get started:

<Cookbook slug="create-multisig-keys" title="Create Multisignature Keys" />

## 1. Create Public and Private Keys

>Endpoint: [Create Key](/reference/expresskeychainlocal)

```shell cURL
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export COIN="<ASSET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/keychain/local \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```
```js JavaScript
const BitGoJS = require('bitgo');
const bitgo = new BitGoJS.BitGo({ env: 'test' });

// Set your access token here
const accessToken = 'v2xcbe8617bd58947a9ec41cc7a92e0a9a9d81dc2780669faa59eab3016ad5792ae';
// Set your coin of choice here
const coin = 'tbtc4';

bitgo.authenticateWithAccessToken({ accessToken });
let key = bitgo.coin(coin).keychains().create();
console.dir(key);
```

#### Step Result

> 📘 **Note**
>
> This response contains critical key material. Save it in a secure place. This is the only time you're given the full private key.

```json JSON
{
  "pub": "xpub661MyMwAqRbcEq5qQLciVPfCyCvx9KstKVp71TxujjY9Kbapv6o2YjtRAV1tfYgQZxBaN6FfFfE3CD21ZRSsd4WkqkFWSZDTiDqf49qtkh7",
  "prv": "xprv9s21ZrQH143K2M1NJK5i8FiURB6TjsA2xGtWD5ZJBQ1ASoFgNZUmzwZwKC9WnyRaN2f4uAdHPdMmLbw2SsUKa6J2bWUEWihbMKcrhJSZueH"
}
```

Repeat this step two more times to create the backup and BitGo keys. This step may appear to create the actual BitGo key. However, the `pub` and `priv` that you receive for the BitGo key are only temporary. BitGo creates the actual public and private key pair for the BitGo key after the following step.

## 2. Upload Public Keys to BitGo

Upload the public keys and an encrypted version of the private keys to BitGo.

Passing a value for the `encryptedPrv` parameter on the user and backup keys enables you to use your `walletPassphrase` to sign transactions from self-managed hot wallets. If omitted, signing transactions requires passing your full, unencrypted private key.

> 📘 **Note**
>
> BitGo recommends using your BitGo login passphrase for your `encryptedPrv`. This results in your `walletPassphrase` being the same as your BitGo login passphrase. If you update your BitGo login passphrase, all shared wallet passphrases also update. However, if your wallet passphrases differ from your BitGo login passphrase, you must manage them all separately.

If you want to store your own keys for your self-custody wallets, follow the steps in [Set Up External-Signing Mode](/docs/wallets-external-signer-mode).

>Endpoint: [Create Key](/reference/v2keyadd)

```shell cURL
export COIN="<ASSET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ENTERPRISE="<YOUR_ENTERPRISE_ID>"
export PUB="<YOUR_PUBLIC_KEY>"
export ENCRYPTED_PRV="<YOUR_BITGO_LOGIN_PASSPHRASE>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/$COIN/key \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "enterprise": "'"$ENTERPRISE"'",
    "source": "user",
    "pub": "'"$PUB"'",
    "encryptedPrv": "'"$ENCRYPTED_PRV"'" # Enables signing with the walletPassphrase
                                         # If omitted, signing requires passing the
                                         # full unencrypted private key
  }'
```
```js JavaScript
// Creates user key
let userKey = bitgo.coin("tbtc4").keychains().create();

// Creates BitGo key
let bitGoKey = bitgo.coin("tbtc4").keychains().createBitGo();

// Creates backup key
let backupKey = bitgo
  .coin("tbtc4")
  .keychains()
  .createBackup({ provider: "coincover" });
```

#### Step Result

> 📘 **Note**
>
> This response contains critical key material. Save it in a secure place. This is the only time you're given the full `encryptedPrv` that you use to decrypt the user key.

```json JSON
{
  "id": "68499a2877a6825438c3339f769ee77a",
  "pub": "xpub661MyMwAqRbcGzKB8maGqFbyvCVGiuMTeRRtRH8pGZ1ozpMJPtkVL9LL6vPT2Xg6BHJCADbDg88byz6Z9eawDqSJkRMnHcQj4TrDVW5vN79",
  "ethAddress": "0x884089925e0a735027679ea14425b4b76b216f69",
  "source": "user",
  "type": "independent",
  "encryptedPrv": "VerySecurePassword1234"
}
```

You receive an `id` for the key that you will use when you create your wallet. Repeat this step two more times to upload the backup key and BitGo keys.

Upon uploading the BitGo key, BitGo creates the actual public and private key pair for the BitGo key. BitGo stores the BitGo key and doesn't share it with you. Although you use the `id` for the BitGo key to create a wallet, you can't use the BitGo key you created in step 1 to co-sign transactions.

## Next

Use the `id` for each key when you [Create Wallets](/docs/wallets-create-wallets).

## See Also

* [API Reference: Create Key](/reference/expresskeychainlocal)
* [API Reference: Create Key](/reference/v2keyadd)
* [Concept: BitGo Wallet Types](/docs/wallet-types)
* [Concept: Offline Vault Console](/docs/ovc)
