diff --git a/README.md b/README.md index 5c174ec..c50ee6d 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ throughout the process. ## Integration The following blockchains are supported: -* Bitcoin +* [Bitcoin](./docs/bitcoin.md) * Ethereum * EOS * Tron diff --git a/docs/bitcoin.md b/docs/bitcoin.md new file mode 100644 index 0000000..00e06b1 --- /dev/null +++ b/docs/bitcoin.md @@ -0,0 +1,134 @@ +# [Bitcoin Lock](../README.md) + +Here, we will be conducting comparative testing using [Bitcoin Core](https://bitcoincore.org) (Version 25.0), an official wallet. +For a more in-depth look at the specific implementations of Bitcoin, you can refer to the [source code](https://github.com/bitcoin/bitcoin). + +**Please note:** that we will be using `legacy addresses`. This choice is due to the fact that the current version (25.0) of Bitcoin Core defaults to `segwit addresses`, which are not supported by `signmessage` and `verifymessage`. For further details on this matter, you can check the [Github Issues](https://github.com/bitcoin/bitcoin/issues/10542). + + +## Quick Start + +### Install Bitcoin Core + +Download the binary archive from [here](https://bitcoincore.org/bin/bitcoin-core-25.0/), choose the file corresponding to your platform, and unarchive it. (Note: If you are using MacOS, we recommend downloading the `.tar.gz` file, `.dmg` file only provides GUI tools.) + +Once you have completed these steps, you can start the background program: `bitcoind`. The signature and verify we need to do later need to rely on this service to process. +```shell +bitcoind +``` + +Normally, we will only be using `signature` and `verify` here, without involving on-chain data. Therefore, you can consider disabling network transmission in the configuration file. +Instructions on how to configure it will be provided in the following section. + + +### Create Wallet and Address + +To create a test wallet and receiving address, use the following commands: +```shell +bitcoin-cli createwallet "Test" +bitcoin-cli getnewaddress label1 legacy +``` +**Note:** Ensure that the address_type is specified as `legacy` here, as failure may occur in subsequent signature processes otherwise. + +Output address: +``` +1CSbWFszmuQiPCRPsaDhhb2NuFTEZFQqih +``` + +### Generate Signature + +First, you need to generate a 32-byte data segment as message: +```shell +message=0011223344556677889900112233445500112233445566778899001122334455 +``` + +Next, use the `bitcoin-cli` for signing: +```shell +bitcoin-cli -rpcwallet=Test signmessage 1CSbWFszmuQiPCRPsaDhhb2NuFTEZFQqih $message +``` +If the wallet has set a password before, you need to use `walletpassphrase` to unlock it first. + +Once the signing is successful, it will output the signature result, which is encoded in base64: +``` +H0v6+IkWf0WL6MDCz0K6XeTiNSChoiDIEzgJQMadJi78NoHE3roRx8QX1mnK57on5w5doBXOFBn1kwpOpPgVwPM= +``` + +### Verify + +Here you can directly pass the address, signature and message to ckb-auth-cli to verify: +```shell +ckb-auth-cli bitcoin verify -a 1CSbWFszmuQiPCRPsaDhhb2NuFTEZFQqih -s H0v6+IkWf0WL6MDCz0K6XeTiNSChoiDIEzgJQMadJi78NoHE3roRx8QX1mnK57on5w5doBXOFBn1kwpOpPgVwPM= -m 0011223344556677889900112233445500112233445566778899001122334455 +``` + + +## Details of Bitcoin + +### Cofing Bitcoin Core + +If you wish to perform testing using a GUI or disable network activity, please refer to the configuration instructions below. +[Help](https://jlopp.github.io/bitcoin-core-config-generator/) + +The configuration file for Bitcoin Core (`bitcoin.conf`) is located in different directories based on the platform: +- Linux: `~/.bitcoin/bitcoin.conf` +- Windows: `%UserProfile%\AppData\Roaming\Bitcoin\bitcoin.conf` +- MacOS: `$HOME/Library/Application Support/Bitcoin/bitcoin.conf` + +If you are using it for the first time, you will need to manually create these directories and files. If you want to specify a custom directory, you can also check the `bitcoind` or `bitcoin-qt` help. + +Disabling network activity is mainly done to reduce disk usage: + +```text +networkactive=0 +``` + +Configuring the default address type is necessary because Bitcoin's sign message does not support `segwit addresses`, and the GUI does not provide an option to choose during address creation. Therefore, it needs to be configured here: + +``` +addresstype=legacy +``` + +Note: The command line requires starting `bitcoind` as a background process, while the GUI (bitcoin-qt) also starts a background service. Running both simultaneously can lead to conflicts (listening port), but they share the same default configuration file. + +### Create Address + +As mentioned earlier, creating addresses via the command line won't be detailed here. + +To create addresses in the GUI: + +- Create a wallet: `File` -> `Create Wallet`. +- Generate a receiving address: In the `Receive` tab, click the "Create new receiving address" button. +- After creation, you will see the `Address` in the lower part of a separate window. You can check the addresses held by the current wallet in the table below. + +If the address starts with `bc` or `tb`, make sure to verify the correctness of the above configurations. + +The returned address is encoded in base58, with a decoded length greater than 21 bytes. Among these, the first 20 bytes represent the public key hash value, which will be used for verification later. + +### Signature + +To sign a message in the GUI: + +- `File` -> `Sign Message`, and enter the corresponding values for signing. + +In ckb-auth, the message uses a fixed 32 bytes, but it internally converts the message to hexadecimal with a length of 64 bytes. Therefore, ensure that the message remains 32 bytes when generating it. If the data to be signed is too long, consider hashing it. For signing in Bitcoin, you can directly use this string. + +Please note: When signing in Bitcoin, case sensitivity should be observed. Ckb-auth uses lowercase letters exclusively. + +The returned signature data is encoded in base64, with a fixed binary length of 65 bytes. In this case, no special handling is required. After decoding, you can directly pass it to ckb-auth. + +### Verify + +Before using `ckb-auth-cli verify`, consider verifying in Bitcoin Core first to prevent discrepancies: + +Command line: + +```shell +bitcoin-cli verifymessage 1CSbWFszmuQiPCRPsaDhhb2NuFTEZFQqih H0v6+IkWf0WL6MDCz0K6XeTiNSChoiDIEzgJQMadJi78NoHE3roRx8QX1mnK57on5w5doBXOFBn1kwpOpPgVwPM= 0011223344556677889900112233445500112233445566778899001122334455 +``` + +If verification is successful, it will output `true`. + +In the GUI: + +- `File` -> `Verify Message`, and enter the corresponding data. + +In ckb-auth-cli, base58 decoding is performed on the address, with the first 20 bytes used as the public key hash. The message is decoded to 32 bytes, and the signature is base64 decoded. After passing these data to ckb-auth, the verification process is similar to that in Bitcoin Core, and further details will not be reiterated here. diff --git a/tests/auth_rust/Cargo.lock b/tests/auth_rust/Cargo.lock index 10bb638..913ed35 100644 --- a/tests/auth_rust/Cargo.lock +++ b/tests/auth_rust/Cargo.lock @@ -887,6 +887,7 @@ dependencies = [ "dyn-clone", "hex", "hex-literal 0.4.1", + "lazy_static", "log", "mbedtls", "monero", diff --git a/tests/auth_rust/Cargo.toml b/tests/auth_rust/Cargo.toml index 5c509af..f741503 100644 --- a/tests/auth_rust/Cargo.toml +++ b/tests/auth_rust/Cargo.toml @@ -45,6 +45,7 @@ solana-cli-output = { version = "1.16.1", default-features = false } serde_json = "1.0.99" ripple-keypairs = "0.1.0" p256 = { version = "^0.10.1" } +lazy_static = "1.3.0" [[bin]] name = "ckb-auth-cli" diff --git a/tests/auth_rust/src/lib.rs b/tests/auth_rust/src/lib.rs index e477305..405cbc9 100644 --- a/tests/auth_rust/src/lib.rs +++ b/tests/auth_rust/src/lib.rs @@ -25,7 +25,7 @@ use serde::{Deserialize, Serialize}; use sha3::{Digest, Keccak256}; use std::{collections::HashMap, mem::size_of, process::Stdio, result, vec}; -use crate::auth_program::{ALWAYS_SUCCESS, AUTH_DEMO, SECP256K1_DATA_BIN}; +use lazy_static::lazy_static; use std::{ process::{Child, Command}, sync::Arc, @@ -41,19 +41,22 @@ pub const SOLANA_MAXIMUM_UNWRAPPED_SIGNATURE_SIZE: usize = 510; pub const SOLANA_MAXIMUM_WRAPPED_SIGNATURE_SIZE: usize = SOLANA_MAXIMUM_UNWRAPPED_SIGNATURE_SIZE + 2; +lazy_static! { + pub static ref ORIGINAL_AUTH_PROGRAM: Bytes = + Bytes::from(&include_bytes!("../../../build/auth")[..]); + pub static ref LIBECC_AUTH_PROGRAM: Bytes = + Bytes::from(&include_bytes!("../../../build/auth_libecc")[..]); + pub static ref AUTH_DEMO: Bytes = Bytes::from(&include_bytes!("../../../build/auth_demo")[..]); + pub static ref SECP256K1_DATA_BIN: Bytes = + Bytes::from(&include_bytes!("../../../build/secp256k1_data_20210801")[..]); + pub static ref ALWAYS_SUCCESS: Bytes = + Bytes::from(&include_bytes!("../../../build/always_success")[..]); +} + pub mod auth_program { use ckb_types::bytes::Bytes; - use once_cell::sync::Lazy; use ref_thread_local::ref_thread_local; use ref_thread_local::RefThreadLocal; - use std::path::Path; - - pub static ORIGINAL_AUTH_PROGRAM: Lazy = Lazy::new(|| get_data("../../build/auth")); - pub static LIBECC_AUTH_PROGRAM: Lazy = Lazy::new(|| get_data("../../build/auth_libecc")); - pub static AUTH_DEMO: Lazy = Lazy::new(|| get_data("../../build/auth_demo")); - pub static SECP256K1_DATA_BIN: Lazy = - Lazy::new(|| get_data("../../build/secp256k1_data_20210801")); - pub static ALWAYS_SUCCESS: Lazy = Lazy::new(|| get_data("../../build/always_success")); #[derive(Clone, Copy, Debug)] pub enum AuthProgramType { @@ -65,18 +68,10 @@ pub mod auth_program { static managed PROGRAM_TO_USE: AuthProgramType = AuthProgramType::Original; } - fn get_data(path: &str) -> Bytes { - let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let path = Path::new(dir.as_str()).join(path); - let data = std::fs::read(&path) - .unwrap_or_else(|_err| panic!("failed to load program: {}", path.display())); - Bytes::from(data) - } - pub fn get_auth_program() -> &'static Bytes { match *PROGRAM_TO_USE.borrow() { - AuthProgramType::Original => &ORIGINAL_AUTH_PROGRAM, - AuthProgramType::Libecc => &LIBECC_AUTH_PROGRAM, + AuthProgramType::Original => &crate::ORIGINAL_AUTH_PROGRAM, + AuthProgramType::Libecc => &crate::LIBECC_AUTH_PROGRAM, } } @@ -611,7 +606,8 @@ pub fn do_gen_args(config: &TestConfig, pub_key_hash: Option>) -> Bytes .copy_from_slice(&incorrect_pubkey.as_slice()[0..20]); } - let sighash_all_cell_data_hash = CellOutput::calc_data_hash(&auth_program::get_auth_program()); + let sighash_all_cell_data_hash: Byte32 = + CellOutput::calc_data_hash(&auth_program::get_auth_program()); entry_type .code_hash .copy_from_slice(sighash_all_cell_data_hash.as_slice()); diff --git a/tools/ckb-auth-cli/Cargo.lock b/tools/ckb-auth-cli/Cargo.lock index 42666f8..19b3c9d 100644 --- a/tools/ckb-auth-cli/Cargo.lock +++ b/tools/ckb-auth-cli/Cargo.lock @@ -397,6 +397,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base58-monero" version = "1.0.0" @@ -419,6 +425,12 @@ version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bech32" version = "0.9.1" @@ -900,7 +912,10 @@ dependencies = [ "log", "mbedtls", "monero", + "once_cell", + "p256", "rand 0.6.5", + "ref_thread_local", "ripple-keypairs", "secp256k1 0.22.2", "serde", @@ -1355,6 +1370,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + [[package]] name = "constant_time_eq" version = "0.3.0" @@ -1440,6 +1461,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle 2.4.1", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -1470,6 +1503,16 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.7", + "subtle 2.4.1", +] + [[package]] name = "ctr" version = "0.8.0" @@ -1534,6 +1577,15 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", +] + [[package]] name = "derivation-path" version = "0.2.0" @@ -1667,6 +1719,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d978bd5d343e8ab9b5c0fc8d93ff9c602fdc96616ffff9c05ac7a155419b824" +[[package]] +name = "ecdsa" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "ed25519" version = "1.5.3" @@ -1708,6 +1772,24 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "elliptic-curve" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "ff", + "generic-array 0.14.7", + "group", + "rand_core 0.6.4", + "sec1", + "subtle 2.4.1", + "zeroize", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -1807,6 +1889,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" +[[package]] +name = "ff" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" +dependencies = [ + "rand_core 0.6.4", + "subtle 2.4.1", +] + [[package]] name = "fixed-hash" version = "0.8.0" @@ -2049,6 +2141,17 @@ dependencies = [ "siphasher", ] +[[package]] +name = "group" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle 2.4.1", +] + [[package]] name = "h2" version = "0.3.20" @@ -2184,6 +2287,16 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + [[package]] name = "hmac" version = "0.12.1" @@ -3035,6 +3148,18 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "p256" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19736d80675fbe9fe33426268150b951a3fb8f5cfca2a23a17c85ef3adb24e3b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sec1", + "sha2 0.9.9", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -3153,6 +3278,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der", + "spki", + "zeroize", +] + [[package]] name = "pkg-config" version = "0.3.27" @@ -3538,6 +3674,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ref_thread_local" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d51660a68078997855ba5602f73ab3a5031bd7ad480a9d4c90fbbf04e1fff0" + [[package]] name = "regex" version = "1.9.1" @@ -3617,6 +3759,17 @@ dependencies = [ "winreg", ] +[[package]] +name = "rfc6979" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +dependencies = [ + "crypto-bigint", + "hmac 0.11.0", + "zeroize", +] + [[package]] name = "ring" version = "0.16.20" @@ -3867,6 +4020,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "sec1" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +dependencies = [ + "der", + "generic-array 0.14.7", + "pkcs8", + "subtle 2.4.1", + "zeroize", +] + [[package]] name = "secp256k1" version = "0.22.2" @@ -3946,9 +4112,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.180" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] @@ -3964,18 +4130,18 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.12" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +checksum = "f3c5113243e4a3a1c96587342d067f3e6b0f50790b6cf40d2868eb647a3eef0e" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.180" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2 1.0.66", "quote 1.0.32", @@ -3984,9 +4150,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -4112,9 +4278,13 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "signature" -version = "1.6.4" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +dependencies = [ + "digest 0.9.0", + "rand_core 0.6.4", +] [[package]] name = "siphasher" @@ -4710,6 +4880,16 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "spl-associated-token-account" version = "1.1.3" diff --git a/tools/ckb-auth-cli/rust-toolchain b/tools/ckb-auth-cli/rust-toolchain new file mode 100644 index 0000000..12816e6 --- /dev/null +++ b/tools/ckb-auth-cli/rust-toolchain @@ -0,0 +1 @@ +1.71 diff --git a/tools/ckb-auth-cli/src/bitcoin.rs b/tools/ckb-auth-cli/src/bitcoin.rs new file mode 100644 index 0000000..edc48a0 --- /dev/null +++ b/tools/ckb-auth-cli/src/bitcoin.rs @@ -0,0 +1,90 @@ +use super::{BlockChain, BlockChainArgs}; +use crate::utils::decode_string; +use anyhow::{anyhow, Error}; +use ckb_auth_rs::AlgorithmType; +use clap::{arg, ArgMatches, Command}; +// use ckb_auth_rs::AlgorithmType; +// use hex::decode; + +pub struct BitcoinLockArgs {} + +impl BlockChainArgs for BitcoinLockArgs { + fn block_chain_name(&self) -> &'static str { + "bitcoin" + } + + fn reg_parse_args(&self, cmd: Command) -> Command { + cmd + } + fn reg_generate_args(&self, cmd: Command) -> Command { + cmd + } + fn reg_verify_args(&self, cmd: Command) -> Command { + cmd.arg(arg!(-a --address "The bitcoin address")) + .arg(arg!(-s --signature "The signature to verify")) + .arg(arg!(-m --message "The signature message")) + } + + fn get_block_chain(&self) -> Box { + Box::new(BitcoinLock {}) + } +} + +pub struct BitcoinLock {} + +impl BlockChain for BitcoinLock { + fn parse(&self, _operate_mathches: &ArgMatches) -> Result<(), Error> { + Err(anyhow!("bitcoin does not parse")) + } + + fn generate(&self, _operate_mathches: &ArgMatches) -> Result<(), Error> { + Err(anyhow!("bitcoin does not generate")) + } + + fn verify(&self, operate_mathches: &ArgMatches) -> Result<(), Error> { + let address = bs58::decode( + operate_mathches + .get_one::("address") + .expect("Get address from args"), + ) + .into_vec() + .expect("get base58"); + + let signature = decode_string( + operate_mathches + .get_one::("signature") + .expect("Get signature from args"), + "base64", + ) + .expect("decode signature from base64 string"); + + let message = hex::decode( + operate_mathches + .get_one::("message") + .expect("Get message from args"), + ) + .expect("decode message"); + + if address.len() < 21 { + return Err(anyhow!("bitcoin address invalidate")); + } + if signature.len() != 65 { + return Err(anyhow!("bitcoin signature size is not 65")); + } + if message.len() != 32 { + return Err(anyhow!("bitcoin message size is not 32")); + } + + let pubkey_hash = &address[1..21]; + + super::auth_script::run_auth_exec( + AlgorithmType::Bitcoin, + pubkey_hash, + &message, + &signature, + )?; + + println!("Signature verification succeeded!"); + Ok(()) + } +} diff --git a/tools/ckb-auth-cli/src/main.rs b/tools/ckb-auth-cli/src/main.rs index 233904c..8e9a718 100644 --- a/tools/ckb-auth-cli/src/main.rs +++ b/tools/ckb-auth-cli/src/main.rs @@ -1,16 +1,18 @@ mod auth_script; +mod bitcoin; mod cardano; mod litecoin; mod monero; -mod solana; mod ripple; +mod solana; mod utils; use crate::monero::MoneroLockArgs; +use bitcoin::BitcoinLockArgs; use cardano::CardanoLockArgs; use litecoin::LitecoinLockArgs; -use solana::SolanaLockArgs; use ripple::RippleLockArgs; +use solana::SolanaLockArgs; use anyhow::{anyhow, Error}; use clap::{ArgMatches, Command}; @@ -80,6 +82,7 @@ fn main() -> Result<(), Error> { Box::new(MoneroLockArgs {}) as Box, Box::new(SolanaLockArgs {}) as Box, Box::new(RippleLockArgs {}) as Box, + Box::new(BitcoinLockArgs {}) as Box, ]; let matches = cli(block_chain_args.as_slice()).get_matches();