After Width: | Height: | Size: 395 B |
After Width: | Height: | Size: 397 B |
After Width: | Height: | Size: 433 B |
@ -0,0 +1,593 @@ |
|||
Bitcoin application : Common Technical Specifications |
|||
===================================================== |
|||
Ledger Firmware Team <hello@ledger.fr> |
|||
Application version 1.1.9 |
|||
|
|||
== 1.1.9 |
|||
|
|||
- Split specification from common firmware |
|||
- Add display and segwit options to GET WALLET PUBLIC KEY |
|||
|
|||
== About |
|||
|
|||
This specification describes the APDU messages interface to communicate with the Bitcoin |
|||
application. It is based on the HW.1 firmware specification detailed on https://github.com/LedgerHQ/btchip-doc |
|||
|
|||
== Wallet usage APDUs |
|||
|
|||
=== GET WALLET PUBLIC KEY |
|||
|
|||
==== Description |
|||
|
|||
This command returns the public key and Base58 encoded address for the given BIP 32 path. |
|||
|
|||
==== Coding |
|||
|
|||
'Command' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* |
|||
| E0 | 40 | 00 : do not display the address |
|||
|
|||
01 : display the address |
|||
|
|||
| 00 : return a legacy address |
|||
|
|||
01 : return a P2SH-P2WPKH address |
|||
|
|||
02 : return a Bech32 encoded P2WPKH address | variable | variable |
|||
|============================================================================================================================== |
|||
|
|||
'Input data' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Number of BIP 32 derivations to perform (max 10) | 1 |
|||
| First derivation index (big endian) | 4 |
|||
| ... | 4 |
|||
| Last derivation index (big endian) | 4 |
|||
|============================================================================================================================== |
|||
|
|||
'Output data' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Public Key length | 1 |
|||
| Uncompressed Public Key | var |
|||
| Bitcoin address length | 1 |
|||
| Bitcoin address | var |
|||
| BIP32 Chain code | 32 |
|||
|============================================================================================================================== |
|||
|
|||
=== GET TRUSTED INPUT |
|||
|
|||
==== Description |
|||
|
|||
This command is used to extract a Trusted Input (encrypted transaction hash, output index, output amount) from a transaction. |
|||
|
|||
The transaction data to be provided should be encoded using bitcoin standard raw transaction encoding. Scripts can be sent over several APDUs. Other individual transaction elements split over different APDUs will be rejected. 64 bits varints are rejected. |
|||
|
|||
==== Coding |
|||
|
|||
'Command' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* |
|||
| E0 | 42 | 00 : first transaction data block |
|||
|
|||
80 : subsequent transaction data block | 00 | var | var |
|||
|============================================================================================================================== |
|||
|
|||
'Input data (first block)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Input index to lookup (big endian) | 4 |
|||
| Transaction data | var |
|||
|============================================================================================================================== |
|||
|
|||
'Input data (next block)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Transaction data | var |
|||
|============================================================================================================================== |
|||
|
|||
'Output data (non last block)' |
|||
|
|||
None |
|||
|
|||
'Output data (last block)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Trusted Input | 56 |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
=== UNTRUSTED HASH TRANSACTION INPUT START |
|||
|
|||
==== Description |
|||
|
|||
This command is used to compose an opaque SHA-256 hash for a new transaction. |
|||
|
|||
This transaction can be verified by the user on screen |
|||
|
|||
The transaction data to be provided should be encoded using bitcoin standard raw transaction encoded as follows : |
|||
|
|||
- A 1 byte flag is added before each input in the transaction - the following flags are valid |
|||
|
|||
- 0x01 if the input is passed as a Trusted Input, previously computed by the dongle. In this case, each input outpoint is replaced by the Trusted Input length (1 byte) and the Trusted Input data |
|||
|
|||
- 0x00 if the input is passed as a non Trusted Input (passing the original 36 bytes prevout). Non Trusted Inputs will generate a specific warning on screen as fees cannot be computed in that case |
|||
|
|||
- 0x02 if the input is passed as a Segregated Witness Input, defined as the concatenation of the original 36 bytes prevout and the original 8 bytes little endian amount associated to this input. When using this mode, all transaction inputs shall be passed as Segregated Witness Inputs, and the signature mechanism defined for version 0 witness program in BIP 143 (https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki) will be used. |
|||
|
|||
- The input scripts shall be prepared by the host for the transaction signing process as per bitcoin rules : the current input script being signed shall be the previous output script (or the redeeming script when consuming a P2SH output, or the scriptCode when consuming a BIP 143 output), and other input script shall be null. |
|||
- The encoded transaction data shall be provided up to (and not including) the number of outputs. |
|||
- Scripts can be sent over several APDUs. Other individual transaction elements split over different APDUs will be rejected. 64 bits varints are rejected. |
|||
- When using Segregated Witness Inputs, the signing mechanism differs slightly : |
|||
|
|||
* The transaction shall be processed first with all inputs having a null script length (to be done twice if the dongle has been powercycled to retrieve the authorization code) |
|||
* Then each input to sign shall be processed as part of a pseudo transaction with a single input and no outputs. |
|||
|
|||
==== Coding |
|||
|
|||
'Command' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* |
|||
| E0 | 44 | 00 : first transaction data block |
|||
|
|||
80 : subsequent transaction data block | |
|||
|
|||
00 : start signing a new transaction |
|||
|
|||
02 : start signing a new transaction containing Segregated Witness Inputs |
|||
|
|||
80 : continue signing another input of the current transaction | var | var |
|||
|============================================================================================================================== |
|||
|
|||
'Input data' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Transaction data | var |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
'Output data' |
|||
|
|||
None |
|||
|
|||
|
|||
=== UNTRUSTED HASH SIGN |
|||
|
|||
==== Description |
|||
|
|||
This command is used to sign a given secure hash using a private key (after re-hashing it following the standard Bitcoin signing process) to finalize a transaction input signing process. |
|||
|
|||
This command will be rejected if the transaction signing state is not consistent or if a user validation is required and the provided user validation code is not correct. |
|||
|
|||
==== Coding |
|||
|
|||
'Command' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* |
|||
| E0 | 48 | 00 | 00 | var | var |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
'Input data' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Number of BIP 32 derivations to perform (max 10) | 1 |
|||
| First derivation index for the private key to use (big endian) | 4 |
|||
| ... | 4 |
|||
| Last derivation index for the private key to use (big endian) | 4 |
|||
| RFU (0x00) | 1 |
|||
| Lock Time (big endian) | 4 |
|||
| SigHashType | 1 |
|||
|============================================================================================================================== |
|||
|
|||
'Output data' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Signed hash, as ASN-1 encoded R & S components. Mask first byte with 0xFE | var |
|||
| SigHashType | 1 |
|||
|============================================================================================================================== |
|||
|
|||
=== UNTRUSTED HASH TRANSACTION INPUT FINALIZE FULL |
|||
|
|||
==== Description |
|||
|
|||
This command is used to compose an opaque SHA-256 hash for the transaction outputs |
|||
|
|||
This command is rejected if all inputs advertised at the beginning of the transaction have not been processed first. |
|||
|
|||
Only standard output scripts are accepted : |
|||
|
|||
* Pay-to-PubkeyHash (OP_DUP OP_HASH160 [pubKeyHash] OP_EQUALVERIFY OP_CHECKSIG) |
|||
* Pay-to-Script-Hash (OP_HASH160 [script hash] OP_EQUAL) |
|||
* A single maximum 80 bytes OP_RETURN with a null value |
|||
* A P2WPKH (00 [20 bytes]) or P2WSH (00 [30 bytes]) version 0 witness program |
|||
|
|||
==== Coding |
|||
|
|||
'Command' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* |
|||
| E0 | 4A | 00 : more input data to be sent |
|||
|
|||
80 : last input data block to be sent |
|||
|
|||
FF : BIP 32 path specified for the change address |
|||
| 00 | var | var |
|||
|============================================================================================================================== |
|||
|
|||
'Input data (first block, no providing a BIP 32 path)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Start of output data, containing the number of outputs encoded as a Bitcoin varint | var |
|||
|============================================================================================================================== |
|||
|
|||
'Input data (providing a BIP 32 path)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Number of BIP 32 derivations to perform (max 10) | 1 |
|||
| First derivation index for the private key to use (big endian) | 4 |
|||
| ... | 4 |
|||
| Last derivation index for the private key to use (big endian) | 4 |
|||
|============================================================================================================================== |
|||
|
|||
'Input data (optional next blocks)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Output data continued | var |
|||
|============================================================================================================================== |
|||
|
|||
'Output data (providing a BIP 32 path)' |
|||
|
|||
None |
|||
|
|||
|
|||
'Output data (not last block)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| RFU (00) | 1 |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
'Output data (last block)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| RFU (00) | 1 |
|||
| Transaction user validation flag |
|||
|
|||
0x00 : no user validation requested |
|||
| 1 |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
=== SIGN MESSAGE |
|||
|
|||
==== Description |
|||
|
|||
This command is used to sign message using a private key. |
|||
|
|||
The signature is performed as follows : |
|||
|
|||
- The data to sign is the magic "\x18Bitcoin Signed Message:\n" - followed by the length of the message to sign on 1 byte (if requested) followed by the binary content of the message |
|||
- The signature is performed on a double SHA-256 hash of the data to sign using the selected private key |
|||
|
|||
The signature is returned using the standard ASN-1 encoding. To convert it to the proprietary Bitcoin-QT format, the host has to : |
|||
|
|||
- Get the parity of the first byte (sequence) : P |
|||
- Add 27 to P if the public key is not compressed, otherwise add 31 to P |
|||
- Return the Base64 encoded version of P || r || s |
|||
|
|||
If the low end word of one component of the BIP 32 derivation path includes 0xB11D or 0xB11E the message is immediately signed without confirmation (typically used for BitID). |
|||
|
|||
==== Coding |
|||
|
|||
'Command' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* |
|||
| E0 | 4E | 00 : prepare message |
|||
|
|||
80 : sign message| |
|||
|
|||
01 : when preparing, first part of the message |
|||
|
|||
80 : when preparing, next part of the message |
|||
|
|||
| var | var |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
'Input data in prepare mode (first block)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Number of BIP 32 derivations to perform (max 10) | 1 |
|||
| First derivation index of the private key to use (big endian) | 4 |
|||
| ... | 4 |
|||
| Last derivation index of the private key to use (big endian) | 4 |
|||
| Message length (big endian, coded on 1 byte for legacy calls) | 2 |
|||
| Message data | var |
|||
|============================================================================================================================== |
|||
|
|||
'Input data in prepare mode (next blocks)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Message data | var |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
'Input data in sign mode' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| User validation code length (or 00 in server mode) | 1 |
|||
| User validation code | var |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
'Output data in prepare mode (not last block)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| RFU (00) | 1 |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
'Output data in prepare mode (last block)' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| RFU (00) | 1 |
|||
| Transaction user validation flag |
|||
|
|||
0x00 : no user validation requested |
|||
| 1 |
|||
|============================================================================================================================== |
|||
|
|||
|
|||
'Output data in sign mode' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| ASN-1 encoded message signature with Y parity indicated in the first (sequence) byte | variable |
|||
|============================================================================================================================== |
|||
|
|||
== Test and utility APDUs |
|||
|
|||
=== GET RANDOM |
|||
|
|||
==== Description |
|||
|
|||
This command returns random bytes from the dongle hardware random number generator |
|||
|
|||
==== Coding |
|||
|
|||
'Command' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* |
|||
| E0 | C0 | 00 | 00 | 00 | variable |
|||
|============================================================================================================================== |
|||
|
|||
'Input data' |
|||
|
|||
None |
|||
|
|||
'Output data' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Random bytes | variable |
|||
|============================================================================================================================== |
|||
|
|||
'Availability' |
|||
|
|||
This function is always available. |
|||
|
|||
|
|||
=== GET FIRMWARE VERSION |
|||
|
|||
==== Description |
|||
|
|||
This command returns the firmware version of the dongle and additional features supported |
|||
|
|||
==== Coding |
|||
|
|||
'Command' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* |
|||
| E0 | C4 | 00 | 00 | 00 | 07 |
|||
|============================================================================================================================== |
|||
|
|||
'Input data' |
|||
|
|||
None |
|||
|
|||
'Output data' |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Features flag |
|||
|
|||
0x01 : public keys are compressed (otherwise not compressed) |
|||
|
|||
0x02 : implementation running with screen + buttons handled by the Secure Element |
|||
|
|||
0x04 : implementation running with screen + buttons handled externally |
|||
|
|||
0x08 : NFC transport and payment extensions supported |
|||
|
|||
0x10 : BLE transport and low power extensions supported |
|||
|
|||
0x20 : implementation running on a Trusted Execution Environment |
|||
|
|||
| 01 |
|||
|
|||
| Architecture | 01 |
|||
| Firmware major version | 01 |
|||
| Firmware minor version | 01 |
|||
| Firmware patch version | 01 |
|||
| Loader ID major version (if applicable) | 01 |
|||
| Loader ID minor version (if applicable) | 01 |
|||
|============================================================================================================================== |
|||
|
|||
'Availability' |
|||
|
|||
This function is always available. |
|||
|
|||
== Transport protocol |
|||
|
|||
=== General transport description |
|||
|
|||
Ledger APDUs requests and responses are encapsulated using a flexible protocol allowing to fragment large payloads over different underlying transport mechanisms. |
|||
|
|||
The common transport header is defined as follows : |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Communication channel ID (big endian) | 2 |
|||
| Command tag | 1 |
|||
| Packet sequence index (big endian) | 2 |
|||
| Payload | var |
|||
|============================================================================================================================== |
|||
|
|||
The Communication channel ID allows commands multiplexing over the same physical link. It is not used for the time being, and should be set to 0101 to avoid compatibility issues with implementations ignoring a leading 00 byte. |
|||
|
|||
The Command tag describes the message content. Use TAG_APDU (0x05) for standard APDU payloads, or TAG_PING (0x02) for a simple link test. |
|||
|
|||
The Packet sequence index describes the current sequence for fragmented payloads. The first fragment index is 0x00. |
|||
|
|||
=== APDU Command payload encoding |
|||
|
|||
APDU Command payloads are encoded as follows : |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| APDU length (big endian) | 2 |
|||
| APDU CLA | 1 |
|||
| APDU INS | 1 |
|||
| APDU P1 | 1 |
|||
| APDU P2 | 1 |
|||
| APDU length | 1 |
|||
| Optional APDU data | var |
|||
|============================================================================================================================== |
|||
|
|||
APDU payload is encoded according to the APDU case |
|||
|
|||
[width="80%"] |
|||
|======================================================================================= |
|||
| Case Number | *Lc* | *Le* | Case description |
|||
| 1 | 0 | 0 | No data in either direction - L is set to 00 |
|||
| 2 | 0 | !0 | Input Data present, no Output Data - L is set to Lc |
|||
| 3 | !0 | 0 | Output Data present, no Input Data - L is set to Le |
|||
| 4 | !0 | !0 | Both Input and Output Data are present - L is set to Lc |
|||
|======================================================================================= |
|||
|
|||
=== APDU Response payload encoding |
|||
|
|||
APDU Response payloads are encoded as follows : |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| APDU response length (big endian) | 2 |
|||
| APDU response data and Status Word | var |
|||
|============================================================================================================================== |
|||
|
|||
=== USB mapping |
|||
|
|||
Messages are exchanged with the dongle over HID endpoints over interrupt transfers, with each chunk being 64 bytes long. The HID Report ID is ignored. |
|||
|
|||
== Status Words |
|||
|
|||
The following standard Status Words are returned for all APDUs - some specific Status Words can be used for specific commands and are mentioned in the command description. |
|||
|
|||
'Status Words' |
|||
|
|||
[width="80%"] |
|||
|=============================================================================================== |
|||
| *SW* | *Description* |
|||
| 6700 | Incorrect length |
|||
| 6982 | Security status not satisfied (Bitcoin dongle is locked or invalid access rights) |
|||
| 6A80 | Invalid data |
|||
| 6A82 | File not found |
|||
| 6B00 | Incorrect parameter P1 or P2 |
|||
| 6Fxx | Technical problem (Internal error, please report) |
|||
| 9000 | Normal ending of the command |
|||
|================================================================================================ |
|||
|
|||
== Data structures |
|||
|
|||
The format of the data structures is provided for interoperability and validation purposes. A typical user will not need to manipulate them directly. |
|||
|
|||
=== Encoded trusted input |
|||
|
|||
An encoded trusted input is stored internally as follow. The signature is the last block of a Triple DES CBC encryption of the previous data by the trusted input encryption key. |
|||
|
|||
[width="80%"] |
|||
|============================================================================================================================== |
|||
| *Description* | *Length* |
|||
| Magic version (*32*) | 1 |
|||
| Flags |
|||
|
|||
RFU |
|||
|
|||
| 1 |
|||
| Nonce | 2 |
|||
| Associated transaction hash | 32 |
|||
| Index in associated transaction (little endian) | 4 |
|||
| Associated amount (little endian) | 8 |
|||
| Signature | 8 |
|||
|============================================================================================================================== |
|||
|
After Width: | Height: | Size: 344 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 362 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,208 @@ |
|||
/* Copyright (c) 2017 Pieter Wuille
|
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
|
|||
#ifdef NATIVE_SEGWIT_PREFIX |
|||
|
|||
#include <stdlib.h> |
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
|
|||
#include "segwit_addr.h" |
|||
|
|||
uint32_t bech32_polymod_step(uint32_t pre) { |
|||
uint8_t b = pre >> 25; |
|||
return ((pre & 0x1FFFFFF) << 5) ^ (-((b >> 0) & 1) & 0x3b6a57b2UL) ^ |
|||
(-((b >> 1) & 1) & 0x26508e6dUL) ^ (-((b >> 2) & 1) & 0x1ea119faUL) ^ |
|||
(-((b >> 3) & 1) & 0x3d4233ddUL) ^ (-((b >> 4) & 1) & 0x2a1462b3UL); |
|||
} |
|||
|
|||
static const char *charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; |
|||
|
|||
static const int8_t charset_rev[128] = { |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 10, 17, 21, 20, 26, 30, 7, |
|||
5, -1, -1, -1, -1, -1, -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, |
|||
31, 27, 19, -1, 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, |
|||
-1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0, |
|||
3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1}; |
|||
|
|||
int bech32_encode(char *output, const char *hrp, const uint8_t *data, |
|||
size_t data_len) { |
|||
uint32_t chk = 1; |
|||
size_t i = 0; |
|||
while (hrp[i] != 0) { |
|||
if (hrp[i] >= 'A' && hrp[i] <= 'Z') |
|||
return 0; |
|||
if (!(hrp[i] >> 5)) |
|||
return 0; |
|||
chk = bech32_polymod_step(chk) ^ (hrp[i] >> 5); |
|||
++i; |
|||
} |
|||
if (i + 7 + data_len > 90) |
|||
return 0; |
|||
chk = bech32_polymod_step(chk); |
|||
while (*hrp != 0) { |
|||
chk = bech32_polymod_step(chk) ^ (*hrp & 0x1f); |
|||
*(output++) = *(hrp++); |
|||
} |
|||
*(output++) = '1'; |
|||
for (i = 0; i < data_len; ++i) { |
|||
if (*data >> 5) |
|||
return 0; |
|||
chk = bech32_polymod_step(chk) ^ (*data); |
|||
*(output++) = charset[*(data++)]; |
|||
} |
|||
for (i = 0; i < 6; ++i) { |
|||
chk = bech32_polymod_step(chk); |
|||
} |
|||
chk ^= 1; |
|||
for (i = 0; i < 6; ++i) { |
|||
*(output++) = charset[(chk >> ((5 - i) * 5)) & 0x1f]; |
|||
} |
|||
*output = 0; |
|||
return 1; |
|||
} |
|||
|
|||
int bech32_decode(char *hrp, uint8_t *data, size_t *data_len, |
|||
const char *input) { |
|||
uint32_t chk = 1; |
|||
size_t i; |
|||
size_t input_len = strlen(input); |
|||
size_t hrp_len; |
|||
int have_lower = 0, have_upper = 0; |
|||
if (input_len < 8 || input_len > 90) { |
|||
return 0; |
|||
} |
|||
*data_len = 0; |
|||
while (*data_len < input_len && input[(input_len - 1) - *data_len] != '1') { |
|||
++(*data_len); |
|||
} |
|||
hrp_len = input_len - (1 + *data_len); |
|||
if (hrp_len < 1 || *data_len < 6) { |
|||
return 0; |
|||
} |
|||
*(data_len) -= 6; |
|||
for (i = 0; i < hrp_len; ++i) { |
|||
int ch = input[i]; |
|||
if (ch < 33 || ch > 126) { |
|||
return 0; |
|||
} |
|||
if (ch >= 'a' && ch <= 'z') { |
|||
have_lower = 1; |
|||
} else if (ch >= 'A' && ch <= 'Z') { |
|||
have_upper = 1; |
|||
ch = (ch - 'A') + 'a'; |
|||
} |
|||
hrp[i] = ch; |
|||
chk = bech32_polymod_step(chk) ^ (ch >> 5); |
|||
} |
|||
hrp[i] = 0; |
|||
chk = bech32_polymod_step(chk); |
|||
for (i = 0; i < hrp_len; ++i) { |
|||
chk = bech32_polymod_step(chk) ^ (input[i] & 0x1f); |
|||
} |
|||
++i; |
|||
while (i < input_len) { |
|||
int v = (input[i] & 0x80) ? -1 : charset_rev[(int)input[i]]; |
|||
if (input[i] >= 'a' && input[i] <= 'z') |
|||
have_lower = 1; |
|||
if (input[i] >= 'A' && input[i] <= 'Z') |
|||
have_upper = 1; |
|||
if (v == -1) { |
|||
return 0; |
|||
} |
|||
chk = bech32_polymod_step(chk) ^ v; |
|||
if (i + 6 < input_len) { |
|||
data[i - (1 + hrp_len)] = v; |
|||
} |
|||
++i; |
|||
} |
|||
if (have_lower && have_upper) { |
|||
return 0; |
|||
} |
|||
return chk == 1; |
|||
} |
|||
|
|||
static int convert_bits(uint8_t *out, size_t *outlen, int outbits, |
|||
const uint8_t *in, size_t inlen, int inbits, int pad) { |
|||
uint32_t val = 0; |
|||
int bits = 0; |
|||
uint32_t maxv = (((uint32_t)1) << outbits) - 1; |
|||
while (inlen--) { |
|||
val = (val << inbits) | *(in++); |
|||
bits += inbits; |
|||
while (bits >= outbits) { |
|||
bits -= outbits; |
|||
out[(*outlen)++] = (val >> bits) & maxv; |
|||
} |
|||
} |
|||
if (pad) { |
|||
if (bits) { |
|||
out[(*outlen)++] = (val << (outbits - bits)) & maxv; |
|||
} |
|||
} else if (((val << (outbits - bits)) & maxv) || bits >= inbits) { |
|||
return 0; |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
int segwit_addr_encode(char *output, const char *hrp, int witver, |
|||
const uint8_t *witprog, size_t witprog_len) { |
|||
uint8_t data[65]; |
|||
size_t datalen = 0; |
|||
if (witver > 16) |
|||
return 0; |
|||
if (witver == 0 && witprog_len != 20 && witprog_len != 32) |
|||
return 0; |
|||
if (witprog_len < 2 || witprog_len > 40) |
|||
return 0; |
|||
data[0] = witver; |
|||
convert_bits(data + 1, &datalen, 5, witprog, witprog_len, 8, 1); |
|||
++datalen; |
|||
return bech32_encode(output, hrp, data, datalen); |
|||
} |
|||
|
|||
int segwit_addr_decode(int *witver, uint8_t *witdata, size_t *witdata_len, |
|||
const char *hrp, const char *addr) { |
|||
uint8_t data[84]; |
|||
char hrp_actual[84]; |
|||
size_t data_len; |
|||
if (!bech32_decode(hrp_actual, data, &data_len, addr)) |
|||
return 0; |
|||
if (data_len == 0 || data_len > 65) |
|||
return 0; |
|||
if (strncmp(hrp, hrp_actual, 84) != 0) |
|||
return 0; |
|||
if (data[0] > 16) |
|||
return 0; |
|||
*witdata_len = 0; |
|||
if (!convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) |
|||
return 0; |
|||
if (*witdata_len < 2 || *witdata_len > 40) |
|||
return 0; |
|||
if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) |
|||
return 0; |
|||
*witver = data[0]; |
|||
return 1; |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,84 @@ |
|||
/* Copyright (c) 2017 Pieter Wuille
|
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
|
|||
#ifndef _SEGWIT_ADDR_H_ |
|||
#define _SEGWIT_ADDR_H_ 1 |
|||
|
|||
#include <stdint.h> |
|||
|
|||
/** Encode a SegWit address
|
|||
* |
|||
* Out: output: Pointer to a buffer of size 73 + strlen(hrp) that will be |
|||
* updated to contain the null-terminated address. |
|||
* In: hrp: Pointer to the null-terminated human readable part to use |
|||
* (chain/network specific). |
|||
* ver: Version of the witness program (between 0 and 16 inclusive). |
|||
* prog: Data bytes for the witness program (between 2 and 40 bytes). |
|||
* prog_len: Number of data bytes in prog. |
|||
* Returns 1 if successful. |
|||
*/ |
|||
int segwit_addr_encode(char *output, const char *hrp, int ver, |
|||
const uint8_t *prog, size_t prog_len); |
|||
|
|||
/** Decode a SegWit address
|
|||
* |
|||
* Out: ver: Pointer to an int that will be updated to contain the witness |
|||
* program version (between 0 and 16 inclusive). |
|||
* prog: Pointer to a buffer of size 40 that will be updated to |
|||
* contain the witness program bytes. |
|||
* prog_len: Pointer to a size_t that will be updated to contain the |
|||
* length |
|||
* of bytes in prog. |
|||
* hrp: Pointer to the null-terminated human readable part that is |
|||
* expected (chain/network specific). |
|||
* addr: Pointer to the null-terminated address. |
|||
* Returns 1 if successful. |
|||
*/ |
|||
int segwit_addr_decode(int *ver, uint8_t *prog, size_t *prog_len, |
|||
const char *hrp, const char *addr); |
|||
|
|||
/** Encode a Bech32 string
|
|||
* |
|||
* Out: output: Pointer to a buffer of size strlen(hrp) + data_len + 8 that |
|||
* will be updated to contain the null-terminated Bech32 string. |
|||
* In: hrp : Pointer to the null-terminated human readable part. |
|||
* data : Pointer to an array of 5-bit values. |
|||
* data_len: Length of the data array. |
|||
* Returns 1 if successful. |
|||
*/ |
|||
int bech32_encode(char *output, const char *hrp, const uint8_t *data, |
|||
size_t data_len); |
|||
|
|||
/** Decode a Bech32 string
|
|||
* |
|||
* Out: hrp: Pointer to a buffer of size strlen(input) - 6. Will be |
|||
* updated to contain the null-terminated human readable part. |
|||
* data: Pointer to a buffer of size strlen(input) - 8 that will |
|||
* hold the encoded 5-bit data values. |
|||
* data_len: Pointer to a size_t that will be updated to be the number |
|||
* of entries in data. |
|||
* In: input: Pointer to a null-terminated Bech32 string. |
|||
* Returns 1 if succesful. |
|||
*/ |
|||
int bech32_decode(char *hrp, uint8_t *data, size_t *data_len, |
|||
const char *input); |
|||
|
|||
#endif |