KaChing APDU Transaction Protocol Explained
The reader of this article is expected to have a fairly good knowledge about bitcoin at a technical level.
Protocol specification: http://kaching.cards/katp.pdf
The KaChing APDU Transaction Protocol (KATP) is a protocol allowing two entities to perform peer-to-peer bitcoin transactions. It’s primarily designed for local communication, where the wallet and terminal are physically close.
During a transaction session one peer acts as the terminal while the other acts as the wallet. Some devices such as an app on a smartphone will have the ability to act both as terminal and wallet.
Both the terminal and wallet are able to add as many inputs and outputs to the transaction as they wish. This allows both the wallet and terminal to consolidate their UTXOs as part of normal use.
Metadata may be added in the form of OP_RETURN outputs by both terminal and wallet.
The terminal is the host of the communication session. It is responsible for determining the correct fee and publishing the completed transaction to the blockchain.
The wallet is responsible for keeping track of it’s own UTXOs. A wallet doesn’t need any internet connectivity. Such a wallet can only receive (and spend) funds when communicating with a terminal.
Card pairing and management protocol
KATP defines only the public protocol of a KaChing wallet implemented in a smart card. A smartcard wallet will also need to support some protocol for managing the card, such initializing the master key, setting PIN and spend limits. Since that protocol typically will only be used between the card holder and their own phone, standardizing that protocol is of less concern.
KATP doesn’t dictate any specific physical communication protocol. Any protocol that allows for the transmission of APDU packets can be used. For interoperability contactless communication using ISO/IEC 14443 A/B is recommended.
NFC: Near-field communication
NFC is a set of protocols managed by the NFC Forum for contactless communication. KaChing APDU Transaction Protocol is not built on top of the NFC protocols, but a contactless wallet will make use of the same underlying protocols such as APDU and ISO/IEC 14443. A smart card implementing KATP might also implement an NFC tag to enhance the user experience.
Android devices can be programmed to both operate as a KaChing terminal and as a wallet. An Android device with NFC support can communicate with wallets supporting ISO/IEC 14443 A or B. The communication is done using the IsoDep interface. This interface allows the transmission of APDU packages directly bypassing the NFC higher level protocols.
In order to implement a wallet, host-based card emulation is used.
The KaChing protocol can be used for phone to phone payments. This requires one of the phones to act as the terminal and the other to act as the wallet. The phone acting as terminal must have internet connection.
As of today, third party apps are not given sufficient access to the built-in NFC of iOS devices required to implement the KaChing protocol. In order to implement a KaChing terminal on an iOS device, external hardware is required.
The APDU protocol is specified in ISO/IEC 7816-4. KaChing APDU Transaction Protocol uses only a subset of this protocol. Communication is performed in command-response pairs. The command APDU is sent by the terminal. The wallet sends a response APDU back.
Note that in order to parse APDUs the length must be known.
The CLA bytes must always be ‘80’. Logical channels, command chaining and secure messaging are not used.
The parameter bytes P1-P2 must always be ‘00’.
Nc is a number denoting the length of the data field in the command APDU. It is encoded in the command APDU as the field Lc.
Ne is a number denoting the expected maximum length of the data field in the response APDU. It is encoded in the command APDU as the field Le.
When the value of both Nc and Ne is equal to or less than 255, the encoding is simple. If the value is zero, the corresponding field is omitted in the command APDU. Any other value is encoded as a single byte.
It’s highly recommended to keep the value of Nc and Ne within the range 0-255. The encoding of extended length is a bit complicated and support is still missing in some libraries and smart cards.
The response APDU consist of up to Ne bytes data followed by two status bytes denoted SW1-SW2. Status bytes ‘9000’ indicates success.
KATP puts no limits on the size of transactions, the number of inputs and outputs nor the size of each input and output.
In practice there will be limits. It can be expected that wallets implemented as smart cards can handle transactions of at least 2000 bytes.
Before the transaction session can start the terminal must wait for:
- Transfer amount
- The wallet to be presented to the terminal
For best user experience a terminal should be prepared for these events to happen in any order.
The session is successfully completed with the transaction being committed to the wallet and published to the blockchain. The wallet must be programmed to be fail safe in case of aborted sessions.
The wallet doesn’t have to be aware of any dust limit policy in output amounts. If the wallet produces an output with value below dust limit, the terminal can resolve this either by retrying the transaction session with a slightly different transfer amount or by removing the problematic output. A wallet that has been programmed to be aware of current dust limits, might refuse to sign the transaction if it’s output has been modified by the terminal.
There is no support for retrying individual commands in the protocol.
0 Select KaChing
Before sending any of the KATP commands the terminal should issue the SELECT command as defined in ISO/IEC 7816-4. This command has many options. In order to reduce the burden on wallet implementers it is highly recommended to only use the following options:
- CLA = ‘00’
- INS = ‘A4’
- P1 = ‘04’
- P2 = ‘00’
- Lc = ‘0A’
- Command data = ’A0000008194B43E282BF’
- Le = omitted (Ne = 0, no response expected)
The command data is the international AID for KATP. It consist of a two parts
- International RID = ’A000000819’
- PIX = ‘4B43E282BF’
Usage of this AID is subject to the conditions found in the standard document. The RID is assigned to Bitcoin.no AS by ISO.
1 Get Transaction Template from Wallet
The transaction template is in bitcoin format including version number and nLockTime.
Transfer amount examples
Payment of 1000 satoshis including any transaction fees. Transfer amount is 1000.
Payment of 1000 satoshis excluding any transaction fees. Transfer amount is 1000 + estimated fee.
Request to send 1000 satoshis to wallet. Transaction fee is paid by the sender. Transfer amount is -1000.
Request to send 1000 satoshis to wallet. Transaction fee is paid by the receiver. Transfer amount is -(1000 - estimated fee).
Fee estimation must be done by the terminal before any transaction data is received from the wallet. If the estimate is way off, the terminal can either try to adjust the amount in some of the outputs or retry the session with a better estimate.
PIN is optional. Some cards might require PIN only after a certain amount has been spent. When one of the PIN required status bytes is returned, the terminal must prompt the user for the PIN and retry the session. The PIN code can be any Unicode string, but a terminal will typically only allow entry of the digits 0-9.
When using contactless cards, the card holder might have to tap the card twice. Once to get prompted for the PIN entry and once more to complete the transaction.
If the transaction template returned from the wallet doesn’t fit into a single response, it will be split into chunks. The terminal retrieves more data by reissuing the command with empty command data. The terminal must support basic transaction parsing in order to determine if the complete transaction has been received.
2 Get Public Meta-Key from Wallet
One intended usage of the public meta-key is for the terminal to embed a receipt into the transaction. The receipt is encrypted using the public meta-key and embedded in an OP_RETURN out of the transaction. If a receipt is too big to fit into the current transaction, an encrypted link can be embedded instead, e.g. using b:// or c:// protocols.
The rationale for this is to allow the user of a smart card, with limited storage, to get a receipt for all purchases. The card holder has paired the card with an app on their smartphone. The app watches the blockchain for transactions signed by the card. The app also has the master key used by the card to derive the public meta-keys. This allows the app to show the purchase including receipt immediately after the card has been used.
3 Write Transaction to Wallet
The terminal completes the transaction by adding its own inputs and outputs to the template retrieved from the wallet. The terminal is encouraged to shuffle the order of inputs and outputs to enhance privacy.
4 Get Signatures from Wallet
The terminal might have modified the outputs of the transaction template returned by the wallet. Any spend limit checks must be redone, potentially triggering PIN requirement at this stage.
5 Get Transaction Hash from Wallet
At this stage both the terminal and wallet has a copy of the complete transaction. The terminal should compare the hash calculated by the wallet with its own.
A wallet implemented in a smart card should do any time consuming housekeeping at this stage.
6 Commit Transaction to Wallet
The commit step is the only command where communication failure can result in the wallet becoming out of sync with the blockchain.
When processing the commit command, the wallet must do as little processing as possible. In practice this means that the next wallet state must be fully prepared and saved into persisted memory during the processing of the previous command. The terminal must never issue the commit command more than once. Adding checks in the wallet to protect against a misbehaving terminal is likely to be counterproductive. It adds complexity to the wallet, with more things that can go wrong.
Only the terminal should publish the transaction. If the terminal doesn’t receive a successful response from the wallet it assumes the transaction failed. No payment has been made, the customer will not receive any goods or services.
In the worst case the wallet can end up with some transaction in its UTXO set that’s never been published to the blockchain. An online wallet can resolve this by timing out the missing transaction. How fast the transaction is timed out should depend on how confident the wallet is that the transaction hasn’t been published. A highly confident wallet can time out the transaction within a few seconds.