• 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

Binance Records $1.5 Billion Stablecoin Net Inflow Amid Highly Reactive Market

Binance Records $1.5 Billion Stablecoin Net Inflow Amid Highly Reactive Market

May 17, 2026
Peter Schiff Tells VRIC Media the US Economy Is Heading Into Its Worst Inflation Yet – Bitcoin News

Peter Schiff Tells VRIC Media the US Economy Is Heading Into Its Worst Inflation Yet – Bitcoin News

May 17, 2026
Share76Tweet47

Related Posts

Binance Records $1.5 Billion Stablecoin Net Inflow Amid Highly Reactive Market

Binance Records $1.5 Billion Stablecoin Net Inflow Amid Highly Reactive Market

by Moussa
May 17, 2026
0

Semilore Faleti is a cryptocurrency writer specialized in the field of journalism and content creation. While he started out writing...

Peter Schiff Tells VRIC Media the US Economy Is Heading Into Its Worst Inflation Yet – Bitcoin News

Peter Schiff Tells VRIC Media the US Economy Is Heading Into Its Worst Inflation Yet – Bitcoin News

by Moussa
May 17, 2026
0

Key TakeawaysPeter Schiff warns that the Fed’s balance sheet expanded by over $200 billion in 2025, signaling a return to...

How do Bitcoin mining pools typically handle payout frequency versus thresholds?

Why is bitcoin connected to the banks?

by Moussa
May 17, 2026
0

Bitcoin is decentralized. Banks are centralized. The powers that be were not supposed to let the banks attach to bitcoin....

Bitcoin’s Fall To $78K Could Be A Bear Trap — Here’s Why

Bitcoin’s Fall To $78K Could Be A Bear Trap — Here’s Why

by Moussa
May 17, 2026
0

After springing back to life on the back of positive CLARITY Act development, the price of Bitcoin has been relatively...

Saylor Chart Puts Strategy’s Next Bitcoin Buy on Watch

Saylor Chart Puts Strategy’s Next Bitcoin Buy on Watch

by Moussa
May 17, 2026
0

Key TakeawaysMichael Saylor’s “Big Dot Energy” chart fueled speculation around another Strategy BTC purchase disclosure.Strategy continues expanding its bitcoin-focused treasury...

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