• About
  • FAQ
  • Earn Bitcoin while Surfing the net
  • Buy & Sell Crypto on Paxful
Newsletter
Approx Foundation
  • Home
    • Home – Layout 1
  • Bitcoin
  • Ethereum
  • Regulation
  • Market
  • Blockchain
  • Business
  • Guide
  • Contact Us
No Result
View All Result
  • Home
    • Home – Layout 1
  • Bitcoin
  • Ethereum
  • Regulation
  • Market
  • Blockchain
  • Business
  • Guide
  • Contact Us
No Result
View All Result
Approx Foundation
No Result
View All Result
Home Bitcoin

verification – Rust Verify Signature

Moussa by Moussa
November 11, 2025
in Bitcoin
0
How do Bitcoin mining pools typically handle payout frequency versus thresholds?
189
SHARES
1.5k
VIEWS
Share on FacebookShare on Twitter


I’m trying to verify signed messages using Rust. lumo AI generated me this:

#[cfg(feature = "derive")]

use bitcoin::util::key::PublicKey;
use secp256k1::{Secp256k1};
pub mod messages {
use bitcoin::{
    Address, PublicKey, address::Payload, hashes::{Hash, sha256d::{self, Hash as Sha256dHash}}, secp256k1::{
        self,
        All,               // the context type we’ll use
        Message
    }
};
use base64::decode;
use secp256k1::{Secp256k1, ecdsa::{RecoverableSignature, RecoveryId}}; // only for convenience; you could use any Base64 lib

/// Turn the first byte of a legacy signature (27‑34) into a `RecoveryId`.
fn decode_recovery_byte(byte: u8) -> Result {
    if !(27..=34).contains(&byte) {
        return Err(secp256k1::Error::InvalidRecoveryId);
    }
    // Low‑order two bits = real recovery id (0‑3). The extra +4 (for compressed)
    // is stripped automatically by the modulo operation.
    RecoveryId::from_i32((byte % 4) as i32)
}

/// Compute the exact double‑SHA‑256 hash that Bitcoin‑CLI/Electrum sign.
///
/// The payload is:
///   <"Bitcoin Signed Message:\n">
///   
fn bitcoin_message_hash(msg: &str) -> Sha256dHash {
    const MAGIC: &str = "Bitcoin Signed Message:\n";

    // CompactSize (varint) encoder – identical to Bitcoin Core.
    fn varint_len(s: &str) -> Vec {
        let mut v = Vec::new();
        let len = s.len() as u64;
        if len < 0xfd {
            v.push(len as u8);
        } else if len <= 0xffff {
            v.push(0xfd);
            v.extend_from_slice(&(len as u16).to_le_bytes());
        } else if len <= 0xffff_ffff {
            v.push(0xfe);
            v.extend_from_slice(&(len as u32).to_le_bytes());
        } else {
            v.push(0xff);
            v.extend_from_slice(&len.to_le_bytes());
        }
        v.extend_from_slice(s.as_bytes());
        v
    }

    let mut data = Vec::new();
    data.extend(varint_len(MAGIC));
    data.extend(varint_len(msg));
    sha256d::Hash::hash(&data)
}

/// Verify a classic Bitcoin‑CLI / Electrum signed‑message **using only the `bitcoin` crate**.
///
/// * `address_str` – the address that allegedly signed the message (Base58 `1…` or Bech32 `bc1…`).  
/// * `message`     – the exact clear‑text that was signed.  
/// * `sig_base64`  – the Base64 string printed by the wallet.
///
/// Returns `Ok(true)` if the signature is valid for the supplied address,
/// `Ok(false)` if it is syntactically correct but does **not** match,
/// and `Err(_)` for malformed inputs (bad Base64, wrong length, unsupported address type, etc.).
pub fn verify_signed_message(
    address_str: &str,
    message: &str,
    sig_base64: &str,
) -> Result> {

    
    // --------------------------------------------------------------
    // 1️⃣ Decode the Base64 signature (must be exactly 65 bytes)
    // --------------------------------------------------------------
    let sig_bytes = decode(sig_base64.trim())?;
    if sig_bytes.len() != 65 {
        return Err(format!("Signature must be 65 bytes (got {})", sig_bytes.len()).into());
    }
   println!("c111heckingadfdsads for address");
    // --------------------------------------------------------------
    // 2️⃣ Split recovery byte and compact (r|s) signature
    // --------------------------------------------------------------
    let rec_id = decode_recovery_byte(sig_bytes[0])?;
    let is_compressed = sig_bytes[0] >= 31; // true for 31‑34
    let compact_sig = &sig_bytes[1..]; // 64‑byte slice (r‖s)

    // --------------------------------------------------------------
    // 3️⃣ Build a RecoverableSignature (bundles the rec_id)
    // --------------------------------------------------------------
    let recoverable = RecoverableSignature::from_compact(compact_sig, rec_id)?;

    // --------------------------------------------------------------
    // 4️⃣ Compute the double‑SHA‑256 hash of the message (magic prefix)
    // --------------------------------------------------------------
    let msg_hash = bitcoin_message_hash(message);
    let secp_msg = Message::from_slice(msg_hash.as_ref())?;

    // --------------------------------------------------------------
    // 5️⃣ Recover the public key
    // --------------------------------------------------------------
    // `Secp256k1::verification_only()` gives us a read‑only context.
    let secp = Secp256k1::verification_only();
    let recovered_secp = secp.recover_ecdsa(&secp_msg, &recoverable)?;
    let recovered_pub = PublicKey::new(recovered_secp);
   println!("checkingadfdsads for address");
    // --------------------------------------------------------------
    // 6️⃣ Parse the supplied address (this also tells us the network)
    // --------------------------------------------------------------
    let supplied_addr: Address = address_str.parse::<:address>>().unwrap().assume_checked();
    println!("checking for address");
    // --------------------------------------------------------------
    // 7️⃣ Re‑derive the address from the recovered public key
    // --------------------------------------------------------------
    let derived_addr = match supplied_addr.payload {
        // ---------- Legacy Base58 (P2PKH) ----------
        Payload::PubkeyHash(_) => {
            // `p2pkh` automatically uses the compressed form if the key is
            // compressed; the `is_compressed` flag we extracted earlier is only
            // needed for sanity‑checking, not for address construction.
            Address::p2pkh(&recovered_pub, supplied_addr.network)
        }

        // // ---------- Native SegWit v0 (bc1q…) ----------
        // Payload::WitnessProgram {
        //     version: 0,
        //     program: ref prog,
        // } if prog.len() == 20 => {
        //     // SegWit v0 always uses the **compressed** public key, regardless
        //     // of the flag in the signature.  The `is_compressed` boolean is
        //     // therefore irrelevant for address reconstruction here.
        //     Address::p2wpkh(&recovered_pub, supplied_addr.network)?
        // }

        // Anything else (Taproot `bc1p…`, P2SH‑wrapped, multisig, etc.)
        // is not supported by the legacy signed‑message format.
        _ => {
            return Err(format!(
                "Legacy verification only supports P2PKH (1…) and native SegWit v0 (bc1q…) \
                 addresses. Address `{}` is of a different type.",
                address_str
            )
            .into())
        }
    };
    println!("{:?}", derived_addr);
    println!("{:?}", supplied_addr);
    // --------------------------------------------------------------
    // 8️⃣ Compare the derived address with the supplied one
    // --------------------------------------------------------------
    Ok(derived_addr == supplied_addr)
}
}

Can anyone tell me why this code isn’t working? I’ve checked bitcoin-cli verifymessage and returned true. The Rust code is returning false. I’m using a P2PKH address. Signing with the Sparrow wallet.



Source link

Related articles

Moo Deng Meme Coin After the Zoo Kidnapping Scare

South East Asia ETF Shock Inbound? Thailand Weighs Direct BTC and ETH ETF Listings

August 26, 2026
SpaceX Tokenization Scramble Shows The Difference Between Tokens And Real Shares

Chainlink Adds 12 Integrations Across 10 Blockchains

August 26, 2026
Share76Tweet47

Related Posts

Moo Deng Meme Coin After the Zoo Kidnapping Scare

South East Asia ETF Shock Inbound? Thailand Weighs Direct BTC and ETH ETF Listings

by Moussa
August 26, 2026
0

In Bitcoin ETF news today, Thailand’s SEC has opened a public consultation on draft rules that would allow asset managers...

SpaceX Tokenization Scramble Shows The Difference Between Tokens And Real Shares

Chainlink Adds 12 Integrations Across 10 Blockchains

by Moussa
August 26, 2026
0

Trusted Editorial content, reviewed by leading industry experts and seasoned editors. Ad Disclosure Chainlink has announced 12 new integrations across...

CleanCore Dumps Dogecoin Treasury To Fund $100M AI Pivot

CleanCore Dumps Dogecoin Treasury To Fund $100M AI Pivot

by Moussa
August 26, 2026
0

CleanCore has disclosed plans to liquidate its Dogecoin treasury holdings as part of a broader $100 million funding plan tied...

Coinbase And Better Announce Bitcoin-Backed Mortgages

Coinbase And Better Announce Bitcoin-Backed Mortgages

by Moussa
August 26, 2026
0

Coinbase and Nasdaq-listed Better Mortgage have announced the availability of Bitcoin-backed mortgages for Americans.  The crypto exchange and lender said...

Sticky Inflation Strikes Again as Fed Faces Stagflation Trap

Sticky Inflation Strikes Again as Fed Faces Stagflation Trap

by Moussa
August 26, 2026
0

Key TakeawaysSticky inflation remains a problem and some believe stagflation is looming.In a market note shared with Bitcoin.com News, Devere...

Load More

youssufi.com

sephina.com

[vc_row full_width="stretch_row" parallax="content-moving" vc_row_background="" background_repeat="no-repeat" background_position="center center" footer_scheme="dark" css=".vc_custom_1517813231908{padding-top: 60px !important;padding-bottom: 30px !important;background-color: #191818 !important;background-position: center;background-repeat: no-repeat !important;background-size: cover !important;}" footer_widget_title_color="#fcbf46" footer_button_bg="#fcb11e"][vc_column width="1/4"]

We bring you the latest in Crypto News

[/vc_column][vc_column width="1/4"][vc_wp_categories]
[/vc_column][vc_column width="1/4"][vc_wp_tagcloud taxonomy="post_tag"][/vc_column][vc_column width="1/4"]

Newsletter

[vc_raw_html]JTNDcCUzRSUzQ2RpdiUyMGNsYXNzJTNEJTIydG5wJTIwdG5wLXN1YnNjcmlwdGlvbiUyMiUzRSUwQSUzQ2Zvcm0lMjBtZXRob2QlM0QlMjJwb3N0JTIyJTIwYWN0aW9uJTNEJTIyaHR0cHMlM0ElMkYlMkZhcHByb3gub3JnJTJGJTNGbmElM0RzJTIyJTNFJTBBJTBBJTNDaW5wdXQlMjB0eXBlJTNEJTIyaGlkZGVuJTIyJTIwbmFtZSUzRCUyMm5sYW5nJTIyJTIwdmFsdWUlM0QlMjIlMjIlM0UlM0NkaXYlMjBjbGFzcyUzRCUyMnRucC1maWVsZCUyMHRucC1maWVsZC1maXJzdG5hbWUlMjIlM0UlM0NsYWJlbCUyMGZvciUzRCUyMnRucC0xJTIyJTNFRmlyc3QlMjBuYW1lJTIwb3IlMjBmdWxsJTIwbmFtZSUzQyUyRmxhYmVsJTNFJTBBJTNDaW5wdXQlMjBjbGFzcyUzRCUyMnRucC1uYW1lJTIyJTIwdHlwZSUzRCUyMnRleHQlMjIlMjBuYW1lJTNEJTIybm4lMjIlMjBpZCUzRCUyMnRucC0xJTIyJTIwdmFsdWUlM0QlMjIlMjIlM0UlM0MlMkZkaXYlM0UlMEElM0NkaXYlMjBjbGFzcyUzRCUyMnRucC1maWVsZCUyMHRucC1maWVsZC1lbWFpbCUyMiUzRSUzQ2xhYmVsJTIwZm9yJTNEJTIydG5wLTIlMjIlM0VFbWFpbCUzQyUyRmxhYmVsJTNFJTBBJTNDaW5wdXQlMjBjbGFzcyUzRCUyMnRucC1lbWFpbCUyMiUyMHR5cGUlM0QlMjJlbWFpbCUyMiUyMG5hbWUlM0QlMjJuZSUyMiUyMGlkJTNEJTIydG5wLTIlMjIlMjB2YWx1ZSUzRCUyMiUyMiUyMHJlcXVpcmVkJTNFJTNDJTJGZGl2JTNFJTBBJTNDZGl2JTIwY2xhc3MlM0QlMjJ0bnAtZmllbGQlMjB0bnAtcHJpdmFjeS1maWVsZCUyMiUzRSUzQ2xhYmVsJTNFJTNDaW5wdXQlMjB0eXBlJTNEJTIyY2hlY2tib3glMjIlMjBuYW1lJTNEJTIybnklMjIlMjByZXF1aXJlZCUyMGNsYXNzJTNEJTIydG5wLXByaXZhY3klMjIlM0UlQzIlQTBCeSUyMGNvbnRpbnVpbmclMkMlMjB5b3UlMjBhY2NlcHQlMjB0aGUlMjBwcml2YWN5JTIwcG9saWN5JTNDJTJGbGFiZWwlM0UlM0MlMkZkaXYlM0UlM0NkaXYlMjBjbGFzcyUzRCUyMnRucC1maWVsZCUyMHRucC1maWVsZC1idXR0b24lMjIlM0UlM0NpbnB1dCUyMGNsYXNzJTNEJTIydG5wLXN1Ym1pdCUyMiUyMHR5cGUlM0QlMjJzdWJtaXQlMjIlMjB2YWx1ZSUzRCUyMlN1YnNjcmliZSUyMiUyMCUzRSUwQSUzQyUyRmRpdiUzRSUwQSUzQyUyRmZvcm0lM0UlMEElM0MlMkZkaXYlM0UlM0NiciUyRiUzRSUzQyUyRnAlM0U=[/vc_raw_html][/vc_column][/vc_row]
No Result
View All Result
  • Contact Us
  • Homepages
  • Business
  • Guide

© 2024 APPROX FOUNDATION - The Crypto Currency News