<p><a href="https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki" rel="nofollow noreferrer">BIP32</a> specifies the serialization format used by extended keys as: </p>

<blockquote>
  <p>Serialization format Extended public and private keys are serialized
  as follows:</p>
  
  <ul>
  <li>4 byte: version bytes (mainnet: 0x0488B21E public, 0x0488ADE4 private;
  testnet: 0x043587CF public, 0x04358394 private)  </li>
  <li>1 byte: depth: 0x00 for master nodes, 0x01 for level-1 derived keys, </li>
  <li>4 bytes: the fingerprint of the parent's key (0x00000000 if master key) </li>
  <li>4 bytes: child number. This is ser32(i) for i in xi = xpar/i, with xi the key being serialized. (0x00000000 if master key) </li>
  <li>32 bytes: the chain code</li>
  <li>33 bytes: the public key or private key data (serP(K) for public keys,
  0x00 || ser256(k) for private keys)  </li>
  </ul>
  
  <p>This 78 byte structure can be
  encoded like other Bitcoin data in Base58, by first adding 32 checksum
  bits (derived from the double SHA-256 checksum), and then converting
  to the Base58 representation. This results in a Base58-encoded string
  of up to 112 characters. Because of the choice of the version bytes,
  the Base58 representation will start with "xprv" or "xpub" on mainnet,
  "tprv" or "tpub" on testnet. </p>
  
  <p>Note that the fingerprint of the parent
  only serves as a fast way to detect parent and child nodes in
  software, and software must be willing to deal with collisions.
  Internally, the full 160-bit identifier could be used.</p>
  
  <p>When importing a serialized extended public key, implementations must
  verify whether the X coordinate in the public key data corresponds to
  a point on the curve. If not, the extended public key is invalid.</p>
</blockquote>

<p>Your PHP code must first run the b58check algorithm to verify the xpub is encoded correctly, and then decode it into the above values. Lastly, you must check that the pubkey found by decoding the xpub is a value point on the secp256k1 curve.</p>

CC BY-SA 4.0
2018-11-05T12:42:30.913Z
Thank you for your quick and very informative reply!
L. Mark
CC BY-SA 4.0
2019-05-08T17:45:58.917Z
Can this also be done in javascript (for input form validation), or are there special PHP functions that enable this?
pferg
CC BY-SA 4.0
2018-11-05T09:11:05.137Z
2018-11-05T09:11:05.137Z
Raghav Sood
<p>Can someone please help me find some PHP open source on how to validate / verify a bitcoin wallet public key ? I am currently working on a project  and I am implementing multisig, and it seems I can't find any type of information on how to verify / validate a wallet public key.</p>

<p>Example of public key that I am trying to validate: xpub661MyMwAqRbcEwAAmd9DpSfoDEUar3C2e8LtpeMCaaPWMoLjAf3jY3RucUmtim729c2qzGmYPaBcFdkEUQuwgrFjTKFwEKSCfRfd949k4DC</p>

<p>Basically, I want to make sure the user can't add a wrong or invalid key, otherwise the multisig wallet cannot be created when the system will try to create it, and I need to prevent that</p>

<p>Thank you for your time!</p>

CC BY-SA 4.0
2018-11-08T08:24:14.827Z
That's not a public key.
Claris
<bitcoin-core><public-key><php>
PHP How can I validate / verify a wallet public key?
L. Mark
# PHP How can I validate / verify a wallet public key?

(Asked by: username_0 on 2018-11-05)

Can someone please help me find some PHP open source on how to validate / verify a bitcoin wallet public key ? I am currently working on a project and I am implementing multisig, and it seems I can't find any type of information on how to verify / validate a wallet public key.

Example of public key that I am trying to validate: xpub661MyMwAqRbcEwAAmd9DpSfoDEUar3C2e8LtpeMCaaPWMoLjAf3jY3RucUmtim729c2qzGmYPaBcFdkEUQuwgrFjTKFwEKSCfRfd949k4DC

Basically, I want to make sure the user can't add a wrong or invalid key, otherwise the multisig wallet cannot be created when the system will try to create it, and I need to prevent that

Thank you for your time!

**Tags:** bitcoin-core, public-key, php

> **Comments:**
> **username_1**: That's not a public key.  

---

## 1 answers

### Answer by username_2 on 2018-11-05. Score: 1

[BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) specifies the serialization format used by extended keys as:

> Serialization format Extended public and private keys are serialized
> as follows:
>
> * 4 byte: version bytes (mainnet: 0x0488B21E public, 0x0488ADE4 private;
>   testnet: 0x043587CF public, 0x04358394 private)
> * 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 derived keys,
> * 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
> * 4 bytes: child number. This is ser32(i) for i in xi = xpar/i, with xi the key being serialized. (0x00000000 if master key)
> * 32 bytes: the chain code
> * 33 bytes: the public key or private key data (serP(K) for public keys,
>   0x00 || ser256(k) for private keys)
>
> This 78 byte structure can be
> encoded like other Bitcoin data in Base58, by first adding 32 checksum
> bits (derived from the double SHA-256 checksum), and then converting
> to the Base58 representation. This results in a Base58-encoded string
> of up to 112 characters. Because of the choice of the version bytes,
> the Base58 representation will start with "xprv" or "xpub" on mainnet,
> "tprv" or "tpub" on testnet.
>
> Note that the fingerprint of the parent
> only serves as a fast way to detect parent and child nodes in
> software, and software must be willing to deal with collisions.
> Internally, the full 160-bit identifier could be used.
>
> When importing a serialized extended public key, implementations must
> verify whether the X coordinate in the public key data corresponds to
> a point on the curve. If not, the extended public key is invalid.

Your PHP code must first run the b58check algorithm to verify the xpub is encoded correctly, and then decode it into the above values. Lastly, you must check that the pubkey found by decoding the xpub is a value point on the secp256k1 curve.

> **Comments:**
> **username_0**: Thank you for your quick and very informative reply!  
> **username_3**: Can this also be done in javascript (for input form validation), or are there special PHP functions that enable this?  

---

