| Crates.io | wallet-signature-verify |
| lib.rs | wallet-signature-verify |
| version | 0.3.2 |
| created_at | 2025-10-09 22:08:45.745566+00 |
| updated_at | 2025-10-29 10:06:49.764323+00 |
| description | Universal wallet signature verifier using challenge-response authentication. Receives a challenge, wallet address, and signature, then validates that the address actually signed the challenge. |
| homepage | https://github.com/marcus-gomes-v/wallet-signature-verify |
| repository | https://github.com/marcus-gomes-v/wallet-signature-verify |
| max_upload_size | |
| id | 1876239 |
| size | 254,610 |
Universal library and CLI for cryptographic verification of wallet signatures using challenge-response authentication.
This tool implements a secure authentication system based on 4 components:
The verifier receives these 4 components and validates that the address actually signed the challenge.
# 1. Compile
cargo build --release
# 2. Execute with: wallet type, signature, address, challenge
./target/release/wallet-signature-verify \
--wallet xaman \
--signature "<hex_blob>" \
--address "<wallet_address>" \
--challenge "<unique_challenge>"
# 3. Check exit code
echo $? # 0 = valid, 1 = invalid
use wallet_signature_verify::{
wallets::{get_wallet_provider, WalletType, VerificationInput},
};
fn main() -> anyhow::Result<()> {
// The 4 components:
let input = VerificationInput {
signature_data: signature, // The signature hex
expected_address: address, // The wallet address
challenge: Some(challenge), // The unique challenge
};
// Select the wallet type
let provider = get_wallet_provider(WalletType::Xaman);
// Verify that the address signed the challenge
let result = provider.verify(&input)?;
if result.is_valid() {
println!("โ
Authenticated! Address {} signed the challenge", address);
}
Ok(())
}
๐ See more: LIBRARY_USAGE.md
cargo build --release
# Binary: ./target/release/wallet-signature-verify
./target/release/wallet-signature-verify \
--wallet <type> \
--signature <signature_hex> \
--address <wallet_address> \
--challenge <challenge_string>
Parameters:
--wallet - Wallet type: xaman, web3auth, or wallet_connect--signature - Signature hex (full blob for Xaman, DER for Web3Auth, EIP-191 for Bifrost)--address - Wallet address that signed (e.g., rAddress for XRPL, 0x for Ethereum)--challenge - Unique challenge string that was signedExit Codes:
0 = โ
Valid (address signed the challenge - all checks passed)1 = โ Invalid (signature verification failed)2 = โ ๏ธ Usage error (invalid arguments or unsupported wallet)Xaman (XRPL):
./target/release/wallet-signature-verify \
--wallet xaman \
--signature "732102DB48115142..." \
--address "rExampleAddr123456789xrpL1234567890" \
--challenge "example.com:1234567890:..."
Web3Auth (secp256k1):
./target/release/wallet-signature-verify \
--wallet web3auth \
--signature "3045022100D69B7099..." \
--address "rTestAddr789012345xrpLTest567890abc" \
--challenge "example.com:1234567891:..."
Bifrost (EVM/Ethereum):
./target/release/wallet-signature-verify \
--wallet wallet_connect \
--signature "0xe5092134a1e3a91dafe7095916466a00..." \
--address "0x33f9D9f0348c1a4Bace2ad839903bBD47F430651" \
--challenge "nuff.tech:1760706960:afba42ef-fbb7-4504-8915-583046d6eb26:login:0x33f9D9f0348c1a4Bace2ad839903bBD47F430651"
๐ See more examples:
Add to your Cargo.toml:
# All wallets (default)
[dependencies]
wallet-signature-verify = "0.3"
# Or from path
[dependencies]
wallet-signature-verify = { path = "../wallet-signature-verify" }
Choose which wallets to include to reduce compilation time and dependencies:
# Only Xaman wallet
[dependencies]
wallet-signature-verify = { version = "0.2", default-features = false, features = ["xaman"] }
# Only Web3Auth wallet
[dependencies]
wallet-signature-verify = { version = "0.2", default-features = false, features = ["web3auth"] }
# Only Bifrost wallet (EVM-compatible)
[dependencies]
wallet-signature-verify = { version = "0.2", default-features = false, features = ["wallet_connect"] }
# Multiple specific wallets
[dependencies]
wallet-signature-verify = { version = "0.2", default-features = false, features = ["xaman", "web3auth", "wallet_connect"] }
# All wallets (same as default)
[dependencies]
wallet-signature-verify = { version = "0.2", features = ["all-wallets"] }
Available Features:
| Feature | Description | Documentation |
|---|---|---|
xaman |
Xaman Wallet (XRPL SignIn) support | docs |
web3auth |
Web3Auth wallet support | docs |
wallet_connect |
Bifrost/EVM wallets with EIP-191 signatures | docs |
cli |
CLI binary with logging (for binary only) | - |
all-wallets |
Convenience feature for all wallets | - |
| default | ["xaman", "web3auth", "wallet_connect", "cli"] |
- |
Benefits of selective features:
๐ View all features on docs.rs
use wallet_signature_verify::{
wallets::{get_wallet_provider, WalletType, VerificationInput},
};
// Challenge-response authentication:
// 1. Client receives a challenge from server
// 2. Client signs the challenge with their wallet
// 3. Client sends: address + signature + challenge
// 4. Server verifies that the address signed the challenge
let input = VerificationInput {
signature_data: sig, // Signature from wallet
expected_address: addr, // Wallet address
challenge: Some(challenge), // Original challenge
};
let provider = get_wallet_provider(WalletType::Xaman);
let result = provider.verify(&input)?;
if result.is_valid() {
// โ
Verified: The address actually signed this challenge
// Now you can authenticate the user!
}
cargo run --example verify_lib
๐ Complete documentation: LIBRARY_USAGE.md
import subprocess
def verify(wallet, signature, address, challenge):
try:
subprocess.run([
"./target/release/wallet-signature-verify",
"--wallet", wallet,
"--signature", signature,
"--address", address,
"--challenge", challenge
], check=True, capture_output=True)
return True # Address signed the challenge
except:
return False # Verification failed
if verify("xaman", sig, addr, ch):
print("โ
Authenticated!")
const { execSync } = require('child_process');
function verify(wallet, signature, address, challenge) {
try {
execSync(
`./target/release/wallet-signature-verify ` +
`--wallet ${wallet} ` +
`--signature "${signature}" ` +
`--address "${address}" ` +
`--challenge "${challenge}"`,
{ stdio: 'pipe' }
);
return true; // Address signed the challenge
} catch {
return false; // Verification failed
}
}
if (verify('xaman', sig, addr, ch)) {
console.log('โ
Authenticated!');
}
๐ See complete scripts: examples/
This library includes a comprehensive test suite with 46 Bitcoin-grade tests:
# Run all tests
cargo test
# Run with output
cargo test -- --nocapture
# Check test coverage locally
cargo install cargo-llvm-cov
cargo llvm-cov --all-features --open
Test Coverage:
Security Tests:
๐ See: TESTING.md for complete testing guide.
./target/release/wallet-signature-verify \
--wallet xaman \
--signature "7321ED9434799FED...TRUNCATED...E1F1" \
--address "rExampleAddr123456789xrpL1234567890" \
--challenge "example.com:1234567890:12345678-abcd-1234-abcd-123456789abc:login:rExampleAddr123456789xrpL1234567890"
./target/release/wallet-signature-verify \
--wallet web3auth \
--signature "3045022100ABC123...TRUNCATED...7890" \
--address "rTestAddr789012345xrpLTest567890abc" \
--challenge "example.com:1234567891:87654321-dcba-4321-dcba-987654321cba:login:rTestAddr789012345xrpLTest567890abc"
cargo run --example verify_lib
How it works:
Server generates unique challenge:
domain:timestamp:uuid:action:address
Example: example.com:1234567890:f0a3a280-...:login:rAddress...
Client signs the challenge with their wallet
Client sends 3 things to server:
Server verifies:
Recommended Challenge Format:
{domain}:{timestamp}:{uuid}:{action}:{address}
Example:
example.com:1234567890:12345678-abcd-1234-abcd-123456789abc:login:rExampleAddr123456789xrpL1234567890
Where:
domain - Your domain (prevents phishing)timestamp - Unix timestamp (allows expiration)uuid - Unique ID (prevents replay)action - Requested action (login, approve, etc)address - User address (binding to specific wallet)Supported Algorithms:
The architecture is blockchain-agnostic. Currently supports XRPL wallets, but can be extended to:
To add a new wallet, simply implement the WalletProvider trait!
The architecture is extensible! To add support for a new wallet:
src/wallets/WALLET_TEMPLATE/WalletProvider traitWalletType enum๐ Complete guide: ADDING_WALLETS.md
# 1. Fork the repository
# 2. Clone your fork
git clone https://github.com/your-username/wallet-signature-verify
# 3. Create a branch
git checkout -b feature/my-feature
# 4. Make your changes and test
cargo test
cargo build --release
# 5. Commit and push
git commit -m "feat: add support for WalletX"
git push origin feature/my-feature
# 6. Open a Pull Request
๐ See more: CONTRIBUTING.md
| File | Description |
|---|---|
| QUICKSTART.md | 5-minute quick start |
| USAGE.md | Examples in Python/Node/Rust/Bash |
| LIBRARY_USAGE.md | Complete guide for using as Rust library |
| CONTRIBUTING.md | How to contribute to the project |
| ADDING_WALLETS.md | How to add support for new wallets |
| examples/ | Ready-to-use scripts |
Control log verbosity using the RUST_LOG environment variable:
# Info level (default) - shows important verification steps
cargo run --release -- --wallet xaman --signature "..." --address "..." --challenge "..."
# Debug level - shows all verification details
RUST_LOG=debug cargo run --release -- --wallet xaman --signature "..." --address "..." --challenge "..."
# Warn level - shows only warnings and errors
RUST_LOG=warn cargo run --release -- --wallet xaman --signature "..." --address "..." --challenge "..."
# Error level - shows only errors
RUST_LOG=error cargo run --release -- --wallet xaman --signature "..." --address "..." --challenge "..."
Debug level shows:
Info level shows:
Warn/Error levels:
Unsupported wallet:
./target/release/wallet-signature-verify --help
# See list of supported wallets
Invalid signature (exit code 1):
Arguments error (exit code 2):
--help to see correct syntaxMIT License - Use freely in commercial and open source projects.
Developed for the blockchain community with a focus on security, extensibility, and ease of use.
Challenge-response authentication: A secure way to prove wallet ownership without exposing private keys.