diff --git a/mnemonic-hash-checker/src/bloom.rs b/mnemonic-hash-checker/src/bloom.rs index 5f20b23..9e74905 100644 --- a/mnemonic-hash-checker/src/bloom.rs +++ b/mnemonic-hash-checker/src/bloom.rs @@ -2,7 +2,9 @@ use std::{fs::File, io::{BufReader, Read}, path::Path}; use color_eyre::eyre::Result; use bloomfilter::Bloom; +use tracing::info; +#[tracing::instrument] pub fn load(file: &Path) -> Result> { let file = File::open(file)?; let length = file.metadata().unwrap().len(); @@ -31,9 +33,11 @@ pub fn load(file: &Path) -> Result> { (u64::from_be_bytes(sk10), (u64::from_be_bytes(sk11))), ]; + info!("Reading {length} bytes into memory"); let mut bitmap = vec![0; (length - 8 - 4 - 32) as usize]; buf.read_exact(&mut bitmap)?; + info!("Generating bloom filter from loaded bitmap"); Ok(Bloom::from_existing( &bitmap, number_of_bits, diff --git a/mnemonic-hash-checker/src/index.html b/mnemonic-hash-checker/src/index.html index cb2febe..7fd1f8d 100644 --- a/mnemonic-hash-checker/src/index.html +++ b/mnemonic-hash-checker/src/index.html @@ -18,11 +18,67 @@
-

MilkSad Lookup Service

+

Milk Sad Lookup Service

- Query a SHA256 hash of your mnemonic phrase. DO NOT ENTER your - mnemonic phrase in cleartext. To generate a hash of your mnemonic, use: - echo -n "milk sad wage cup reward umbrella raven visa give list decorate broccoli" | sha256sum with your mnemonic. + To help people identify if they are impacted by Milksad, we are + providing a web service to check if your mnemonic is in the vulnerable + set. Note that this service only covers mnemonics impacted by + Libbitcoin Explorer (bx) versions 3.0.0 to + 3.6.0, though it may be updated over time to cover other + related vulnerabilities we are researching. +

+ +

Who should use this tool?

+
    +
  • + If you know you generated your wallet with bx 3.0.0 or + higher (after March 2017) +
  • +
  • + If you know you generated your wallet with a CLI tool, but don't + remember which tool. +
  • +
+ +

What do the results mean?

+
    +
  • + Vulnerable means that we are 99.99% sure your mnemonic is vulnerable + to being brute forced. You should recreate your mnemonic and move + your funds. +
  • +
  • + Match Not Found means that we do not have a record of your mnemonic, + but it does not mean it may not be impacted by other issues. If you + are not certain your wallet is secure, you may consider changing + regardless. +
  • +
+ +

Security and Privacy

+

+ We do not want to store BIP39 mnemonics for this lookup service, or + have people submit their BIP39 mnemonic private keys to us, so we had + to sacrifice the user experience to provide this service safely. Our + server contains SHA256 hashes of all currently known vulnerable + mnemonics, so you can submit the SHA256 hash of your own mnemonic and + see if it is in our set. +

+

+ Please note that it is usually a very bad idea to follow + invitations from strangers on the internet when it comes to sharing + something about your wallet private keys. Typically they are scammers + with bad intentions. We're aware of this and want to avoid being a poor + example, so we decided to avoid including a convenient HTML input field + to do the hashing for you (and could steal your mnemonic in the + process). Users must bring their own SHA256 hash of their mnemonic + ideally calculated in their own offline machine. If other people offer + a similar lookup service, especially one that accepts a mnemonic as + input, please be very cautious. +

+

+ For those wishing to limit metadata sent to us or our service provider, + we encourage using Whonix/Tor.

diff --git a/mnemonic-hash-checker/src/main.rs b/mnemonic-hash-checker/src/main.rs index b369e59..b57ca3c 100644 --- a/mnemonic-hash-checker/src/main.rs +++ b/mnemonic-hash-checker/src/main.rs @@ -7,7 +7,7 @@ use axum::{ http::{header::CONTENT_TYPE, StatusCode}, response::{AppendHeaders, IntoResponse}, routing::get, - Json, Router, + Router, }; use bloomfilter::Bloom; @@ -76,13 +76,11 @@ struct CheckQuery { async fn check_hash_slug( query: Query, State(state): State>, -) -> (StatusCode, Json) { - let result = check_hash(&query.sha256, &state).await; - let status_code = match state.bloom_filter.check(&query.sha256.to_string()) { - true => StatusCode::OK, - false => StatusCode::NOT_FOUND, - }; - (status_code, Json(result)) +) -> (StatusCode, &'static str) { + match state.bloom_filter.check(&query.sha256.to_string()) { + true => (StatusCode::OK, "vulnerable"), + false => (StatusCode::NOT_FOUND, "match not found") + } } #[tokio::main] @@ -108,7 +106,7 @@ async fn main() -> Result<()> { .layer(CatchPanicLayer::new()) .layer(TraceLayer::new_for_http()); - info!("server go nyoom"); + info!("server go nyoom: {addr}"); axum::Server::bind(&addr) .serve(app.into_make_service())