AOPP

Authoritative source

Address Ownership Proof Protocol (AOPP)

Mission Statement

The AOPP streamlines and automates address ownership proofs, which are required in interactions between private wallets and Virtual Asset Service Providers (VASPs), for example in virtual asset withdrawal.

Specification

Link on the "Address Ownership Proof" web page of a VASP:

<a href="​aopp:?v=0&msg=vasp-chosen-msg&asset=btc&format=p2xxx&callback=https://vasp.com/proofs/vasp-chosen-token​">verify address</a>

Required parameters in version 0:

  1. v: version number, always 0

  2. msg: a vasp-chosen message up to 1024 ASCII characters; it is recommended to contain a ​nonce​ value

  3. asset: a virtual asset identifier (as defined in ​SLIP-0044​)

  4. format: specifies a wallet address type the VASP expects in a callback;

    1. for "btc" asset it is:

      • p2pkh
      • p2wpkh
      • p2sh
      • p2tr
      • any
    2. for "eth" asset it is:

      • standard
  5. callback: a VASP chosen URL endpoint where the client wallet sends the response to.

When a wallet encounters an unknown version number or other unrecognised or invalid values in required parameters, it should display an error and abort signing. Wallets should ignore parameters not listed above.

On click, a desktop app shows up. The user confirms the message. The app sends a response to the server:

Response:

POST <callback URL>
Content-Type: application/json; utf-8
{
    "version": 0,
    "address": "bc1000000000000000000000000",
    "signature": "​<Bitcoin Signed Message Signature>​"
}

Response from the Server:

  1. HTTP 204: Signature is valid.
  2. HTTP 400: Bad Request.
  3. HTTP 404: The vasp-chosen-token in the callback URL doesn't exist.

Compressed Keys Only

Uncompressed keys are considered legacy and are not supported.

Bitcoin Message Signatures

For bitcoin, the signatures are constructed following the algorithm in bitcoin core. Special attention should be brought to the encoding of the recovery byte that does not indicate information about witness addresses in its encoding. This is the main difference between bitcoin core's message signatures and other, less popular ones.

Please refer to the wallet guide for further implementation hints.

Ethereum Message Signatures

For ethereum, the signatures are constructed following the same algorithm as in bitcoin core with the notable exception that the recovery byte is appended to the signature instead of prepended.

Recommendations

  1. Choose any for the address format if your VASP supports all possible address formats. Certain wallets (e.g. electrum) have a fixed address format and therefore letting them pick the address format will increase interoperability.
  2. Choose a small message to improve UX using hardware wallets (small screens). Also, URIs have an implementation-defined limit so smaller URIs will have better interoperability in general.
  3. [Add SRO approved message style here]

FAQ

  1. Why is there a format specifier?

    A format specifier allows a VASP to hint to a wallet what address format it can accept. Historically, certain VASPs have had poor support for various address formats.

  2. How to deal with p2sh addresses?

    For p2sh addresses we need to presume that it's a p2wpkh address wrapped in a p2sh.

  3. Why is the wallet choosing the address?

    Certain wallet types, such as hardware wallets, are limited in how they can handle specific workflows. To facilitate the adoption in all kinds of wallets, the protocol lets the wallet choose the address.

  4. Why is there a limit on the msg parameter?

    Some wallets have a hard limit on the size of the message, hence the 1024 character limit in AOPP.

Test vectors

Bitcoin

  • p2pkh
    • private key: L4MSJRS7EZNoinjUXJAKrtSgvA6epQDAmwgo5B2LJdVCcjEapPE1
    • address: 13LiZwTMfowMo5KsWHf5TNLmK78WSxVQCG
    • message: hello
    • signature: IFwh9XVPb8vvNUsbuuQU1Xk1jT652JD/6HN3cqnFn/MMBDziPbM8cOi83D29LRGSwMF3ZcjytD7nfNdn5dI0/50=
  • p2sh (wrapped SegWit)
    • private key: L5fETAwYWGRA1eWCHk8AgH2FX2rxLp64winwoAoRGpz1aQMp3Rai
    • address: 3JvVkfeKrrJstF66haNpFepfhxzQuBB78h
    • message: hello
    • signature: H1oYVmDaWxZBPEk2ou4myn1SRC20ycBUPPD5fLS+SmQ1e04Bi1J9mIJ5fNhe3khDhJRUX2fU+VHGKlJdAjYIvBU=
  • p2wpkh
    • private key: L5fETAwYWGRA1eWCHk8AgH2FX2rxLp64winwoAoRGpz1aQMp3Rai
    • address: bc1qnshsvhrfl28g03k0vxdez6vua56r0c72xy9e93
    • message: hello
    • signature: H1oYVmDaWxZBPEk2ou4myn1SRC20ycBUPPD5fLS+SmQ1e04Bi1J9mIJ5fNhe3khDhJRUX2fU+VHGKlJdAjYIvBU=

Ethereum

  • private key: 4142e80a872531fd1055f52ccab713d4c7f1eee28c33415558e74faeb516de2b
  • address: 0x270402aeB8f4dAc8203915fC26F0768feA61b532
  • message: hello
  • signature: vbyudz7PM/tUdVjlL0wEtCnvn3PVYv8eCqCf/aLeVj8JwAsUVuyMMwbIInXAj7EtmZIUwlem7AOH0da8ygXmQBs=