0
long nonce;
String message = "blahblabahlsdhqwi";
String digest = digest("SHA-256", String + nonce);
byte[] digestBytes = digest.getBytes();

I'm trying to hash through a message whilst incrementing a nonce until I find a digest that has the first 4 bytes that are 0's. How can I do this?

Chimp_Town
  • 185
  • 1
  • 3
  • 14
  • 3
    A `String` consists of *characters*, not *bytes*, and it definitely shouldn't contain bytes with value `\x00`. Now, if you're referring to the character `'0'`, aka, `\u0030`, that would be different. Anyway, if you have stored byte data in a `String`, you should **seriously** reconsider the logic of your `digest()` method. – Andreas May 20 '17 at 15:37
  • Even if i used this, would it still take a very long time to find a digest with the first byte == 0? `public static byte[] digestToByte(String alg, byte[] bytes) throws Exception { MessageDigest md = MessageDigest.getInstance(alg); byte[] buffer = bytes; md.update(buffer); byte[] digest = md.digest(); return digest; }` – Chimp_Town May 20 '17 at 16:14
  • 1
    Testing the first 4 bytes of a byte array for 0 is extremely fast, so I'm not sure what you're asking. Are you trying to brute-force find a payload that will produce a SHA-256 digest starting with 4 zero-bytes? – Andreas May 20 '17 at 20:36
  • Yes but even finding the first byte == 0 is taking forever when I too thought it would've been quick. – Chimp_Town May 21 '17 at 04:34

2 Answers2

3

It took me about two and a half minutes to find: "blahblabahlsdhqwi164370510". I checked it online and that confirmed the hash:

000000007bb0d5ef7b63faaad076fe505a112a485c83ca25af478ea1f81e33d5

My code looks like:

public static void main(String[] args) throws UnsupportedEncodingException {

    // I use Bouncy Castle.
    SHA256Digest SHA = new SHA256Digest();

    byte[] digest = new byte[32];

    byte[] textBytes;

    long nonce = 0L;

    String message = "blahblabahlsdhqwi";

    boolean found;

    do {

        // Calculate digest.
        textBytes = (message + nonce).getBytes("UTF-8");
        SHA.update(textBytes, 0, textBytes.length);
        SHA.doFinal(digest, 0);

        // Check for 4 zeros.
        found = digest[0] == 0 && digest[1] == 0 && digest[2] == 0 && digest[3] == 0;

        // Try next nonce.
        ++nonce;

    } while (!found);

    System.out.println("Found at: SHA256(" + message + (nonce - 1L) +")");

    System.out.println("SHA256 digest = " + Arrays.toString(digest));

} // end main()
rossum
  • 15,344
  • 1
  • 24
  • 38
1

You could use an IntStream with a limit(n) (to take the first n numbers) and allMatch. Like,

int n = 4;
if (IntStream.range(0, digestBytes.length).limit(n)
        .allMatch(i -> digestBytes[i] == 0)) {
    // ...
}

or just

int n = 4;
if (IntStream.range(0, n).allMatch(i -> digestBytes[i] == 0)) {
    // ...
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 1
    It's only 4, so why not just `if (digestBytes.length >= 4 && digestBytes[0] == 0 && digestBytes[1] == 0 && digestBytes[2] == 0 && digestBytes[3] == 0)`? – Andreas May 20 '17 at 15:40
  • 1
    `if (ByteBuffer.wrap(digestBytes).getInt() == 0)` is another option. It's concise, but feels a bit excessive, though it's probably less overhead than using a stream. – Andreas May 20 '17 at 15:44
  • 1
    @Andreas I assumed the title of the question meant that `4` is an example, and it could also be the first `8` or first `32` byte(s) that should be `0`. – Elliott Frisch May 20 '17 at 16:28
  • 1
    Good point. I didn't notice the `n` in the title. --- Anyway, did you see [OPs comment](http://stackoverflow.com/questions/44087707/how-to-check-if-the-first-n-bytes-of-a-string-are-zeroes?noredirect=1#comment75198078_44087707): *"would it take a very long time to find a digest with the first byte == 0?"* If OP wants fast, a regular `for` loop would be better, but since it sounds to me like OP is trying to brute-force a digest with leading zeroes, the overhead of streams is minuscule compared to the digest generation, so it doesn't really matter. – Andreas May 20 '17 at 20:41