• 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

Russia’s Sberbank Given Green Light To Custody Bitcoin

Russia’s Sberbank Given Green Light To Custody Bitcoin

October 8, 2026
Robinhood Puts $25M Into Bitcoin, Citing Belief in Crypto’s Future

Robinhood Puts $25M Into Bitcoin, Citing Belief in Crypto’s Future

October 8, 2026
Share76Tweet47

Related Posts

Russia’s Sberbank Given Green Light To Custody Bitcoin

Russia’s Sberbank Given Green Light To Custody Bitcoin

by Moussa
October 8, 2026
0

Russia’s largest bank has announced it is the first in the country to have been approved to custody bitcoin.  Sberbank...

Robinhood Puts $25M Into Bitcoin, Citing Belief in Crypto’s Future

Robinhood Puts $25M Into Bitcoin, Citing Belief in Crypto’s Future

by Moussa
October 8, 2026
0

Key TakeawaysRobinhood’s crypto chief confirmed a $25 million bitcoin allocation.Arkham characterized the move as the company’s first bitcoin purchase.Kerbrat described...

Cardano News: CIP-0113 Brings Compliance Rules to ADA Tokens

Cardano News: CIP-0113 Brings Compliance Rules to ADA Tokens

by Moussa
October 8, 2026
0

In Cardano news today, the Cardano Foundation has launched CIP-0113, a standard that lets issuers build compliance rules into programmable...

DSA White Paper Named Among the 2026 DC Fintech Week Winning Papers

BitGo And HashKey Expand Asia Partnership Across Staking, Custody And Tokenization

by Moussa
October 7, 2026
0

Trusted Editorial content, reviewed by leading industry experts and seasoned editors. Ad Disclosure TL;DR: BitGo and HashKey Cloud have expanded...

Ethereum ETFs Lose $201.9 Million As Bitcoin Funds Return To Inflows

Ethereum ETFs Lose $201.9 Million As Bitcoin Funds Return To Inflows

by Moussa
October 7, 2026
0

Reason to trust Strict editorial policy that focuses on accuracy, relevance, and impartiality Created by industry experts and meticulously reviewed...

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