from Hacker News

The SHA256 for this sentence begins with: one, eight, two, a, seven, c and nine.

by isp on 9/11/23, 10:08 AM with 143 comments

  • by oefrha on 9/11/23, 4:06 PM

    Since I'm slacking off, here's a straightforward, not at all optimized Go implementation:

      package main
      
      import (
          "bytes"
          "crypto/sha256"
          "encoding/hex"
          "fmt"
      )
      
      var (
          _chars = []byte("0123456789abcdef")
          _names = []string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "a", "b", "c", "d", "e", "f"}
          _size  = len(_chars)
      )
      
      func main() {
          hexsum := make([]byte, 64)
          for i1 := 0; i1 < _size; i1++ {
              for i2 := 0; i2 < _size; i2++ {
                  for i3 := 0; i3 < _size; i3++ {
                      for i4 := 0; i4 < _size; i4++ {
                          for i5 := 0; i5 < _size; i5++ {
                              for i6 := 0; i6 < _size; i6++ {
                                  for i7 := 0; i7 < _size; i7++ {
                                      s := fmt.Sprintf("The SHA256 for this sentence begins with: %s, %s, %s, %s, %s, %s and %s.", _names[i1], _names[i2], _names[i3], _names[i4], _names[i5], _names[i6], _names[i7])
                                      sum := sha256.Sum256([]byte(s))
                                      hex.Encode(hexsum, sum[:])
                                      prefix := []byte{_chars[i1], _chars[i2], _chars[i3], _chars[i4], _chars[i5], _chars[i6], _chars[i7]}
                                      if bytes.HasPrefix(hexsum, prefix) {
                                          fmt.Printf("%s\n", s)
                                          fmt.Printf("%s\n", hexsum)
                                      }
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }
    
    Takes a few minutes on common consumer hardware. There's exactly one hit.

    (Easiest optimization is wrapping the loop body in a goroutine. GOEXPERIMENT=loopvar really makes this nicer btw.)

    The reply is obviously more interesting, need to come up with a lot of variations.

  • by rawling on 9/11/23, 10:17 AM

    > Was just verifying your tweet's hash, and then...omg!!! I couldn't believe what I realised. The SHA256 of THIS tweet starts with exactly the same 7 characters as your tweet's hash. What are the chances of that?

    As always, the real WTF is in the comments.

  • by gtrubetskoy on 9/11/23, 3:49 PM

    The original from July 2019 https://twitter.com/humblehack/status/1088982929940848647

    $ echo -n 'The SHA256 for this sentence begins with seven, seven, f, zero, a, b, b and five.' | sha256sum 77f0abb54cd09ad7b654bd5e762d7be58e7daffd1a0da6a56f5135bd667856a3 -

  • by Someone on 9/11/23, 10:36 AM

    That’s 28 bits. Loop through 256 million of these strings, and you’re bound to find a hit.

    Bitcoin difficulty is at around 50 bits (https://ycharts.com/indicators/bitcoin_average_difficulty#:~....)

    It also uses SHA256.

    So, if my logic is right (is it? That seems awfully cheap to me), this is about 2^22 times as easy as mining a bitcoin. Bitcoin is at about $25k, so there are people who can find hits like this one for way less than a cent.

  • by nneonneo on 9/11/23, 10:24 PM

    Well, I got bored too, so here's some results with CUDA (on an RTX 3090):

        The SHA256 hash of this message begins with 534d765
        The SHA256 hash of this message begins with c18b2de
        The SHA256 hash of this message begins with 7fe17da2
        The SHA256 hash of this message begins with a7fdc855d
        The SHA256 hash of this message begins with 46eae34f1
    
    My unoptimized implementation takes about 40s for 9 digits, so it will probably take about 10 minutes for 10 digits, about 3 hours for 11 digits, etc. It shouldn't be hard to use words instead of hex digits, if that's desired.
  • by curtisf on 9/11/23, 5:13 PM

    A semi-useful variant of this technique was posted nine months ago on Hacker News:

    https://news.ycombinator.com/item?id=33704297

    Generating sequential Git short commits! It's so pleasant looking I'm tempted to try using it one of my projects, but deep down I know it's not worth the hassle.

  • by jph on 9/11/23, 8:54 PM

    Rust implementation...

    The code searches permutations of increasing length. Benchmark is 8 seconds on a MacBook Pro M1 to discover the match of 182a7c9. The code is not yet optimized.

        use std::time::SystemTime;
        use itertools::Itertools;
        use sha256::digest;
    
        fn main() {
            let digits: [usize; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
            let chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
            let words = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "a", "b", "c", "d", "e", "f"];
            let mut length = 2;
            let start = SystemTime::now();
            loop {
                for permutation in digits.iter().permutations(length) {
                    let parts = permutation.iter().map(|x| words[**x]).collect_vec();
                    let sentence = format!(
                        "The SHA256 for this sentence begins with: {} and {}.",
                        &parts[0..(parts.len() - 1)].join(", "), 
                        &parts[parts.len() - 1]
                    );            
                    let checksum: String = digest(&sentence);
                    let starts: String = permutation.iter().map(|x| chars[**x]).collect();
                    if checksum.starts_with(&starts) {
                        println!("milliseconds: {:?}, {} ", start.elapsed().unwrap().as_millis(), &sentence);
                    }
                };
                length += 1;
            }
        }
    
    Output:

        milliseconds: 3, The SHA256 for this sentence begins with: zero, b, six and two. 
        milliseconds: 54, The SHA256 for this sentence begins with: zero, e, d, eight and f. 
        milliseconds: 8279, The SHA256 for this sentence begins with: one, eight, two, a, seven, c and nine.
    
    Repository:

    https://github.com/joelparkerhenderson/sha256-sentence

  • by skilled on 9/11/23, 10:19 AM

    It appears to have been taken from here,

    https://news.ycombinator.com/item?id=19003644 (2019)

  • by mgdm on 9/11/23, 7:28 PM

    Something that I'm not seeing mentioned in these comments (I may just have missed it) is that you can precompute the hash of the static part of the string and then extend it with the numbers in a loop, saving some cycles. This is because the full hex representation of a SHA hash gives you the entire internal state of the algorithm. This can lead to security vulnerabilities:

    https://en.m.wikipedia.org/wiki/Length_extension_attack

  • by chriskw on 9/11/23, 5:51 PM

    I did something similar once (with a bit of a twist) for my bio when I was a TA in college:

    "Hi! I’m a senior studying CS. My hobbies include making semantic paradoxes and my bio includes eight a’s, seventeen e’s, fourteen i’s, eight o’s, six u’s, and one wrong number"

  • by isp on 9/11/23, 10:09 AM

        $ echo -n "The SHA256 for this sentence begins with: one, eight, two, a, seven, c and nine." | sha256sum
        182a7c930b0e5227ff8d24b5f4500ff2fa3ee1a57bd35e52d98c6e24c2749ae0  -
  • by siraben on 9/12/23, 5:05 AM

    With some clever information hiding, you can sort of mask the brute force:

      On 2015/7/6 at 00:00, I wrote this message's hash down. It started with 1337.
    
      Thought #335552803: I love beef so much I made sure the sha256 of this message started with 0xbeef!
    
    A longer example:

      $ cat predestination.txt 
      (1991/4/7 at 00:16) <siraben> I know the hash of this message before you do!
      (1991/4/7 at 00:17) <larsivi> Huh. What is it?
      (1991/4/7 at 00:18) <siraben> It starts with 1337.
    
      $ sha256sum predestination.txt
      1337a4654163ab48761bf8acc75a407179e700f67f97d754b08c7afeac7da70a  predestination.txt
  • by omoikane on 9/11/23, 5:03 PM

    Related, here is a program that prints its own SHA-512 hash:

    https://www.ioccc.org/years.html#2019_diels-grabsch2

  • by danbruc on 9/11/23, 8:13 PM

    After picking some scheme to generate messages that predict n bits of their hash in some form, the chance of finding at least one message that correctly predicts its hash is 1 - (1 - 1/x)^x where x is 2^n. This approaches 1 - 1/e = 63.2 % for large n. So by trying a few different schemes, for example slightly varying the prefix »The SHA256 for this sentence begins with:«, it becomes quickly very likely to succeed. In the limit of large n, for example only 5 different schemes will yield at least one correct message with 99 %.

    With 5 patterns, 24 bits and SHA-1.

      The SHA-1 hash of this text starts with 051E35.
      The hash of this text starts with A943BD.
      The SHA-1 hash of this text starts with B6640C.
      The SHA-1 hash of this message starts with C3B03D.
      The SHA-1 hash of this message starts with D93717.
    
    Or the same as before but as patterns just padding the 6 hex digits with zero zero to eight dots.

      0AF3DE..
      2AF7DF.......
      3E0E50.
      8EE84C.....
      919025...
      A57198....
      B20775.....
      DA525A........
      ED20F4..
  • by olafalo on 9/11/23, 9:01 PM

    Well, this nerd sniped me... I made a quick Go tool for this. You simply write a string {like|this}, and then it finds a hash with the same prefix automatically. (Hash this comment, it's also 182a7c9)
  • by nneonneo on 9/11/23, 9:19 PM

    I bet you could hack hashcat (or just use CUDA) to find these quickly for larger prefixes. Might make a fun (silly) challenge. Hashcat can do 21B SHA256 hashes per second on an RTX 4090; this translates into bruteforcing a 9-digit prefix in 4 seconds, a 10-digit prefix in 52 seconds, or a 11-digit prefix in about 14 minutes.
  • by SethTro on 9/11/23, 10:41 PM

    Took less than a minute to find a seven digit example in python

    The SHA-256 of this sentence begins with 0, three, 9, four, 8, four, and 1 amazing!

    The SHA256 for this sentence begins with 0, 4, five, 5, eight, 6, and 7 amazing!

    Suffix extensions (hence the "amazing!") are several times faster to try than throwing away the entire sha256 state for each attempt.

  • by pontifier on 9/11/23, 7:23 PM

    This is similar to the vanity address generation for Bitcoin and other cryptocurrency addresses.
  • by dragontamer on 9/12/23, 5:23 AM

    28 bits of entropy? That's definitely within brute-force regions with CPU. Possibly even single-threaded CPU honestly.

    -------

    GPU-level brute force is pushing ~40-bits. Assuming ~1 week of solid compute, a 6 TFlop computer has ~3.7 sextillion compute cycles. Or alternatively, that's ~3 billion clock cycles (single thread) per check to reach 2^40 bits of entropy. More than easily doable for most simple brute-force computational problems IMO.

    If you go multi-GPU on top of that, you'll have even more computational work available.

  • by ms0 on 9/15/23, 5:31 PM

    Beneath the veil of binary territories, in a subtle symphony of stillness, sevenfold zeros rise and conjure a calm masterpiece. As if celestial beacons in an ethereal night sky, they materialize in the form of an arcanum with heptadic serenity, with divine grace.
  • by istjohn on 9/12/23, 3:42 AM

    I now see that eyeballing the first and/or last few characters of a checksum is not going to detect a skillfully altered executable or ISO.
  • by Obscurity4340 on 9/11/23, 10:07 PM

    Dumb question but what are the implications here? Is this problematic⌨ or is it more of an Easter egg?
  • by lionkor on 9/12/23, 6:07 AM

    You would get more possibilities if you allowed "eighteen" instead of "one, eight"
  • by sagebird on 9/13/23, 6:15 PM

    I made https://lowhash.com to collect string with low hashes.

    I am not sure who submitted "byzBLFAM4Penguin"...

  • by kif on 9/11/23, 6:40 PM

    Whereas the SHA256 for this sentence begins with: five, three, e, two, one, f and e.
  • by Alifatisk on 9/12/23, 10:52 AM

  • by Ekaros on 9/11/23, 8:18 PM

    Now a SHA256 hash that hashes to itself would be more interesting.
  • by nabla9 on 9/11/23, 5:20 PM

    Would you believe in God if sha256 of "I am God. My name is BOB " would be 4920616D20476F642E204D79206E616D6520697320424F4220202020202020 (the text in hex)?
  • by Gunnerhead on 9/11/23, 3:00 PM

    I’m not sure I understand the significance. Can anyone explain?
  • by narcindin on 9/11/23, 6:08 PM

    This is cool. Isn't finding these the same as minting a new block of bitcoin? So definitially hard using our best understanding of algorithms, math, etc.
  • by bizzleDawg on 9/11/23, 4:32 PM

    It's way above my head mathematically as to if this is even possible, but it is hilarious how screwed so many things would be if sha256 was discovered to have a means to more quickly reverse at least a partial hash. Just off the top of my head:

      - SSL
      - Bitcoin (bonus: unlimited money hack if you can keep the discovery under wraps)
      - Signed updates for devices
    
    Goodness only knows what I am missing, but that first one along is enough to cause an unmitigated disaster.

    I assume these tweets are effectively brute forced given the fairly short prefix though and we're all safe

  • by grantmnz on 9/12/23, 12:41 AM

  • by nuancebydefault on 9/11/23, 7:07 PM

    It took some time for me to sink in why no explanation was needed. Is there a general term for such a thing, self-reflection or something the like?
  • by wholesomepotato on 9/11/23, 4:37 PM

    This is only 7 * 4 bits. That's really nothing.
  • by matt3210 on 9/11/23, 7:09 PM

    Why is X covering code as “sensitive material”?
  • by PaulHoule on 9/11/23, 4:52 PM

    You have to try like what, 2^24 ~ 16 million sentences to make that work?
  • by ms0 on 9/15/23, 5:27 PM

    sha-256 of the above is 182a7c95ae9e1149eb48f0f5eedee0a184764a45e8a2cb5d986b7c57c9a42022
  • by Uptrenda on 9/11/23, 11:58 PM

    It's like a human-readable PoW, lol.
  • by fleekonpoint on 9/11/23, 8:22 PM

    Reminds me of this xkcd:

    https://xkcd.com/917/

  • by kjrose on 9/11/23, 3:46 PM

    Yay pigeon-hole principle combined with birthday attack.
  • by kazinator on 9/11/23, 2:58 PM

    In this game, the rules should be that the digit 9 counts as either "nine" and "quine".