<p>I did some digging into Coinbase's <a href="https://github.com/coinbase/multisig-tool" rel="noreferrer">offline multisig tool</a> to figure out what the user seed actually was and their derivation paths. It turns out the user seed is just that, a seed that is used to get the Master Private Key. This is done by hashing it with HMAC-SHA512 where the key is the string <code>Bitcoin seed</code> and the data is the binary form of the user seed (which means decode it and get the binary data). </p>

<p>To do this with <code>pybitcointools</code>, we first decode the WIF user seed with <code>decode_privkey</code> and re-encode it with <code>encode_privkey</code> in order to get the binary form. Then we pass that into <code>bip32_master_key</code> to get the bip32 master key from that seed. And from there, just call <code>bip32_ckd</code> to get the extended private key of whichever index child we want. Lastly we extract the actual private key with <code>bip32_bin_extract_key</code> and encode that with <code>encode_privkey</code> in order to get it into WIF form which can be imported and used in other wallet software.</p>

<p>The below code does all of this for you and will print out the extended master private key derived from the seed, the extended public key derived from the master key (which should match the public key you have), the extended child private key, and that child key in WIF.</p>

<p>Replace the values for USER_PUB, USER_SEED, and I with your actual user public key, user seed, and child index that you want. The values I have here are real and will work.</p>

<pre><code>from pybitcointools.deterministic import bip32_ckd, bip32_master_key, bip32_bin_extract_key, bip32_privtopub
from pybitcointools.main import decode_privkey, encode_privkey

USER_PUB = 'xpub661MyMwAqRbcEzdGMFKZXuVwbyHY2zKhiw6YFTrULfNBF53QVfXyoAiKMZKWkQA5444NXtLj9HPmgyN1xLCiJJ9dKAy4nLZJ87trHRnwUDb'
USER_SEED = 'L3XCYcQ2pwY3YTuwyPXzWsvVtGnCp4zL2ajP3XQt2pVhPuKiVM7r'
I = 14

user_seed = encode_privkey(decode_privkey(USER_SEED), 'bin')
priv = bip32_master_key(user_seed)
derived_pub = bip32_privtopub(priv)
child_priv = bip32_ckd(priv, I)
assert USER_PUB == derived_pub
print "Master Private Key corresponding to seed: " + priv
print "Master Public Key corresponding to seed: " + derived_pub
print "Extended Private key at index " + str(I) + ": " + child_priv
print "WIF format of that key: " + encode_privkey(bip32_bin_extract_key(child_priv), 'wif_compressed')
</code></pre>

CC BY-SA 3.0
2017-07-28T09:23:39.877Z
Excellent, this works perfectly!
Erwin Mayer
CC BY-SA 3.0
2017-07-28T05:41:28.443Z
2017-07-28T05:41:28.443Z
Ava Chow
<p>When I created a multi-sig vault on Coinbase, I obtained:</p>

<ol>
<li>A master public key in BIP32 extended format, of depth <code>0</code>, parent fingerprint <code>00000000</code> and child index <code>0</code>.</li>
<li>A private key in WIF format ("user seed"), which I don't know if it has been hardened, derived from a public key, nor the depth or index.</li>
</ol>

<p>I am trying to prove ownership of an address derived from the master public key at index <code>14</code>. So using <a href="http://bip32.org" rel="nofollow noreferrer">bip32.org</a> I have been able to derive the public key in BIP32 extended format at index <code>m/14</code>, that corresponds exactly to the address for which I need to prove ownership.</p>

<p>My objective now is therefore to derive the private key for which the address is the same as the address of the derived public key at index <code>m/14</code>, based on the information I have. If possible with <code>pybitcointools</code>.</p>

<p>I tried asking a more general question <a href="https://bitcoin.stackexchange.com/questions/55383/how-to-convert-a-wif-private-key-to-a-bip32-extended-private-key">here</a>, but it was a good case of <a href="http://xyproblem.info/" rel="nofollow noreferrer">XY problem</a> (I asked about my attempted solution rather than actual problem).</p>

CC BY-SA 3.0
2017-07-28T03:52:16.210Z
Do you mind posting an example xpub/WIF/generated address? It would help me figure out what they want you to do. (Not one you're using to handle actual money, obviously.)
Nick ODell
<private-key><coinbase.com><multi-signature><recover-private-key><pybitcointools>
How to derive the private key associated with a Coinbase multi-sig vault address
Erwin Mayer
# How to derive the private key associated with a Coinbase multi-sig vault address

(Asked by: username_0 on 2017-07-28)

When I created a multi-sig vault on Coinbase, I obtained:

1. A master public key in BIP32 extended format, of depth `0`, parent fingerprint `00000000` and child index `0`.
2. A private key in WIF format ("user seed"), which I don't know if it has been hardened, derived from a public key, nor the depth or index.

I am trying to prove ownership of an address derived from the master public key at index `14`. So using [bip32.org](http://bip32.org) I have been able to derive the public key in BIP32 extended format at index `m/14`, that corresponds exactly to the address for which I need to prove ownership.

My objective now is therefore to derive the private key for which the address is the same as the address of the derived public key at index `m/14`, based on the information I have. If possible with `pybitcointools`.

I tried asking a more general question [here](https://bitcoin.stackexchange.com/questions/55383/how-to-convert-a-wif-private-key-to-a-bip32-extended-private-key), but it was a good case of [XY problem](http://xyproblem.info/) (I asked about my attempted solution rather than actual problem).

**Tags:** private-key, coinbase.com, multi-signature, recover-private-key, pybitcointools

> **Comments:**
> **username_1**: Do you mind posting an example xpub/WIF/generated address? It would help me figure out what they want you to do. (Not one you're using to handle actual money, obviously.)  

---

## 1 answers

### Answer by username_2 on 2017-07-28. Score: 5 | Accepted answer

I did some digging into Coinbase's [offline multisig tool](https://github.com/coinbase/multisig-tool) to figure out what the user seed actually was and their derivation paths. It turns out the user seed is just that, a seed that is used to get the Master Private Key. This is done by hashing it with HMAC-SHA512 where the key is the string `Bitcoin seed` and the data is the binary form of the user seed (which means decode it and get the binary data).

To do this with `pybitcointools`, we first decode the WIF user seed with `decode_privkey` and re-encode it with `encode_privkey` in order to get the binary form. Then we pass that into `bip32_master_key` to get the bip32 master key from that seed. And from there, just call `bip32_ckd` to get the extended private key of whichever index child we want. Lastly we extract the actual private key with `bip32_bin_extract_key` and encode that with `encode_privkey` in order to get it into WIF form which can be imported and used in other wallet software.

The below code does all of this for you and will print out the extended master private key derived from the seed, the extended public key derived from the master key (which should match the public key you have), the extended child private key, and that child key in WIF.

Replace the values for USER\_PUB, USER\_SEED, and I with your actual user public key, user seed, and child index that you want. The values I have here are real and will work.

```
from pybitcointools.deterministic import bip32_ckd, bip32_master_key, bip32_bin_extract_key, bip32_privtopub
from pybitcointools.main import decode_privkey, encode_privkey

USER_PUB = 'xpub661MyMwAqRbcEzdGMFKZXuVwbyHY2zKhiw6YFTrULfNBF53QVfXyoAiKMZKWkQA5444NXtLj9HPmgyN1xLCiJJ9dKAy4nLZJ87trHRnwUDb'
USER_SEED = 'L3XCYcQ2pwY3YTuwyPXzWsvVtGnCp4zL2ajP3XQt2pVhPuKiVM7r'
I = 14

user_seed = encode_privkey(decode_privkey(USER_SEED), 'bin')
priv = bip32_master_key(user_seed)
derived_pub = bip32_privtopub(priv)
child_priv = bip32_ckd(priv, I)
assert USER_PUB == derived_pub
print "Master Private Key corresponding to seed: " + priv
print "Master Public Key corresponding to seed: " + derived_pub
print "Extended Private key at index " + str(I) + ": " + child_priv
print "WIF format of that key: " + encode_privkey(bip32_bin_extract_key(child_priv), 'wif_compressed')

```

> **Comments:**
> **username_0**: Excellent, this works perfectly!  

---

