Re: The SHA256 of "xy\n" (ASCII, no CRLF) contains 1337, ACBAD in za, and I am 1aa
- From
- Klaus Sembritzki <klausem@gmail.com>
- Date
- Jan 25, 2026, 11:25 UTC
- Message-ID
- <CADMnYXDBSTDHynvVcpfpU79V=BXNOksi1W0pHFRWgZBkqTf5Hw@mail.gmail.com>
- In-Reply-To
- <CADMnYXAF5VV9jKbxm1rduR-x96TFEso572zCAVOU-JoMpnX1tg@mail.gmail.com>
On Sun, Jan 25, 2026 at 10:47 AM Klaus Sembritzki <klausem@gmail.com> wrote:
Show 185 quoted lines
>
> On Sat, Jan 24, 2026 at 10:25 AM Klaus Sembritzki <klausem@gmail.com> wrote:
> >
> > On Sat, Jan 24, 2026 at 8:28 AM Jeff King <peff@peff.net> wrote:
> > >
> > > On Fri, Jan 23, 2026 at 02:36:41PM -0800, Junio C Hamano wrote:
> > >
> > > > Jeff King <peff@peff.net> writes:
> > > >
> > > > > On Fri, Jan 23, 2026 at 09:16:46PM +0100, Klaus Sembritzki wrote:
> > > > >
> > > > >> $ # My initials (ks): 1aa
> > > > >> $ echo ks | sha256sum
> > > > >> $ 1aa44e718d5bc9b7ff2003dbbb6f154e16636d5c2128ffce4751af5124b65337
> > > > >>
> > > > >> $ # 50566750337
> > > > >> $ echo thinking | sha256sum
> > > > >> $ 50566750337beb9e98e553fd9196d10576f9eb0cbc6b66e2586b9d73af4f352f
> > > > >
> > > > > Oh man, I've got deadbeef!
> > > > >
> > > > > $ echo jk35252822 | sha256sum
> > > > > 33f1a74529870456c56ad97c59cfed6bdeadbeef9b9bc3f4ff49bb203e36f96b
> > > > >
> > > > > What could it all mean?
> > > >
> > > > Sorry, but I have to admit that I completely lack humor receptor
> > > > cells.
> > >
> > > Probably because it was not that funny. :)
> > >
> > > The original message seemed to be looking for Numerology-style meanings
> > > in random data. I wasn't sure if it was serious or not, but I could not
> > > resist either playing along (if not) or trolling (if so).
> > >
> > > But here's my deadbeef brute-force program for fun.
> > >
> > > -Peff
> > >
> > > -- >8 --
> > > #include <stdio.h>
> > > #include <string.h>
> > > #include <openssl/evp.h>
> > >
> > > int main(int argc, const char **argv)
> > > {
> > > const char needle[] = { 0xde, 0xad, 0xbe, 0xef };
> > > const EVP_MD *algo = EVP_sha256();
> > > EVP_MD_CTX *ctx = EVP_MD_CTX_new();
> > >
> > > EVP_DigestInit_ex(ctx, algo, NULL);
> > > while (*++argv)
> > > EVP_DigestUpdate(ctx, *argv, strlen(*argv));
> > >
> > > for (unsigned i = 0; ; i++) {
> > > char buf[16];
> > > char *p;
> > > unsigned char digest[32];
> > > EVP_MD_CTX *copy = EVP_MD_CTX_dup(ctx);
> > >
> > > p = buf + sizeof(buf);
> > > for (unsigned v = i; v; v /= 10)
> > > *--p = '0' + (v % 10);
> > > EVP_DigestUpdate(copy, p, buf + sizeof(buf) - p);
> > > EVP_DigestUpdate(copy, "\n", 1);
> > > EVP_DigestFinal_ex(copy, digest, NULL);
> > > EVP_MD_CTX_free(copy);
> > > if (memmem(digest, sizeof(digest), needle, sizeof(needle)))
> > > printf("%d\n", i);
> > > }
> > > }
> >
> > Incrementing the MSB instead of the LSB (indexing naturally starts
> > with 1 in that case) seems to improve the performance, and it finds
> > different solutions, if the program is terminated early.
> > The rationale is that there is autocorrelation in the observations,
> > though I cannot judge what that means in this concrete example. The
> > speedup is not that dramatic here, so SHA256 seems to be pretty
> > random.
> >
> > #include <stdio.h>
> > #include <string.h>
> > #include <stdint.h>
> > #include <openssl/evp.h>
> >
> > #ifdef POLYFILL
> > EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in)
> > {
> > EVP_MD_CTX *out = EVP_MD_CTX_new();
> >
> > if (out != NULL && !EVP_MD_CTX_copy_ex(out, in)) {
> > EVP_MD_CTX_free(out);
> > out = NULL;
> > }
> > return out;
> > }
> > #endif
> >
> > #define REVERTED_BIT(n, position, width) (((n & (1 << position)) >>
> > position) << (width - position - 2))
> >
> > uint32_t revert_bits(uint32_t n, uint32_t width) {
> > uint32_t result = 0;
> > for (uint32_t i = 0; i < width; ++i) {
> > result |= REVERTED_BIT(n, i, width);
> > }
> > return result;
> > }
> >
> > int main(int argc, const char **argv)
> > {
> > const char needle[] = { 0xde, 0xad, 0xbe, 0xef };
> > const EVP_MD *algo = EVP_sha256();
> > EVP_MD_CTX *ctx = EVP_MD_CTX_new();
> >
> > EVP_DigestInit_ex(ctx, algo, NULL);
> > while (*++argv)
> > EVP_DigestUpdate(ctx, *argv, strlen(*argv));
> >
> > for (uint32_t n = 1; ; n++) {
> > #if (COUNTER_WIDTH != 0)
> > uint32_t i = revert_bits(n, COUNTER_WIDTH);
> > #else
> > uint32_t i = n;
> > #endif
> > // printf("%u %u\n", n, i);
> > char buf[16];
> > char *p;
> > unsigned char digest[32];
> > EVP_MD_CTX *copy = EVP_MD_CTX_dup(ctx);
> >
> > p = buf + sizeof(buf);
> > for (uint32_t v = i; v; v /= 10)
> > *--p = '0' + (v % 10);
> > EVP_DigestUpdate(copy, p, buf + sizeof(buf) - p);
> > EVP_DigestUpdate(copy, "\n", 1);
> > EVP_DigestFinal_ex(copy, digest, NULL);
> > EVP_MD_CTX_free(copy);
> > if (memmem(digest, sizeof(digest), needle, sizeof(needle)))
> > {
> > printf("counter width: %2u | n: %10u | i: %10u\n",
> > COUNTER_WIDTH, n, i);
> > return 0;
> > }
> > }
> > return 1;
> > }
> >
> > cc -DPOLYFILL -DCOUNTER_WIDTH=32 jk_evp.c -lssl -lcrypto -o jk_evp_msb_32
> > cc -DPOLYFILL -DCOUNTER_WIDTH=31 jk_evp.c -lssl -lcrypto -o jk_evp_msb_31
> > cc -DPOLYFILL -DCOUNTER_WIDTH=30 jk_evp.c -lssl -lcrypto -o jk_evp_msb_30
> > cc -DPOLYFILL -DCOUNTER_WIDTH=29 jk_evp.c -lssl -lcrypto -o jk_evp_msb_29
> > cc -DPOLYFILL -DCOUNTER_WIDTH=0 jk_evp.c -lssl -lcrypto -o jk_evp_0
> > counter width: 32 | n: 103832253 | i: 1588397616
> > counter width: 31 | n: 62413559 | i: 1003915120
> > counter width: 30 | n: 166340413 | i: 396135154
> > counter width: 29 | n: 137077701 | i: 171728193
> > counter width: 0 | n: 171728193 | i: 171728193
>
> I have to admit there is a bug in my previous code, it only works
> correctly for even numbers. It should have been:
>
> #define REVERTED_BIT(n, position, width) (((n & (1 << position)) >>
> position) << (width - position - 2 + (width & 1)))
>
> uint32_t revert_bits(uint32_t n, uint32_t width) {
> uint32_t result = 0;
> for (uint32_t i = 0; i < width; ++i) {
> result |= REVERTED_BIT(n, i, width);
> }
> return result;
> }
>
> The actual performance measurements are:
> counter width: 32 | n: 103832253 | i: 1588397616
> counter width: 31 | n: 103832253 | i: 1588397616
> counter width: 30 | n: 166340413 | i: 396135154
> counter width: 29 | n: 166340413 | i: 396135154
> counter width: 28 | n: 268041599 | i: 2281045247 # 2**28 is close to
> the first finding when counting by incrementing the LSB, so this is
> slow.
> counter width: 27: This does not find anything, because 2**27 is lower
> than the first finding when counting by incrementing the LSB.
> counter width: 0 | n: 171728193 | i: 171728193 #
> math.log2(171728193) = 27.35555166834193As an interim solution, it could make sense to leave small input unmodified, and to permute large texts to get rid of the natural language manifold.