[HN Gopher] Show HN: SHA-256 explained step-by-step visually ___________________________________________________________________ Show HN: SHA-256 explained step-by-step visually Author : manceraio Score : 834 points Date : 2022-02-07 13:31 UTC (9 hours ago) (HTM) web link (sha256algorithm.com) (TXT) w3m dump (sha256algorithm.com) | DJPocari wrote: | This is fantastic. I once implemented SHA-256 in Google Sheets to | visualize it, but it had horrible performance compared to this. | This is the best visualization I've seen yet. | daenz wrote: | You should be very satisfied with how well you conveyed the | algorithm. Well done. What was your approach to arriving at this | result? | manceraio wrote: | Thanks :) I first implemented sha256 in js to understand its | inner workings. Then I started displaying its variables with | react and adding this stepped mechanism. Finally, I added some | notes on the left to add some context of what is going on. | daenz wrote: | Very nice. Have you built any other algorithm visualizations? | I have a very strong interest in how algorithms are | visualized so that they are more easily understood. | manceraio wrote: | First time doing this type of visualizations. I have this | one tailwind.ink which will visualize a color palette on | their luminance, chroma and hue values, but it's not really | representing the algorithm behind. | brk wrote: | How long before we see this website as the source for some | "hacker sequence" in a movie where a person wearing a black | hoodie states they are "... working on cracking their SHA-256 | encryption, should only take a sec." | can16358p wrote: | If such a movie even mentions SHA-256 I think that's above | average on its own. | breakingcups wrote: | That depends.. | | "Just a second, I need to backdoor the SHA256 rootkit to | penetrate the directory. Shit, they have an X62 firewall. | Luckily I brought my pentester." | skilled wrote: | "These packets are not going to sniff themselves." | reincarnate0x14 wrote: | Syntax-highlighted ALGOL-y code blocks seem to be back in style | if they're not going with the constant "toss that screen up to | a hologram" bit. | | Sometime there will be a nice interview of such on the design | that goes into that, not necessarily for "hacker sequences" but | general imaginary computer interfaces like | https://www.hudsandguis.com/home/2021/theexpanse . | Darkphibre wrote: | Man, this is amazing. I had to hand-unroll bit packing in a | binary encoding scheme we used in a game. Rare enough that making | a tool wasn't worth it, but damn I love your visualizations! | Doing something like that would have helped others understand how | I was "seeing the matrix." | hombre_fatal wrote: | Beautiful color palette. | mabbo wrote: | Before watching this: "Why can't cryptographers just figure out | some tricks to crack these hash algorithms?" | | After watching this: "How can any cryptographer EVER figured out | any trick to crack these hash algorithms?!" | sammyo wrote: | They can't. But there are certainly unsavory actors that are | able to trick a certain percentage of the unsuspecting to just | give them a private key. | selestify wrote: | They actually can, in some situations: | https://security.googleblog.com/2017/02/announcing-first- | sha... | mynameismon wrote: | > "How can any cryptographer EVER figured out any trick to | crack these hash algorithms?!" | | More so, "How can any cryptographer EVER figure out any trick | to come up with these hash algorithms?!" Seriously, they are | incredibly impressive mathematical algorithms. Even coming up | with an algorithm that is able to show the avalanche effect is | mind boggling. To make sure that the algorithm is not biased to | a set of samples AND shows the avalanche effect is tremendously | mind blowing. | userbinator wrote: | This reminds me that I've always wanted to make a huge | interactive combinatorial circuit that computes SHA-256 and shows | all its internal state, then put it on a site with the claim that | anyone who can make its output match a certain clearly- | constructed value (e.g. 0123456...ABCD...) will win a prize. No | mentions of hash algorithms or other such phrasing to deter | anyone. I wonder how many people would try such a "logic puzzle", | how much time they'd spend on it, and if we might even get the | first successful preimage attack from that. | jjeaff wrote: | I think making a problem more accessible like that is the | fastest path to a solution. | | It reminds me of the Stephen J Gould quote: | | "I am, somehow, less interested in the weight and convolutions | of Einstein's brain than in the near certainty that people of | equal talent have lived and died in cotton fields and | sweatshops." | manceraio wrote: | I actually started this because my first idea was: can I | implement SHA-256 with just TTL logic gates? which should be | possible, but it would take months to do. | | for puzzles try 12037465 for some coffee :) | stevofolife wrote: | Well made! Can you share how you made the website? | berta wrote: | This is awesome! | chris_l wrote: | Someone should make a collection of the various visualization web | projects that crop up here from time to time. | p1mrx wrote: | Can it be proven whether values of m exist such that SHA256(m) == | 0? | | If I were omnipotent and wanted people to believe in me, I would | write a book that hashes to 0, so that anyone could verify its | authenticity. | picture wrote: | You could in theory also get that with a lot of computation of | course | p1mrx wrote: | It should be straightforward to design a hash function that | can't be preimage attacked using all the computing power in | the universe. | | Maybe an omnipotent cryptographer would find flaws in | SHA-256, but then they could design a better function and | include it in the book. | kzrdude wrote: | Maybe their omnipotence includes being lucky enough | p1mrx wrote: | Why would an omnipotent being need luck? They have | infinite brute force. | orangepenguin wrote: | Maybe I'm being incredibly naive, but it seems like this would | be trivial. Can you just start with the output hash and then | essentially run the algorithms backwards? Obviously the | resulting "input" would be random-ish garbage, but it seems | like if all you care about is the output, you can pretty much | just "pick" any data for the last step that produces the | output. Then do likewise for the step prior, and so on. | arcastroe wrote: | As a comment above stated, part of the "input" is the | initialized values: | | > Initialize hash value h0 to h7: first 32 bits of the | fractional parts of the square roots of the first 8 primes | 2..19). | | My guess is h0 to h7 change throughout the algorithm. If you | perform each step in "reverse" as you suggest, "picking" any | input at each step that produces the required output for that | step, then you may not arrive to the correct initial state | with the square roots of the first 8 primes. | | You'll arrive at "random-ish garbage". | orangepenguin wrote: | Ah, yep. You're right. I overlooked that part. It looks | like it's truly non-reversible--even if you don't care what | the resulting input is. | p1mrx wrote: | If you do ever figure out how to reverse SHA-256, best | keep it a secret until you've sold all your free Bitcoin. | y42 wrote: | Sure, that would be a pretty high difficult factor, but its | possible. | p1mrx wrote: | But is it provably possible for SHA-256? | | An n-bit cryptographic hash function should _ideally_ cover | every n-bit output value, given slightly more than n bits of | input, but I don 't know whether this has been proven for any | real-world functions. | [deleted] | pbsd wrote: | A hash function aims to replicate the properties of a truly | random function. | | The probability that a random function does _not_ output 0 | given some specific input block is (1 - 1/2^n). Taking each | of the possible 2^b input values into account this means | that 0 is not an output for any input with probability (1 - | 1/2^n)^(2^b) ~ e^(-2^(b-n)). | | For SHA-256 with n = 256 and b = 512 (one can treat the | compression function as a 768 to 256 bit random function, | but we can stick to the worst-case single-block message | case here) we have that the probability of 0 _being_ an | output for a single-block message is 1-e^(-256) which | effectively means it exists, but the probability never | quite reaches 1. | p1mrx wrote: | Your math looks plausible for an _ideal_ cryptographic | hash, but wouldn 't you first have to prove that SHA-256 | actually does behave as if each unique input generates an | independent random number? | pbsd wrote: | There's no real way to connect the compression function | to any kind of mathematical model that would help here, | other than modeling it as random. Provability is out the | window. | | So what you do is assume it behaves like a random | function until proven otherwise, by _some_ property that | deviates from this model. (This is not even the case for | SHA-256, since neither the hash nor the compression | function can be modeled as random oracles (due to length | extension and the Davies-Meyer structure), but we can | conveniently forget that for the duration of this | thread.) | | There _are_ some hash functions based on number-theoretic | problems where you could reason about such things, but | none of those are in common use since they are usually | slow and/or require an output unstructured transformation | anyway to turn them into proper, rather than just | collision-resistant, hash functions. | ypcx wrote: | Similar project which visualizes SHA-256 into terminal: | https://github.com/in3rsha/sha256-animation | based2 wrote: | https://en.wikipedia.org/wiki/Secure_Hash_Algorithms | jonathanyc wrote: | I love single-purpose websites like this that put a potentially | complex implementation behind an elegantly simple interface. This | website's design and styling are pretty too :) Another useful one | is https://www.h-schmidt.net/FloatConverter/IEEE754.html . I'd | say even https://godbolt.org/ counts! | westurner wrote: | SHA2: https://en.wikipedia.org/wiki/SHA-2 | | https://rosettacode.org/wiki/SHA-256 | | Hashcat's GPU-optimized OpenCL implementation: | https://github.com/hashcat/hashcat/blob/master/OpenCL/inc_ha... | | Bitcoin's CPU-optimized sha256.cpp, sha256_avx2.cpp, | sha256_sse4.cpp, sha256_sse41.cpp: | https://github.com/bitcoin/bitcoin/blob/master/src/crypto/sh... | | https://github.com/topics/sha256 | https://github.com/topics/sha-256 | | Cryptographic_hash_function#Cryptographic_hash_algorithms: | https://en.wikipedia.org/wiki/Cryptographic_hash_function#Cr... | | Merkle-Damgard construction: | https://en.m.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_... | | (... https://rosettacode.org/wiki/SHA-256_Merkle_tree ... | Merkleized IAVL+ tree that is balanced with rotations in order to | optimize lookup,: https://github.com/cosmos/iavl | | Self-balancing binary search tree: | https://en.wikipedia.org/wiki/Self-balancing_binary_search_t... ) | nwatab wrote: | Looks bautiful. I understand it is really complicated (even I | know calculation of SHA256) | recursive wrote: | On the third step(?) of the second step, it says "Copy 2nd chunk | into 1st 16 words", but it's accompanied by a visualization of | copying the _1st_ chunk into the 1st 16 words. Am I just totally | misunderstanding something? | spdebbarma wrote: | This comes to my attention at a really convenient time. As a | teenager, I initially got interested in Computer Science due to | cryptography. Over a decade later, I've gotten into the subject | for the first time since then. | | For the last few days, I've been writing my own encryption for | fun even though it's 100% not secure enough or powerful. My | belief is that even though it's not super useful, the experience | of attempting to write one is teaching me a lot more than I would | have by simply studying it. | zahllos wrote: | Rather than write crypto, what I'd actually recommend is to | break it. Schneier put together a block cipher cryptanalysis | course a long time ago and while I don't usually recommend his | crypto books these days, the course is good: | https://www.schneier.com/academic/archives/2000/01/self-stud... | (in this case, his crypto book might actually be useful, | because it documents some of these out of date ciphers. There's | (was?) a mistake in the DES code though iirc). | | It is essentially a tour of all the early cryptanalysis | literature, complete with suggestions of ciphers to target | (e.g. FEAL). This will give you a sense of how the attacks | work. Many of the ciphers are old, but I wouldn't let that put | you off. | | The study technique for this would be a) implement each cipher | with toggles to control rounds and any other features, then | implement attacks. Most of the papers should be open access by | now since the 'course' was written in the year 2000. You could | also 'catch up' on the constructions and attacks that have come | out since. | | I would caveat this with: what I am advising is purely for | potential interest. Bear in mind there is little need to | implement new block ciphers these days (what I'm saying is: | this is a very specialized skill and most people won't find | jobs in it). | iqanq wrote: | Two of the buttons at the top have no "title" attribute and | therefore no tooltip. | nayuki wrote: | My way of explaining step by step visually is by implementing in | Excel: AES https://www.nayuki.io/page/aes-cipher-internals-in- | excel ; DES https://www.nayuki.io/page/des-cipher-internals-in- | excel . | | Also relevant: https://www.righto.com/2014/09/mining-bitcoin- | with-pencil-an... | jerpint wrote: | Very satisfying! | oconnor663 wrote: | Oh this is great. When we taught SHA-256 last semester, we linked | to this YouTube video: https://youtu.be/f9EbD6iY9zI. Next time we | do it, we'll probably link to both. Having several different ways | to visualize the same thing is very helpful, and I like that this | one moves quickly. | | A couple of details missing from this visualization are how you | pad a message to be a multiple of the block size, and how you | chain blocks together to form a longer message. In the pseudocode | at https://en.wikipedia.org/wiki/SHA-2#Pseudocode, that's the | "Pre-processing (Padding)" part and the "for each chunk" loop | just below it. I get why you'd want to leave those things out, | since they're not really the interesting part, and the screen is | already pretty packed as it is. | | If anyone's feeling curious about implementing this yourself, | take a look at these project notes: | https://github.com/oconnor663/applied_crypto_2021_fall/tree/.... | At some point I'll clean that up for public consumption, but for | now just ignore the parts about grades and cheating :) | manceraio wrote: | Thanks for the feedback and I am glad you'll use it for | teaching (which was the main goal of this project)! The padding | part it's briefly explained on the "dynamic" notes on the left | column, but yes, can be improved. Typing on the input gives you | some sense of what is doing on the background, specially if it | jumps to two blocks. | | The "for each chunk" is also implemented (which was one of the | most difficult parts to synchronize with the UI), but I agree | too, I should come up with some way to represent it better. | Thanks again :) | picture wrote: | So, how do people come up with these things? I assume every | aspect of the design is carefully considered to defend it against | various attacks. For example, why "right rotate 7 XOR right | rotate 18 XOR right shift 3" and not "right rotate 2 XOR right | rotate 3 XOR right shift 4"? | edflsafoiewq wrote: | >why not "right rotate 2 XOR right rotate 3 XOR right shift 4" | | In this case, you generally want shifts that are far apart so | bits that far apart have a chance to influence each other. The | other operations have only local effects on bits (and, or, xor | affect only the same bit position; add affects the same bit | position and perhaps a few that follow via carries). Only the | shifts/rotates give a chance for "non-local" effects. | metalrain wrote: | Visualized like this it feels like security through obscurity, | but there must be reason for this. | | I did wonder why initialization is like: | | 1. Initialize hash value h0 to h7: first 32 bits of the | fractional parts of the square roots of the first 8 primes | 2..19). | | 2. Initialize array of K constants: first 32 bits of the | fractional parts of the cube roots of the first 64 primes | 2..311 | orangepenguin wrote: | It's not security through obscurity. In fact, it's the very | opposite. You can see the process exactly. The reason this is | secure is because the process itself doesn't work backwards. | You can create a hash using this algorithm, but you'll never | reverse that hash back into the original text. | manceraio wrote: | https://news.ycombinator.com/item?id=23166713 | | It seems like a "nothing up my sleeve" way to initialize the | variables. | [deleted] | bsedlm wrote: | from what I've seen, there's a lot of "obscurity" to this; | there are many seemingly arbitrary choices all over the | place. | | In the end most encryption algorithms boil down to doing | 'random' (arbitrary, hard to justify why) things to data and | then undoing them exactly in order to decrypt. | | the math is all incredibly abstract but not all that complex, | the high level of abstraction does make it quite difficult to | grasp. | | What's worse is that I fear there are incentives (mostly | political/security interests) to keep the field small and to | keep many people far away from this very practical use for | all these beautiful, elegant, simple (but extremely abstract) | mathematics (refering to the entire cryptography field). | dragontamer wrote: | > What's worse is that I fear there are incentives (mostly | political/security interests) to keep the field small and | to keep many people far away from this very practical use | for all these beautiful, elegant, simple (but extremely | abstract) mathematics (refering to the entire cryptography | field). | | I mean, everything you want to learn about crypto is | available online, in libraries, in textbooks. Including | differential cryptoanalysis, the theory behind these | mathematical forms (Galois Field makes things _EASIER_, not | harder actually. That's why CRC-checks and Reed-Solomon | codes were based off of Galois Fields, and AES being based | on GF(2^8) is to take advantage of those same properties). | | -------- | | What has happened is that the "old generation" of | programmers is dying out / retiring. And they aren't | passing on their knowledge to the new generation. The "old | generation" of programmers were high-math, abstract algebra | and more, while "new generation" programmers just never | bothered to learn this stuff. | holoduke wrote: | Isn't all the math involved in the end based on the modulo | operator and prime numbers? | dragontamer wrote: | Yes in "Galois Field" arithmetic. But GF(2^8) (or | whatever) arithmetic is only in AES and a few other | ciphers/hash functions. SHA-256 looks like an XOR / Add / | Rotate kinda cipher. | tptacek wrote: | No. | aaronmdjones wrote: | Not all decryption is doing exactly the same things in | reverse. For example, with CTR mode (and thus GCM mode, | which is CTR plus GMAC), you call the /encryption/ routine | regardless of whether you're encrypting or decrypting data. | This means in an embedded environment you can save die | space because your program doesn't need the e.g. AES | decryption routines too. | | https://upload.wikimedia.org/wikipedia/commons/4/4d/CTR_enc | r... | | https://upload.wikimedia.org/wikipedia/commons/3/3c/CTR_dec | r... | | (Note the bold text) | bsedlm wrote: | I mean it in the sense that they undo the 'noise' added | to (or reverse the scrambling of) the initial input . | | even if they do it in a different way. | jjeaff wrote: | I doubt there is any concerted effort to keep the field | small. That would be like saying tech companies don't want | people learning how to code so that they can maintain an | advantage. | | If anything, governments and companies are encouraging | people to study cryptography so that they are able to hire | more experts in the future. | | Now, once you get gatekeeper organizations and special | licensing organizations like contractors licensing or | beauticians licensing, those are examples of groups trying | to keep the pool of experts small. | tptacek wrote: | This seems pretty silly, as there is extensive (one might | say tedious) detail on why the decisions in a hash function | or block cipher were made; your challenge is that you have | to do a literature search to collect all the reasons --- | but that's science for you. | less_less wrote: | You may not get an exact answer for SHA-1 or SHA-2, because | they were designed by NSA, and I'm not sure whether a complete | design doc has been published. SHA-3, by contrast, was designed | in an open competition, and is completely different from SHA-1 | and SHA-2. But here's a rough go at it. | | First of all, the overall form. SHA-2 is a Merkle-Damgard | construction, meaning that it has a "compression function" | which takes an algorithm state and a message block, and outputs | a new algorithm state. The final block gets some padding, so | that eg "x" and "x\000" don't have the same hash, and then the | final algorithm state is the output. (This is a known weakness: | from H(x) you can calculate H(x concat padding(x) concat other | stuff). SHA-3 doesn't have this weakness. This weakness doesn't | itself break collision resistance, but it can be dangerous for | other uses of SHA2 if you aren't careful.) | | The compression function is a Davies-Meyer construction, which | means that given an input state, it: | | * Copies the state. | | * Encrypts the state with a "cipher" of sorts (the "cipher" | extracted from SHA-2 is known as SHACAL-2), using the message | as a "key". | | * Adds the copied state to the encrypted state to produce a new | state. | | Davies and Meyer proved that, for an ideal cipher, this would | make a collision-resistant hash function. Note that because the | update is a "cipher", it must be internally invertible. This is | a good idea anyway, because any non-invertibility is by | definition a collision, and you want to push that out as far as | possible to make collisions hard to find. The step that isn't | invertible is the final "add the copied state to the encrypted | state". | | Within that design, the SHA-2 cipher is based on a shift | register. Basic shift registers have been used in crypto for | many decades; traditionally you get almost all of the bits in | the register by shifting its current state, and at least one | (typically only the one shifting in) by computing a function of | the other bits. To extend this to general-purpose computers, | you can do the same thing for words (32-bit words for SHA-224 | and -256 and 64-bit words for SHA-384 -512). So you have A | shifting to B shifting to C etc, with a final value that's | computed and shifted back into A. You can see there's a slight | twist, which is that instead of E=D you get E=D+stuff. I expect | that this mitigates issues where the same stuff is used in the | same way throughout the whole round. | | The "message schedule" is likewise based on a cipher's key | schedule. The idea in a cipher is that each round needs a | different version of the key to avoid "slide" attacks, so you | mix the key during the round as well as mixing the cipher | state. I'm not sure what the corresponding theory is for a hash | function, but it's also pretty clear that you want a single | byte of the message to be used in many places throughout the | operation, so mixing the message is a must. | | For the operations, the biggest constraint is that they need to | be as nonlinear as cheaply, because doing a bunch of linear | functions in a row still gets you a linear function, and those | are easy to break. They need to be nonlinear both as bits and | as integers, so a popular design is to mix addition (linear | over ints) with xor (linear over bits) and rotations (linear | over both, but you need it to propagate changes from the top of | a number to the bottom). That way the whole operation won't be | linear over bits, nor over the integers, but all three | operations are cheap on PCs. This is called an "ARX" (Add- | Rotate-Xor) design. | | Picking the exact operations and rotation constants is | something of a black art, and while you can trace descent from | MD5-SHA0-SHA1-SHA2, the exact design criteria for the SHAs | might not even be public. But you can see how some of the | decisions may have been made. Consider the rotations in sigma0 | and sigma1. The rotation constants in these designs are | typically chosen so that if you look at any slice of the | output, it will have many different input bits affecting it, | which in turn means that small changes diffuse rapidly | thoughout the design. This is not done perfectly in SHA2, in | that the same bits are used for the Maj and Ch in successive | iterations (i.e. you compute Maj(A,B,C) and then Maj(newA,A,B) | next time since they shifted over), so you'd get correlated | outputs of those steps from round to round, but apparently it's | good enough. | | The setup constants are chosen as the square and cube roots of | prime numbers, as "nothing-up-my-sleeve" numbers. The idea is | that if the initialization were random numbers with no | rationale given, then it would be a possible place that NSA | could have hidden a backdoor. But it would be difficult to | create a backdoor where the initialization is the square roots | of the primes. | dragontamer wrote: | About linearity, that just means that there's no "multiply" | or "exponent" function equivalent to our primitives. | | For example: if "add Foo" were our primitive, then 64-rounds | of "add-Foo" could be broken by simply "data + 64 * Foo". IE: | We found a "trivial shortcut" and someone else can break our | cipher way faster than we can use it. | | Addition is linear over numbers, because of multiplication. | | XOR is linear over numbers: because XOR undoes itself. (5 x | (XOR-Foo) is equivalent to 1x (XOR-Foo)). | | It turns out that combining addition and XOR together results | in a non-linear function over numbers and non-linear function | over bits. | | We can't "shortcut numbers", because the XOR-messes up our | "number math". We can't "shortcut bits" because Add has this | really annoying "carry" that basically has a 50% chance of | shuffling bits around. | | As such, we "expect" that combinations of Addition, XOR, and | Shifts are non-linear. I'm not sure if it's been | mathematically proven however, but no one has been able to | show a "shortcut" thus far. | floodyberry- wrote: | Generally, come up with a set of operations that you want to | use that meet your design criteria (fast in hardware, fast in | software, fast in SIMD, whatever), then brute-force the | instruction order and/or arbitrary constants (rotations) to | minimize known attacks and maximize diffusion | | e.g. the Chacha20 design document explains the choices made in | a fairly high level and easy to understand way: | https://cr.yp.to/chacha/chacha-20080128.pdf | kzrdude wrote: | MD5 and SHA-1 are predecessors, and they are simpler, so | certainly by starting from the understanding of the simpler | ones. Just to say it wasn't all conceived in one go. | tptacek wrote: | It's helpful to understand that the algorithm wasn't designed | the way it's presented in this illustration, and consists of | somewhat discrete components. | | It's an iterated design, like a block cipher, meaning that it's | built around a simple round function that's repeated a bunch of | times on each input, rather than a super-complicated function | run once. | | It belongs to a large, important family of cryptographic hashes | called Merkle-Damgard, which pads messages to a fixed block | size, chunks them into blocks, feeds and feeds each block to an | iterated "compression function" (the heart of the hash) that | takes a block and the chained n-1th compression value and spits | out the nth compression value. So a lot of the mechanism in | this illustration is just the vanilla mechanics of an MD hash. | | Iterated cryptographic designs generally have "schedule" or | "expansion" functions that take the (small) input to the | iterated function and "expand" it so that not all the | iterations are working on exactly the same data; in the same | way, a block cipher will have a "key schedule" that expands | your 128-bit key into distinct "round keys" for each round. | Message and key schedules, to me, feel like tiny little ciphers | embedded in the larger cipher, and they're yet more of the | complexity you're looking at, but can be studied independently | (the SHA2 message schedule is apparently a big part of what | makes it difficult to attack). | | When you see magic numbers in a block cryptography design like | this, two relatively safe bets you can make is that they're | either "nothing up my sleeve" numbers chosen from e.g. | mathematical constants, just for the sake of avoiding | arguments, or that they're the product of statistical testing | to maximize things like diffusion or minimize things like | linear or differential characteristics. | | With all block cipher cryptography one goal you always have is | introducing nonlinearity; you can accidentally design a simple | iterated function that is actually linear, and that cipher will | be solvable simply with Gaussian elimination. People have shown | me CTF levels that, for instance, linearized the AES round | function. So when you see particular operations chained | together in a cipher/hash design, keep in mind that they're | balancing goals of (1) ensuring nonlinearity, (2) maximizing | diffusion, the rate at which a single-bit change in the message | totally scrambles the output in the shortest number of rounds, | (3) optimizing metrics to avoid differential and linear | cryptanalysis, (4) maximizing performance on target hardware. | | As was suggested downthread: a good way to come at this stuff | is to start with MD4, and then read about MD5 (vs. MD4), then | SHA1, and then take a closer look at SHA2. This stuff didn't | get figured out all at once, and all these hashes are related. | You might find MD4 easier to get your head around. | | For the linear and differential cryptanalysis stuff, which is | surprisingly (given its age) important in cipher/hash design, a | great starting point is the Heys tutorial, which is built | around worked examples of both attacks: | | https://ioactive.com/wp-content/uploads/2015/07/ldc_tutorial... | sedatk wrote: | What a great question and what an excellent answer. Thank | you! | dragontamer wrote: | 1. You want an invertible operation. Invertible operations do | _NOT_ lose information, and therefore have the maximum amount | of entropy per step. | | 2. You want the invertible operation to pass a statistical test | called "differential cryptography analysis". Over multiple | rounds, it must be difficult / impossible to "predict" how | 1-bit of difference changes the state. (ie: 1-bit of difference | should lead to 50.0000000% change in every output bit. If its | 50.1% or 49.9% change of bits, you fail because someone running | cryptoanalysis will pick that up). | | ---------- | | #1 is somewhat easy. It turns out that Data XOR (Rotate-left | Data) XOR (Rotate-right Data) is all you need to make an | invertible operation. 5-operations, no more (any more is | redundant and therefore unnecessary use of compute power), no | less (any less is not invertible and therefore loses | information / entropy each step). | | #2 is complicated: you gotta understand differential | cryptoanalysis and run a bunch of tests. | | ----------- | | The discovery that (Data) XOR (Rotate-left Data) XOR (Rotate- | right Data) was invertible became extremely popular in the | 2010s through 2020s, and has become the cornerstone of XOR / | Rotate / Add ciphers (aka: chacha), pseudorandom generators, | and hash functions. | | I don't know quite when it was originally discovered, but | Jenkins was blogging about the importance of invertibility and | playing with invertible xor/rotate stuff in (non-crypto) hash | functions way back in the 90s. | | I know Knuth's "Art of Computer Programming" book 2, | Seminumerical Algorithms, discusses the importance of | invertibility in random number generators, which is closely | related to hashing / cryptographic procedures. So this | "understanding" has been around for decades, but has only | "become popular" in the SHA256 / Blake3 / pcg-random era. | | ------ | | In the 90s, ciphers were mostly using SBoxes for this step | ("confusion", to grossly change a value to another value | without losing information). But today, modern CPUs are much | faster at add/xor/bitshift operations than reading/writing to | memory. So SBoxes are no longer a high-speed methodology / | primitive for these kinds of operations. | | It makes more sense to change our algorithms to use a new | "invertible confusion operation" (aka: what SBoxes did before, | and what ((Data) XOR (Rotate-left Data) XOR (Rotate-right | Data)) does today). | | -------- | | EDIT: Remember: the modern crypto-primitive is just a | combination of "confusion" principles and "diffusion" | principles. | | 1. Confusion "lossless transforms" numbers into other numbers. | (A "set permutation" of sorts) | | 2. Diffusion "moves" bits from one number into other numbers. | | Iterating over confusion + diffusion many times (IIRC, SHA256 | is 64 rounds) is all you need to make a cryptographic cipher. | If you "just" need a pseudo-random number generator or hash | function, maybe 5 to 10 rounds is all you need. | y42 wrote: | Not sure if I understand you right, but sha256 is not | invertible, there are a couple of steps where you actually | just 'cut off' information that is lost afterwards. | dragontamer wrote: | The primitive (data) XOR (rotate-data) XOR (rotate-data) is | invertible, which means there's no "bit funnel" (Bob | Jenkin's term). | | You want your "primitives" to be invertible, so that your | one source of "non-invertible" operations is controlled | very carefully. | | Hash functions are non-invertible. But all operations on | the "internal state" should be invertible (!!!!) to | maximize the entropy per round. | | -------- | | All good hash-functions have invertable operations (aka: a | bijective (1-to-1 and onto) operation) over its state to | "distribute" the bits around in some manner. You then | perform a non-reversable XOR over the input message data | (this is the one and only non-reversible step), maybe after | operating over the input data somehow. | | Whenever you're "mixing" bits around in a cipher or hash, | you need every step to be invertible to maximize your | entropy. If you have 2^256 possible input states, you want | to have 2^256 output states. By the pigeon-hole principle, | this only happens if you have a bijective / 1-to-1 and onto | invertible operation. | | -------- | | Lets look at the opposite. Lets say we have a non- | invertible function. That is, 2^256 possible inputs become | only 2^128 outputs. Guess what? We've just lose 128-bits of | information (!!!). | | It doesn't matter how complex your operation is. If you | have 256-bits of input and only 128-bits of output, you've | "lost information". You _NEVER_ want to lose internal-state | information. | | The hash-function's internal state should be at a maximum | 256-bits (with 256-bits of entropy) every step. Sure, the | input might be 512-bits, 4096-bits, or 100-MBs long, but | each "step" of a 256-bit hash should retain 256-bits of | state to be maximally "difficult" to reverse. | | That's kinda-sorta obvious if you think of it from a | pigeon-hole perspective. | y42 wrote: | That's right, but sha256 also utilizes eg shift operation | with a fixed length for the result. Meaning: your moving | information "out of the scope". Or all the additions: the | result is often greater then 32bit (2 words) and | therefore being reduced. | dragontamer wrote: | Everything in context. | | The operation you're talking about is "sigma_0" and | "sigma_1" I believe, which is defined as: | | sigma_0(x) = Rotate7(x) XOR Rotate18(x) XOR shift3(x). | | sigma_1(x) = Rotate17(x) XOR Rotate19(x) XOR shift10(x). | | Where "shift3" and "shift10" are both lossy operations. | | ---------------- | | While "shift3" and "shift10" are lossy, I'm not 100% | certain that "sigma_0" or "sigma_1" is lossy. But that | discussion aside, both sigma_0 and sigma_1 are applied to | the _message_, not the internal SHA256 state. | | The _message_ needs to be compressed, so a lossy | operation over the message is not only expected, but | required. 4096-bits of input need to become 256-bits of | output. 8192 bits of message-input needs to become | 256-bits of output. | | ----------- | | But if you look at the "intermediate hash chain" where | H(i) = a + H(i-1) for 64 rounds, all operations over "a" | and the internal hash-state are invertible operations | (SIGMA_0 and SIGMA_1 are both invertible, being (x) XOR | (rotate x) XOR (rotate x) style functions). | | ------ | | I'm not saying that the "whole" hash function needs to be | invertible. I'm saying that __particular__ elements of | the hash function _should_ be invertible. The design of | these particular elements (in particular, SIGMA_0, which | is (Rotate2(x) XOR Rotate13(x) XOR rotate22(x))) is | _clearly_ and evidently invertible / 1-to-1 and onto | bijection / confusion principles. | | The particular constants (why "rotate2", "rotate13" and | "rotate22") is chosen for other reasons: probably | differential cryptoanalysis but I admit that I'm not 100% | sure on that (that's my expectation though). | tptacek wrote: | I guess sort of intuitively (I'm not a cryptographer): | | If your round function isn't invertible, then it's going | to converge at some point on some fixed value, and the | round function is going to stop doing anything useful. | | More broadly, SHA2 is a sort of instance of a | construction called Davies-Meyer, which treats each | message block as the key to a bona-fide block cipher | (SHACAL, in SHA's case), each encrypting the previous | block. It's hopefully pretty obvious why a block cipher | core needs to be invertible. :) | | So I also find it kind of helpful to remember that you | can take any block cipher and turn it into a hash, and | then a "good" hash function is just optimizing the block | cipher core around the goals of a hash function (be fast, | be nonlinear, be hard to find differential trails through | the whole sequence of round functions, &c). | | It's a thing I don't love about illustrations like the | one we're discussing, in that it sort of presents this | "intelligent design" problem of, like, "how did we arrive | at this incredibly complex fully functioning eyeball", | when there's a whole series of smaller evolutionary steps | that led to this point; it's more productive maybe to | look at the bones of the whole design before diving into | the details of which bits go where at each precise step. | dragontamer wrote: | > I guess sort of intuitively (I'm not a cryptographer): | | Don't worry. I'm not one either. And I think that's why I | am actually able to tell you that invertibility / 1-to-1 | onto bijections is an important concept :-) | | An actual cryptographer would tell you its 1-to-1 and | onto and move on. | | > It's a thing I don't love about illustrations like the | one we're discussing, in that it sort of presents this | "intelligent design" problem of, like, "how did we arrive | at this incredibly complex fully functioning eyeball", | when there's a whole series of smaller evolutionary steps | that led to this point; it's more productive maybe to | look at the bones of the whole design before diving into | the details of which bits go where at each precise step. | | Agreed. There's a lot of history here, and knowing all of | the history helps a _LOT_. | | Go back 50 years ago, and ciphers are way easier to grok. | DES / Feistel ciphers are really easy for example. But | then we discovered issues about them and iteratively | improved. | | The old "DES" / Feistel cipher principles of confusion | and diffusion remain with us today, but each step has | been honed for 90s-era computers (SBoxes and 32-bit | numbers), and then honed again for 2010s-era computers | (recognition that XOR / Rotate / Add is a faster | primitive today than memory-based SBoxes). | | I don't think any of the principles have changed since | DES / Feistel cipher days. Its just that today's designs | are better for today's computers. | | ------ | | EDIT: As far as I can tell: "confusion" can be created by | (data) XOR (rotate-data) XOR (rotate-data) primitives. | "diffusion" can be created by the "ADD" operator (in | particular: "carries" will diffuse the bits around). | | So XOR, rotate, and Add are the only primitives you need | to make a modern crypto-cipher. All three primitives are | outrageously fast on modern machines. | | AES and other older ciphers tried to make each round | relatively high quality. Modern ciphers try to make each | round low-quality, and then do something like 64-rounds | or 80-rounds to make up for it. | | So you'll see old ciphers like AES with just 11 rounds, | but modern ciphers / crypto algorithms like SHA256 use | 64-rounds. | manceraio wrote: | Do you recommend any resources to learn about this? | dragontamer wrote: | The information in the above post is a merger of like, 20 | different sources of information. | | Your standard cryptographic books from any undergraduate | program will tell you about the basics of confusion / | diffusion, but I don't think the concept is very difficult | at all. | | Invertibility is hugely important but not discussed very | much. It seems like crypto-experts 'obviously' know about | it so they just don't talk about it? Knuth and Bob Jenkins | both talked about the importance of invertibility to random | number generators. EDIT: Invertibility is the basis of | bijective / 1-to-1 and onto permutation functions. To be | fair, I think everyone discusses the concept but maybe with | different words. | | Here's Jenkin's discussion on (non-crypto) hash functions, | including a few paragraphs on "invertibility" (or "funnels" | as they put it): | http://www.burtleburtle.net/bob/hash/doobs.html | | The "pcg-random" generator also has a large discussion on | invertibility. Honestly, one of the best writeups on the | subject, and I felt like my IQ went up severely after | reading the paper end-to-end: https://www.pcg- | random.org/paper.html | | -------- | | The study of the invertibility of (data XOR (rotate-right | data) XOR (rotate-left data)) is covered in many blogposts. | https://marc-b- | reynolds.github.io/math/2017/10/13/XorRotate.... | | The study of invertibility in general was covered by | Lemire: https://lemire.me/blog/2016/08/09/how-many- | reversible-intege... | | ----- | | So as you can see, invertibility is "important", but rarely | discussed as important. Its just assumed that everyone | knows how important it is. Once you realize that | invertibility / lack of funnels is important, everything | else makes sense. | | Galois field multiplication is useful in AES because its | invertible (multiply by the GF(2^8) reciprocal). Aaaaah. I | see. Why didn't my undergrad teacher just start with the | importance of invertibility before talking about prime | numbers and extension fields? | | ----- | | Ah right. Once you know that these things have great | properties (ie: invertible), then you can just read the | SHA256 paper directly and the rest is just "obviously" | confusion + diffusion principles. | | ----- | | Linear Cryptoanalysis is the "standard" run a distribution | kinda thing. Anyone who has done Chi-squared tests over | random numbers kinda-gets this principle. Honestly, your | standard non-crypto RNGs are roughly at this level at this | point, so the study of any statistical-test for any random- | number generator is good. Knuth / Art of Computer | Programming Vol2 is one source of information on Chi- | squared tests, but the study of statistics in general also | results in Chi-squared tests and the like. | | Differential Cryptoanalysis is more difficult and looks at | the change-of-bits at each step of every operation. I don't | quite remember how I was introduced to the concept, but | differential-cryptoanalysis of many popular ciphers is a | well-studied thing throughout the field. | | -------- | | Knowledge of "what is fast" and "what is not fast" is... | not really easy to come by, and seems to change as computer | architectures change. I know that memory has gotten | relatively slower compared to CPU-speeds in the past 30 | years. I can imagine that in the 90s, an XOR-rotate-add | cipher would take "relatively more" time than today, and | that SBox-based / lookup table based ciphers were far more | popular back then. | | I'm not sure where I learned that information. Maybe | software optimization manuals in general? | reincarnate0x14 wrote: | That's super cool. Visualized or illustrated algorithms have | always looked so magical, to me at least. | M4tze wrote: | Great visualization. Might become my new screensaver. | colejohnson66 wrote: | One could even feed the hash back into itself to get a | different result each time | em3rgent0rdr wrote: | how long would the cycle last before it starts repeating? | [deleted] | tromp wrote: | On the order of 2^256 steps, if SHA-256 behaves randomly, | since the largest cycle in a random permutation on N | elements has expected length ~ 0.62 * N. | MayeulC wrote: | Then wouldn't that be 0.62*2^256, closer to 2^255 ? Not | that it makes a notable difference: at 1 fs per step | (1000 GHz, or 1 TH/s), that would take about 4.5e65 years | to happen. The universe is only about 1e10 years old... | tromp wrote: | It would be at least that, with a smaller contribution to | the expectation from smaller cycles. That's why I said | "on the order of", i.e. not much smaller. | pbsd wrote: | SHA-256 is not a permutation; the expected cycle length | is ~2^128. It's how collisions are (generically) found. | colejohnson66 wrote: | Pigeonhole principle? | pbsd wrote: | Each new output value i can collide with output 1, 2, | ..., i-1. So the collision probability of iteration i is | (i-1)/2^256. Adding all of the iterations up you have | 1/2^256 + 2/2^256 + ... + (i-1)/2^256 = 0.5 i (i-1)/2^256 | which approaches 1/2 as you get to 2^128. | | In reality you use some variant of Rho which does not | store every previous value but uses something like | Floyd's cycle detection or distinguished points and | requires minimal storage, at the cost of some extra hash | computations, bt still on the order of 2^128. | dragontamer wrote: | This situation calls for Birthday paradox, not pigeon | hole. | taviso wrote: | That's really cool. I made a terrible one for SHA1 years ago, | yours is 1000x better. | | https://lock.cmpxchg8b.com/sha1/visualize.html | | I read a paper at the time where someone described a tool they | made to find a near-collision, they explained they were just | flipping bits and visually observing the affects. That sounded | kinda fun, but they didn't release it, so I tried to replicate it | from their description! | bmitc wrote: | Does anyone have any good references, preferably a book but a | good detailed website is fine, on cryptography, hashing, | public/private keys, tokens, encryption, etc. as it relates to a | software engineer? I don't necessarily want to know all the nitty | gritty details of how these things are implemented. Rather, I | think I would prefer simply understanding them and how to use | them, piece them together, etc. to build something out of them. | | I just have very little knowledge in this area. I'm going through | a how to build a blockchain book right now, and I find myself | struggling a little bit where I'm just calling some library | functions but not necessarily knowing how to compose things | properly. | tptacek wrote: | JP Aumasson is one of the authors of the BLAKE hashes and wrote | "Serious Cryptography": | | https://www.amazon.com/Serious-Cryptography-Practical-Introd... | manceraio wrote: | For that I like this one: https://cryptobook.nakov.com/ | y42 wrote: | There also exists a written description showing the process in | Python, step by step, which I consider more helpful, because you | do not need to stop and play the video. | | https://nickyreinert.medium.com/wie-funktioniert-der-sha256-... | edwnj wrote: | not everybody speaks barbarian sir | y42 wrote: | Python that bad? | lelandbatey wrote: | I think it's a reference to the written human language of | the blog post, which when I attempt to view, is in German. | I realize both of the parent comments could be read in | jest; I'm mentioning this here very clearly since tone and | implication sometimes may not translate, and passing | readers may stumble on the context(s) here. | seumars wrote: | Fantastic presentation! The utility functions from the source | code are just as useful. | [deleted] | sylware wrote: | Can we have a video of this on youtube/dailymotion/vimeo/etc | which we can download with yt-dlp? | [deleted] ___________________________________________________________________ (page generated 2022-02-07 23:00 UTC)