Skip to content

Commit

Permalink
Ethereum doc (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
joii2020 authored Sep 27, 2023
1 parent a88febd commit 3303d5f
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 16 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ throughout the process.
The following blockchains are supported:

* [Bitcoin](./docs/bitcoin.md)
* Ethereum
* [Ethereum](./docs/ethereum.md)
* EOS
* Tron
* Dogecoin
Expand Down
28 changes: 14 additions & 14 deletions docs/bitcoin.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# [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).
Here, use the official wallet [Bitcoin Core](https://bitcoincore.org) (Version 25.0). ([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).
**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, For details, please see this [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.)
Download the binary archive from [here](https://bitcoincore.org/bin/bitcoin-core-25.0/), choose the file corresponding to platform, and unarchive it. (Note: If 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.
After installation is complete, start the background program: `bitcoind`. The signature and verify we need to do later need to rely on this service to process.
```shell
bitcoind
bitcoind -chain=regtest -daemonwait
```
(For the convenience of testing, start Bitcoin Core in Regtest mode and run it in the background, waiting until it is fully started.)

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.
Expand All @@ -37,7 +37,7 @@ Output address:

### Generate Signature

First, you need to generate a 32-byte data segment as message:
To begin, generate a 32-byte data segment as the message:
```shell
message=0011223344556677889900112233445500112233445566778899001122334455
```
Expand All @@ -46,7 +46,7 @@ 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.
If the wallet requires a password, unlock it first using `walletpassphrase`.

Once the signing is successful, it will output the signature result, which is encoded in base64:
```
Expand All @@ -55,7 +55,7 @@ H0v6+IkWf0WL6MDCz0K6XeTiNSChoiDIEzgJQMadJi78NoHE3roRx8QX1mnK57on5w5doBXOFBn1kwpO

### Verify

Here you can directly pass the address, signature and message to ckb-auth-cli to verify:
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
```
Expand All @@ -65,15 +65,15 @@ ckb-auth-cli bitcoin verify -a 1CSbWFszmuQiPCRPsaDhhb2NuFTEZFQqih -s H0v6+IkWf0W

### Cofing Bitcoin Core

If you wish to perform testing using a GUI or disable network activity, please refer to the configuration instructions below.
For GUI testing or disabling network activity, 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.
First time using, need to manually create these directories and files.

Disabling network activity is mainly done to reduce disk usage:

Expand All @@ -97,7 +97,7 @@ 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.
- After creation, the 'Address' will be visible in the lower part of a separate window. The addresses held by the current wallet can be checked in the table below.

If the address starts with `bc` or `tb`, make sure to verify the correctness of the above configurations.

Expand All @@ -109,11 +109,11 @@ 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.
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, just use string directly.

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.
The returned signature data is encoded in base64, with a fixed binary length of 65 bytes. In this case, no special processing is required and passed directly to ckb-auth

### Verify

Expand Down
110 changes: 110 additions & 0 deletions docs/ethereum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# [Ethereum Lock](../README.md)

Here, we are conducting comparative testing using the official Ethereum tool [go-ethereum](https://geth.ethereum.org/) (Version 1.12.2).

## Install
Supported installation methods:

* Package Managers, supported on: Mac (brew), Ubuntu, FreeBSD, Arch Linux. For specific instructions, please refer to the [official documentation](https://geth.ethereum.org/docs/getting-started/installing-geth).
* [Download the standalone bundle](https://geth.ethereum.org/downloads)
* Building from [source code](https://github.com/ethereum/go-ethereum)

Within the `geth` package, there are multiple executable files. Here, we will focus on using `geth` and `ethkey`.

* `geth` for creating accounts and generating addresses.
* `ethkey` for signature and verification.

Note that if using a standalone bundle or building from source, it's advisable to add the installation directory to environment variables for ease of use.

### Build from source code
Keep in mind that compiling `geth` requires a [golang environment](https://go.dev/doc/install).

```
git clone https://github.com/ethereum/go-ethereum.git
cd go-ethereum
make all
```

As `ethkey` is required, we compile all components for convenience. The compiled results can be found in the `build/bin` directory. It's recommended to add this directory to 'PATH' environment variable for ease of use.

## Address
First, A test account is required:
```shell
geth account new
```

Once created, look for this line in the output:
```
Public address of the key: <BIN>
Path of the secret key file: <FILE_PATH>
```

Here, the account's address and private key file are displayed. To query account information again, use: `geth account list`.

In Ethereum, the `Address` is a 20-byte fixed-length array. When used in programs (geth and ckb-auth-cli), it will handle the leading `0x`.

If automation testing is needed, the passwordfile and keystore parameters can be employed to handle password and key storage.

```shell
eth_password_file=`pwd`/password.txt
echo $RANDOM > $eth_password_file
eth_account_dir=`pwd`/account
rm -rf $eth_account_dir
mkdir -p $eth_account_dir
geth account new --password $eth_password_file --keystore $eth_account_dir > /dev/null 2>&1

eth_account_info=`geth account list --keystore $eth_account_dir 2>/dev/null`
eth_address=`echo $eth_account_info | grep -oE -m 1 '\{[a-f0-9]+\}' | sed 's/{\(.*\)}/\1/'`
eth_privkey_file=`echo $eth_account_info | grep -oE 'keystore://[^ ]+' | awk -F 'keystore:' '{print $2}'`

echo Address: $eth_address
echo PrivateKeyFile: $eth_privkey_file
```

After executing the above code. The value `eth_address` is ethereum address, `eth_privkey_file` is private key file path. In subsequent operations, these two variables can be used directly.

## Signature

Ethereum's message is calculated using sha3: `Ethereum Signed Message:\n` + 'message' hash. While ckb-auth's message is a fixed length of 32 bytes, so here, `ethkey` supports the input of messages in both textual form and through a file (by using the `--msgfile` parameter). In this context, Ethereum's message is directly utilized as a data parameter hash, necessitating the use of the `--msgfile` to input a file.

Here, ethkey needs to use message_file, use `ckb-auth-cli ethereum generate` to convert the message to file:
```shell
message=0011223344556677889900112233445500112233445566778899001122334455
message_file=`pwd`/message_file.bin
ckb-auth-cli ethereum generate -m $message --msgfile $message_file
```
(Other paths can also be used)

After generating the message file, ethkey can be used for signing:
```shell
ethkey signmessage --msgfile $message_file --passwordfile $eth_password_file $eth_privkey_file
```
output:
```
Signature: 5a62aa66a32a41fb44a58e7284ca964952da485dc0fcec24dadb7402d65274d8733f9a2c34274c573d09743d04f25fdfb00ffee8d821a1422c7d3f4e97ce97e100
```

If it's an automated test, obtaining the signature can also be accomplished through a script.

```shell
eth_sign_info=`ethkey signmessage --msgfile $message_file --passwordfile $eth_password_file $eth_privkey_file`
eth_signature=`echo $eth_sign_info | awk -F 'Signature: ' '{print $2}'`
echo Signature: $eth_signature
```

Now, the value in `eth_signature` is signature.

After signing, verification can be done using geth to prevent any basic errors:
```shell
ethkey verifymessage --msgfile $message_file $eth_address $eth_signature
```

* Here need to pay attention to the order of command parameters.

## Verify

This can now be verified in ckb-auth:

```shell
ckb-auth-cli ethereum verify -a $eth_address -s $eth_signature -m $message
```
2 changes: 1 addition & 1 deletion tools/ckb-auth-cli/rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.71
1.71.1
103 changes: 103 additions & 0 deletions tools/ckb-auth-cli/src/ethereum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use super::{BlockChain, BlockChainArgs};
use anyhow::{anyhow, Error};
use ckb_auth_rs::AlgorithmType;
use clap::{arg, ArgMatches, Command};
use hex::decode;

pub struct EthereumLockArgs {}

impl BlockChainArgs for EthereumLockArgs {
fn block_chain_name(&self) -> &'static str {
"ethereum"
}

fn reg_parse_args(&self, cmd: Command) -> Command {
cmd
}
fn reg_generate_args(&self, cmd: Command) -> Command {
cmd.arg(arg!(-m --message <MESSAGE> "Generate message binary for ethereum signing"))
.arg(arg!(--msgfile <MESSAGE_FILE> "Output file"))
}
fn reg_verify_args(&self, cmd: Command) -> Command {
cmd.arg(arg!(-a --address <PUBKEYHASH> "The ethereum address"))
.arg(arg!(-s --signature <SIGNATURE> "The signature to verify"))
.arg(arg!(-m --message <MESSAGE> "The signature message"))
}

fn get_block_chain(&self) -> Box<dyn BlockChain> {
Box::new(BitcoinLock {})
}
}

pub struct BitcoinLock {}

impl BlockChain for BitcoinLock {
fn parse(&self, _operate_mathches: &ArgMatches) -> Result<(), Error> {
Err(anyhow!("ethereum does not generate"))
}

fn generate(&self, operate_mathches: &ArgMatches) -> Result<(), Error> {
let message = decode(
operate_mathches
.get_one::<String>("message")
.expect("Get signature message"),
)
.expect("Decode message");
if message.len() != 32 {
return Err(anyhow!("Signature length must be 32"));
}

let msgfile = operate_mathches
.get_one::<String>("msgfile")
.expect("Get signature message output file");

let msgfile = std::path::PathBuf::from(msgfile);
// if msgfile.exists() && msgfile.is_file() {
// std::fs::remove_file(&msgfile);
// }

std::fs::write(msgfile, message).expect("write message file");

Ok(())
}

fn verify(&self, operate_mathches: &ArgMatches) -> Result<(), Error> {
let mut address = operate_mathches
.get_one::<String>("address")
.expect("Get address from args")
.clone();
if address.starts_with("0x") {
address = address[2..].to_string();
}
let address = decode(&address).expect("decode address");

let signature = decode(
operate_mathches
.get_one::<String>("signature")
.expect("Get signature from args"),
)
.expect("decode ethereum signature");

let message = decode(
operate_mathches
.get_one::<String>("message")
.expect("Get message from args"),
)
.expect("decode ethereum message");

if address.len() != 20 {
return Err(anyhow!("ethereum address invalidate"));
}
if signature.len() != 65 {
return Err(anyhow!("ethereum signature size is not 65"));
}
if message.len() != 32 {
return Err(anyhow!("ethereum message size is not 32"));
}

super::auth_script::run_auth_exec(AlgorithmType::Ethereum, &address, &message, &signature)?;

println!("Ethereum Signature verification succeeded!");
Ok(())
}
}
3 changes: 3 additions & 0 deletions tools/ckb-auth-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod auth_script;
mod bitcoin;
mod cardano;
mod ethereum;
mod litecoin;
mod monero;
mod ripple;
Expand All @@ -10,6 +11,7 @@ mod utils;
use crate::monero::MoneroLockArgs;
use bitcoin::BitcoinLockArgs;
use cardano::CardanoLockArgs;
use ethereum::EthereumLockArgs;
use litecoin::LitecoinLockArgs;
use ripple::RippleLockArgs;
use solana::SolanaLockArgs;
Expand Down Expand Up @@ -83,6 +85,7 @@ fn main() -> Result<(), Error> {
Box::new(SolanaLockArgs {}) as Box<dyn BlockChainArgs>,
Box::new(RippleLockArgs {}) as Box<dyn BlockChainArgs>,
Box::new(BitcoinLockArgs {}) as Box<dyn BlockChainArgs>,
Box::new(EthereumLockArgs {}) as Box<dyn BlockChainArgs>,
];

let matches = cli(block_chain_args.as_slice()).get_matches();
Expand Down

0 comments on commit 3303d5f

Please sign in to comment.