• About
  • Privacy Poilicy
  • Disclaimer
  • Contact
CoinInsight
  • Home
  • Bitcoin
  • Ethereum
  • Regulation
  • Market
  • Blockchain
  • Ripple
  • Future of Crypto
  • Crypto Mining
No Result
View All Result
  • Home
  • Bitcoin
  • Ethereum
  • Regulation
  • Market
  • Blockchain
  • Ripple
  • Future of Crypto
  • Crypto Mining
No Result
View All Result
CoinInsight
No Result
View All Result
Home Bitcoin

verification – Rust Confirm Signature

Coininsight by Coininsight
April 16, 2026
in Bitcoin
0
verification – Rust Confirm Signature
189
SHARES
1.5k
VIEWS
Share on FacebookShare on Twitter


I am attempting to confirm signed messages utilizing Rust. lumo AI generated me this:

#[cfg(feature = "derive")]

use bitcoin::util::key::PublicKey;
use secp256k1::{Secp256k1};
pub mod messages {
use bitcoin::{
    Deal with, PublicKey, handle::Payload, hashes::{Hash, sha256d::{self, Hash as Sha256dHash}}, secp256k1::{
        self,
        All,               // the context sort we’ll use
        Message
    }
};
use base64::decode;
use secp256k1::{Secp256k1, ecdsa::{RecoverableSignature, RecoveryId}}; // just for comfort; you could possibly use any Base64 lib

/// Flip the primary byte of a legacy signature (27‑34) right into a `RecoveryId`.
fn decode_recovery_byte(byte: u8) -> Consequence {
    if !(27..=34).comprises(&byte) {
        return Err(secp256k1::Error::InvalidRecoveryId);
    }
    // Low‑order two bits = actual restoration id (0‑3). The additional +4 (for compressed)
    // is stripped mechanically by the modulo operation.
    RecoveryId::from_i32((byte % 4) as i32)
}

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

    // CompactSize (varint) encoder – equivalent 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 information = Vec::new();
    information.lengthen(varint_len(MAGIC));
    information.lengthen(varint_len(msg));
    sha256d::Hash::hash(&information)
}

/// Confirm a basic Bitcoin‑CLI / Electrum signed‑message **utilizing solely the `bitcoin` crate**.
///
/// * `address_str` – the handle that allegedly signed the message (Base58 `1…` or Bech32 `bc1…`).  
/// * `message`     – the precise clear‑textual content that was signed.  
/// * `sig_base64`  – the Base64 string printed by the pockets.
///
/// Returns `Okay(true)` if the signature is legitimate for the provided handle,
/// `Okay(false)` whether it is syntactically right however does **not** match,
/// and `Err(_)` for malformed inputs (dangerous Base64, improper size, unsupported handle sort, and so on.).
pub fn verify_signed_message(
    address_str: &str,
    message: &str,
    sig_base64: &str,
) -> Consequence> {

    
    // --------------------------------------------------------------
    // 1️⃣ Decode the Base64 signature (should be precisely 65 bytes)
    // --------------------------------------------------------------
    let sig_bytes = decode(sig_base64.trim())?;
    if sig_bytes.len() != 65 {
        return Err(format!("Signature should be 65 bytes (acquired {})", sig_bytes.len()).into());
    }
   println!("c111heckingadfdsads for handle");
    // --------------------------------------------------------------
    // 2️⃣ Cut up restoration 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️⃣ Construct 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️⃣ Get better the general public key
    // --------------------------------------------------------------
    // `Secp256k1::verification_only()` provides us a learn‑solely 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 handle");
    // --------------------------------------------------------------
    // 6️⃣ Parse the provided handle (this additionally tells us the community)
    // --------------------------------------------------------------
    let supplied_addr: Deal with = address_str.parse::<:address>>().unwrap().assume_checked();
    println!("checking for handle");
    // --------------------------------------------------------------
    // 7️⃣ Re‑derive the handle from the recovered public key
    // --------------------------------------------------------------
    let derived_addr = match supplied_addr.payload {
        // ---------- Legacy Base58 (P2PKH) ----------
        Payload::PubkeyHash(_) => {
            // `p2pkh` mechanically makes use of the compressed kind if the secret's
            // compressed; the `is_compressed` flag we extracted earlier is simply
            // wanted for sanity‑checking, not for handle building.
            Deal with::p2pkh(&recovered_pub, supplied_addr.community)
        }

        // // ---------- Native SegWit v0 (bc1q…) ----------
        // Payload::WitnessProgram {
        //     model: 0,
        //     program: ref prog,
        // } if prog.len() == 20 => {
        //     // SegWit v0 at all times makes use of the **compressed** public key, regardless
        //     // of the flag within the signature.  The `is_compressed` boolean is
        //     // due to this fact irrelevant for handle reconstruction right here.
        //     Deal with::p2wpkh(&recovered_pub, supplied_addr.community)?
        // }

        // The rest (Taproot `bc1p…`, P2SH‑wrapped, multisig, and so on.)
        // will not be supported by the legacy signed‑message format.
        _ => {
            return Err(format!(
                "Legacy verification solely helps P2PKH (1…) and native SegWit v0 (bc1q…) 
                 addresses. Deal with `{}` is of a special sort.",
                address_str
            )
            .into())
        }
    };
    println!("{:?}", derived_addr);
    println!("{:?}", supplied_addr);
    // --------------------------------------------------------------
    // 8️⃣ Examine the derived handle with the provided one
    // --------------------------------------------------------------
    Okay(derived_addr == supplied_addr)
}
}

Can anybody inform me why this code is not working? I’ve checked bitcoin-cli verifymessage and returned true. The Rust code is returning false. I am utilizing a P2PKH handle. Signing with the Sparrow pockets.

Related articles

Musk’s SpaceX Breaks Under Its $135 IPO Value After a 42% Collapse From Its Peak

Musk’s SpaceX Breaks Under Its $135 IPO Value After a 42% Collapse From Its Peak

July 17, 2026
Visa Stablecoin Platform Launches for Banks, Fintechs

Visa Stablecoin Platform Launches for Banks, Fintechs

July 17, 2026


I am attempting to confirm signed messages utilizing Rust. lumo AI generated me this:

#[cfg(feature = "derive")]

use bitcoin::util::key::PublicKey;
use secp256k1::{Secp256k1};
pub mod messages {
use bitcoin::{
    Deal with, PublicKey, handle::Payload, hashes::{Hash, sha256d::{self, Hash as Sha256dHash}}, secp256k1::{
        self,
        All,               // the context sort we’ll use
        Message
    }
};
use base64::decode;
use secp256k1::{Secp256k1, ecdsa::{RecoverableSignature, RecoveryId}}; // just for comfort; you could possibly use any Base64 lib

/// Flip the primary byte of a legacy signature (27‑34) right into a `RecoveryId`.
fn decode_recovery_byte(byte: u8) -> Consequence {
    if !(27..=34).comprises(&byte) {
        return Err(secp256k1::Error::InvalidRecoveryId);
    }
    // Low‑order two bits = actual restoration id (0‑3). The additional +4 (for compressed)
    // is stripped mechanically by the modulo operation.
    RecoveryId::from_i32((byte % 4) as i32)
}

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

    // CompactSize (varint) encoder – equivalent 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 information = Vec::new();
    information.lengthen(varint_len(MAGIC));
    information.lengthen(varint_len(msg));
    sha256d::Hash::hash(&information)
}

/// Confirm a basic Bitcoin‑CLI / Electrum signed‑message **utilizing solely the `bitcoin` crate**.
///
/// * `address_str` – the handle that allegedly signed the message (Base58 `1…` or Bech32 `bc1…`).  
/// * `message`     – the precise clear‑textual content that was signed.  
/// * `sig_base64`  – the Base64 string printed by the pockets.
///
/// Returns `Okay(true)` if the signature is legitimate for the provided handle,
/// `Okay(false)` whether it is syntactically right however does **not** match,
/// and `Err(_)` for malformed inputs (dangerous Base64, improper size, unsupported handle sort, and so on.).
pub fn verify_signed_message(
    address_str: &str,
    message: &str,
    sig_base64: &str,
) -> Consequence> {

    
    // --------------------------------------------------------------
    // 1️⃣ Decode the Base64 signature (should be precisely 65 bytes)
    // --------------------------------------------------------------
    let sig_bytes = decode(sig_base64.trim())?;
    if sig_bytes.len() != 65 {
        return Err(format!("Signature should be 65 bytes (acquired {})", sig_bytes.len()).into());
    }
   println!("c111heckingadfdsads for handle");
    // --------------------------------------------------------------
    // 2️⃣ Cut up restoration 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️⃣ Construct 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️⃣ Get better the general public key
    // --------------------------------------------------------------
    // `Secp256k1::verification_only()` provides us a learn‑solely 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 handle");
    // --------------------------------------------------------------
    // 6️⃣ Parse the provided handle (this additionally tells us the community)
    // --------------------------------------------------------------
    let supplied_addr: Deal with = address_str.parse::<:address>>().unwrap().assume_checked();
    println!("checking for handle");
    // --------------------------------------------------------------
    // 7️⃣ Re‑derive the handle from the recovered public key
    // --------------------------------------------------------------
    let derived_addr = match supplied_addr.payload {
        // ---------- Legacy Base58 (P2PKH) ----------
        Payload::PubkeyHash(_) => {
            // `p2pkh` mechanically makes use of the compressed kind if the secret's
            // compressed; the `is_compressed` flag we extracted earlier is simply
            // wanted for sanity‑checking, not for handle building.
            Deal with::p2pkh(&recovered_pub, supplied_addr.community)
        }

        // // ---------- Native SegWit v0 (bc1q…) ----------
        // Payload::WitnessProgram {
        //     model: 0,
        //     program: ref prog,
        // } if prog.len() == 20 => {
        //     // SegWit v0 at all times makes use of the **compressed** public key, regardless
        //     // of the flag within the signature.  The `is_compressed` boolean is
        //     // due to this fact irrelevant for handle reconstruction right here.
        //     Deal with::p2wpkh(&recovered_pub, supplied_addr.community)?
        // }

        // The rest (Taproot `bc1p…`, P2SH‑wrapped, multisig, and so on.)
        // will not be supported by the legacy signed‑message format.
        _ => {
            return Err(format!(
                "Legacy verification solely helps P2PKH (1…) and native SegWit v0 (bc1q…) 
                 addresses. Deal with `{}` is of a special sort.",
                address_str
            )
            .into())
        }
    };
    println!("{:?}", derived_addr);
    println!("{:?}", supplied_addr);
    // --------------------------------------------------------------
    // 8️⃣ Examine the derived handle with the provided one
    // --------------------------------------------------------------
    Okay(derived_addr == supplied_addr)
}
}

Can anybody inform me why this code is not working? I’ve checked bitcoin-cli verifymessage and returned true. The Rust code is returning false. I am utilizing a P2PKH handle. Signing with the Sparrow pockets.

Tags: RustsignatureVerificationverify
Share76Tweet47

Related Posts

Musk’s SpaceX Breaks Under Its $135 IPO Value After a 42% Collapse From Its Peak

Musk’s SpaceX Breaks Under Its $135 IPO Value After a 42% Collapse From Its Peak

by Coininsight
July 17, 2026
0

Key TakeawaysSPCX closed at $131.11 on July 16, down 3.08% and under its $135 IPO worth for the primary time.SpaceX...

Visa Stablecoin Platform Launches for Banks, Fintechs

Visa Stablecoin Platform Launches for Banks, Fintechs

by Coininsight
July 17, 2026
0

Visa unveiled the Visa Stablecoin Platform (VSP), a brand new product that lets banks, fintechs and crypto companies mint, transfer...

smooth fork – Why does BIP-110 require a 55% signaling threshold if its nodes reject non-signaling blocks?

smooth fork – Why does BIP-110 require a 55% signaling threshold if its nodes reject non-signaling blocks?

by Coininsight
July 16, 2026
0

A compulsory signaling interval solely occurs if miners have not already locked within the activation by way of voluntary signaling....

Binance $800K XRP Airdrop: RLUSD Holders Qualify

Binance $800K XRP Airdrop: RLUSD Holders Qualify

by Coininsight
July 16, 2026
0

In main information as we speak, Binance has reportedly launched an $800,000 XRP reward marketing campaign working till August 14,...

Kraken API Accomplice Program Introduces Developer Improve Options

Kraken API Accomplice Program Introduces Developer Improve Options

by Coininsight
July 16, 2026
0

Trusted Editorial content material, reviewed by main trade consultants and seasoned editors. Advert Disclosure Crypto doesn't transfer on one type...

Load More
  • Trending
  • Comments
  • Latest
MetaMask Launches An NFT Reward Program – Right here’s Extra Data..

MetaMask Launches An NFT Reward Program – Right here’s Extra Data..

July 24, 2025
Finest Bitaxe Gamma 601 Overclock Settings & Tuning Information

Finest Bitaxe Gamma 601 Overclock Settings & Tuning Information

November 26, 2025
Easy methods to Host a Storj Node – Setup, Earnings & Experiences

Easy methods to Host a Storj Node – Setup, Earnings & Experiences

March 11, 2025
BitHub 77-Bit token airdrop information

BitHub 77-Bit token airdrop information

February 6, 2025
Kuwait bans Bitcoin mining over power issues and authorized violations

Kuwait bans Bitcoin mining over power issues and authorized violations

2
The Ethereum Basis’s Imaginative and prescient | Ethereum Basis Weblog

The Ethereum Basis’s Imaginative and prescient | Ethereum Basis Weblog

2
Unchained Launches Multi-Million Greenback Bitcoin Legacy Mission

Unchained Launches Multi-Million Greenback Bitcoin Legacy Mission

1
Earnings Preview: Microsoft anticipated to report larger Q3 income, revenue

Earnings Preview: Microsoft anticipated to report larger Q3 income, revenue

1
Visa Introduces New Platform for Stablecoin with Open USD

Visa Introduces New Platform for Stablecoin with Open USD

July 17, 2026
Supporting Ethereum’s Shopper Ecosystem | Ethereum Basis Weblog

Supporting Ethereum’s Shopper Ecosystem | Ethereum Basis Weblog

July 17, 2026
Crypto.com Secures $400M Funding From Citadel Securities At $20B Valuation

Crypto.com Secures $400M Funding From Citadel Securities At $20B Valuation

July 17, 2026
XRP att dominera Japans banksystem med 80% antagande

XRP att dominera Japans banksystem med 80% antagande

July 17, 2026

CoinInight

Welcome to CoinInsight.co.uk – your trusted source for all things cryptocurrency! We are passionate about educating and informing our audience on the rapidly evolving world of digital assets, blockchain technology, and the future of finance.

Categories

  • Bitcoin
  • Blockchain
  • Crypto Mining
  • Ethereum
  • Future of Crypto
  • Market
  • Regulation
  • Ripple

Recent News

Visa Introduces New Platform for Stablecoin with Open USD

Visa Introduces New Platform for Stablecoin with Open USD

July 17, 2026
Supporting Ethereum’s Shopper Ecosystem | Ethereum Basis Weblog

Supporting Ethereum’s Shopper Ecosystem | Ethereum Basis Weblog

July 17, 2026
  • About
  • Privacy Poilicy
  • Disclaimer
  • Contact

© 2025- https://coininsight.co.uk/ - All Rights Reserved

No Result
View All Result
  • Home
  • Bitcoin
  • Ethereum
  • Regulation
  • Market
  • Blockchain
  • Ripple
  • Future of Crypto
  • Crypto Mining

© 2025- https://coininsight.co.uk/ - All Rights Reserved

Social Media Auto Publish Powered By : XYZScripts.com
Verified by MonsterInsights