[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7850":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":14,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":18,"compositeScore":19,"rankGlobal":9,"rankLanguage":9,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":9,"pushedAt":9,"updatedAt":25,"readmeContent":26,"aiSummary":27,"trendingCount":15,"starSnapshotCount":15,"syncStatus":14,"lastSyncTime":28,"discoverSource":29},7850,"sha256-animation","in3rsha\u002Fsha256-animation","in3rsha","Animation of the SHA-256 hash function in your terminal.",null,"Ruby",3394,169,32,2,0,1,5,3,62.19,"MIT License",false,"master",true,[],"2026-06-12 04:00:36","# SHA-256 Animation\n\nAn animation of the [SHA-256](https:\u002F\u002Fnvlpubs.nist.gov\u002Fnistpubs\u002FFIPS\u002FNIST.FIPS.180-4.pdf) hash function in your terminal.\n\nVideo: \u003Chttps:\u002F\u002Fwww.youtube.com\u002Fwatch?v=f9EbD6iY9zI>\n\n![](images\u002Fsha256.gif)\n\n## Usage\n\nJust run the `sha256.rb` script with the data you want to see hashed.\n\n```\n# simple\nruby sha256.rb abc\n\n# hash binary or hex data by using `0b` or `0x` prefixes\nruby sha256.rb 0b01100001\nruby sha256.rb 0xaabbccdd\n\n# hash a file (be aware that files will have a newline character at the end)\nruby sha256.rb file.txt\n\n# speed up or step through the animation (optional)\nruby sha256.rb abc normal # default\nruby sha256.rb abc fast\nruby sha256.rb abc enter\n```\n\nYou can also run the individual functions used in SHA-256 by passing in binary strings as arguments:\n\n```\nruby shr.rb 11111111111111110000000000000000 22\nruby rotr.rb 11111111111111110000000000000000 22\nruby sigma0.rb 11111111111111110000000000000000\nruby sigma1.rb 11111111111111110000000000000000\nruby usigma0.rb 11111111111111110000000000000000\nruby usigma1.rb 11111111111111110000000000000000\nruby ch.rb 11111111111111110000000000000000 11110000111100001111000011110000 00000000000000001111111111111111\nruby maj.rb 11111111111111110000000000000000 11110000111100001111000011110000 00000000000000001111111111111111\n```\n\nYou can do double-SHA256 (e.g. [Bitcoin](https:\u002F\u002Flearnmeabitcoin.com)) by using `hash256.rb`. This script accepts _hex data_ (e.g. [block headers](https:\u002F\u002Flearnmeabitcoin.com\u002Ftechnical\u002Fblock\u002F#header), [transaction data](https:\u002F\u002Flearnmeabitcoin.com\u002Ftechnical\u002Ftransaction\u002F)) by default.\n\n```\nruby hash256.rb 0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c # genesis block header\n```\n\n## How does SHA-256 work?\n\nThe [\u003Cabbr title=\"National Institute of Standards and Technology\">NIST\u003C\u002Fabbr> specification](https:\u002F\u002Fnvlpubs.nist.gov\u002Fnistpubs\u002FFIPS\u002FNIST.FIPS.180-4.pdf) contains a precise explanation of SHA-256. The following is essentially a visualised summary of that document.\n\n\n### 1. Definitions\n\nThe official specification begins with a number of definitions, but seeing as this is a simplified explanation, all I want you to know is:\n\n* `bit` = `0` or `1` (the smallest unit of storage on a computer)\n* `word` = 32 bits\n\nAlso, [bitwise operations](https:\u002F\u002Fwww.calleerlandsson.com\u002Frubys-bitwise-operators\u002F) use the following symbols:\n\n```\nOR  = |\nXOR = ^\nAND = &\nNOT = ~\n```\n\n### 2. Operations\n\nSHA-256 uses four basic bitwise operations on `words`.\n\n#### Right Shift ([`shr.rb`](shr.rb))\n\n![](images\u002Fshr.gif)\n\n\u003Cpre>\nSHR\u003Csup>n\u003C\u002Fsup>(x) = x >> n\n\u003C\u002Fpre>\n\nMove bits a number of positions to the right. The bits shifted off the right-hand side are lost.\n\n#### Rotate Right ([`rotr.rb`](rotr.rb))\n\n![](images\u002Frotr.gif)\n\n\u003Cpre>\nROTR\u003Csup>n\u003C\u002Fsup>(x) = (x >> n) | (x \u003C\u003C 32-n)\n\u003C\u002Fpre>\n\nMove bits a number of positions to the right, and place the shifted bits on the left-hand side. This can also be referred to as a _circular right shift_.\n\n#### Exclusive Or ([`xor.rb`](xor.rb))\n\n![](images\u002Fxor.gif)\n\n\u003Cpre>\nx ^ y ^ z\n\u003C\u002Fpre>\n\nThe `XOR` bitwise operator takes two input bits, and outputs a `1` if _only one_ of them is a `1`. This is useful for getting a _balanced representation of multiple bits_ when merging them together via multiple `XOR` operations.\n\n#### Addition ([`add.rb`](add.rb))\n\n![](images\u002Fadd.gif)\n\n\u003Cpre>\n(v + w + x + y + z) % 2\u003Csup>32\u003C\u002Fsup>\n\u003C\u002Fpre>\n\nThis is standard integer addition, but we constrain the result to a 32 bit number by taking the result **modulus 2\u003Csup>32\u003C\u002Fsup>**.\n\n\n### 3. Functions\n\nThe operations above can be combined to create functions.\n\nThe first four functions are named using the Greek symbol **Sigma** (lowercase `σ` and uppercase `Σ`). This is for no particular reason, it's just so we can give names to some combined operations.\n\nI like to think of these as the \"rotational\" functions.\n\n#### σ0 ([`sigma0.rb`](sigma0.rb))\n\n![](images\u002Fsigma0.gif)\n\n\u003Cpre>\nσ\u003Csub>0\u003C\u002Fsub>(x) = ROTR\u003Csup>7\u003C\u002Fsup>(x) ^ ROTR\u003Csup>18\u003C\u002Fsup>(x) ^ SHR\u003Csup>3\u003C\u002Fsup>(x)\n\u003C\u002Fpre> \u003C!-- σ0(x) = ROTR(7, x) ^ ROTR(18, x) ^ SHR(3, x) -->\n\n#### σ1 ([`sigma1.rb`](sigma1.rb))\n\n![](images\u002Fsigma1.gif)\n\n\u003Cpre>\nσ\u003Csub>1\u003C\u002Fsub>(x) = ROTR\u003Csup>17\u003C\u002Fsup>(x) ^ ROTR\u003Csup>19\u003C\u002Fsup>(x) ^ SHR\u003Csup>10\u003C\u002Fsup>(x)\n\u003C\u002Fpre> \u003C!-- σ1(x) = ROTR(17, x) ^ ROTR(19, x) ^ SHR(10, x) -->\n\n\n#### Σ0 ([`usigma0.rb`](usigma0.rb))\n\n![](images\u002Fusigma0.gif)\n\n\u003Cpre>\nΣ\u003Csub>0\u003C\u002Fsub>(x) = ROTR\u003Csup>2\u003C\u002Fsup>(x) ^ ROTR\u003Csup>13\u003C\u002Fsup>(x) ^ ROTR\u003Csup>22\u003C\u002Fsup>(x)\n\u003C\u002Fpre> \u003C!-- Σ0(x) = ROTR(2, x) ^ ROTR(13, x) ^ ROTR(22, x) -->\n\n#### Σ1 ([`usigma1.rb`](usigma1.rb))\n\n![](images\u002Fusigma1.gif)\n\n\u003Cpre>\nΣ\u003Csub>1\u003C\u002Fsub>(x) = ROTR\u003Csup>6\u003C\u002Fsup>(x) ^ ROTR\u003Csup>11\u003C\u002Fsup>(x) ^ ROTR\u003Csup>25\u003C\u002Fsup>(x)\n\u003C\u002Fpre> \u003C!-- Σ1(x) = ROTR(6, x) ^ ROTR(11, x) ^ ROTR(25, x) -->\n\nThe last two functions of **Choice** and **Majority** accept three different inputs.\n\n#### Choice ([`ch.rb`](ch.rb))\n\nThis function uses the `x` bit to **choose** between the `y` and `z` bits. It chooses the `y` bit if `x=1`, and chooses the `z` bit if `x=0`.\n\n![](images\u002Fch.gif)\n\n```\nCh(x, y, z) = (x & y) ^ (~x & z)\n```\n\n#### Majority ([`maj.rb`](maj.rb))\n\nThis function returns the **majority** of the three bits.\n\n![](images\u002Fmaj.gif)\n\n```\nMaj(x, y, z) = (x & y) ^ (x & z) ^ (y & z)\n```\n\n\n### 4. Constants ([`constants.rb`](constants.rb))\n\n![](images\u002Fconstants.gif)\n\n\u003Cpre>\nK\u003Csub>t\u003C\u002Fsub> = ∛primes \u003Cem>(first 32 bits of fractional part)\u003C\u002Fem>\n\u003C\u002Fpre>\n\nSHA-256 uses sixty four constants \u003Ccode>K\u003Csub>t\u003C\u002Fsub>\u003C\u002Fcode> to help with mixing up the bits during the main hash computation. These constants are generated by taking the **cube root** of the first sixty four **prime numbers**.\n\nThe _fractional parts_ of these cube roots are irrational (they go on forever), so they make for a good selection of random bits to use at constants. This is better than using specifically chosen constants, as this makes it less likely that the hash function has been designed with a back-door.\n\nAnyway, to get _32 bits_ from these numbers, we take the fractional part and multiply it by 2\u003Csup>32\u003C\u002Fsup>, and use the resulting _integer_ as the constant.\n\n---\n\nNow that we've defined the functions and constants we're going to use, the next step is to _prepare the message_ for hashing.\n\n### 5. Message ([`message.rb`](message.rb))\n\n![](images\u002Fmessage.gif)\n\nAs you may have noticed, SHA-256 operates on the individual _bits_ of data. So we before we can hash any data, we first of all need to convert it to its binary representation (`1`s and `0`s).\n\nFor example when hashing a _string_, we convert each character to its corresponding number in the [ASCII table](https:\u002F\u002Fwww.cs.cmu.edu\u002F~pattis\u002F15-1XX\u002Fcommon\u002Fhandouts\u002Fascii.html). These numbers are converted to binary, and it's this binary data that we use as the input to the hash function.\n\n\n### 6. Padding ([`padding.rb`](padding.rb))\n\n![](images\u002Fpadding.gif)\n\nThe SHA-256 hash function works on data in 512-bit chunks, so all messages need to be _padded_ with zeros up to the nearest multiple of 512 bits.\n\nFurthermore, to prevent similar inputs from hashing to the same result, we separate the message from the zeros with a `1` bit, and also include the size of the message in the last 64 bits of the padding.\n\n_**NOTE:** This method of separating the message with a `1` and including the message size in the padding is known as **Merkle–Damgård strengthening** (MD strengthening)._\n\n\n### 7. Message Blocks ([`blocks.rb`](blocks.rb))\n\n![](images\u002Fblocks.gif)\n\nAfter the message has been padded, we cut it in to equal 512-bit **message blocks** \u003Ccode>M\u003Csup>i\u003C\u002Fsup>\u003C\u002Fcode> to be processed by the hash function. (There is only one message block for this example message, so the animation above isn't very interesting.)\n\nEach of these message blocks can also be further split in to 16 words \u003Ccode>M\u003Csup>i\u003C\u002Fsup>\u003Csub>j\u003C\u002Fsub>\u003C\u002Fcode> (`512 \u002F 32 = 16 words`), which will come in handy in just a moment.\n\n---\n\nNow that we have padded our message and cut it in to equal chunks, we put _each of the message blocks_ through the main hash function.\n\n### 8. Message Schedule ([`schedule.rb`](schedule.rb), [`expansion.rb`](expansion.rb))\n\nFor each message block we create a sixty-four word **message schedule** \u003Ccode>W\u003Csub>t\u003C\u002Fsub>\u003C\u002Fcode>.\n\nThe first sixteen words of this message schedule are constructed from the message block.\n\n![](images\u002Fschedule.gif)\n\n\u003Cpre>\nW\u003Csub>t\u003C\u002Fsub> = M\u003Csup>i\u003C\u002Fsup>\u003Csub>t\u003C\u002Fsub>\n\n\u003Cem>(for 0 ≤ t ≤ 15)\u003C\u002Fem>\n\u003C\u002Fpre>\n\nThis is then _expanded_ to a total of sixty four words by applying rotational functions to some of the words _already in the schedule_.\n\n![](images\u002Fexpansion.gif)\n\n\u003Cpre>\nW\u003Csub>t\u003C\u002Fsub> = σ\u003Csub>1\u003C\u002Fsub>(W\u003Csub>t-2\u003C\u002Fsub>) + W\u003Csub>t-7\u003C\u002Fsub> + σ\u003Csub>0\u003C\u002Fsub>(W\u003Csub>t-15\u003C\u002Fsub>) + W\u003Csub>t-16\u003C\u002Fsub>\n\n\u003Cem>(for 16 ≤ t ≤ 63)\u003C\u002Fem>\n\u003C\u002Fpre>\n\n\n### 9. Initial Hash Value ([`initial.rb`](initial.rb))\n\nThe hash function begins by setting the **initial hash value** \u003Ccode>H\u003Csup>0\u003C\u002Fsup>\u003C\u002Fcode> in the _state registers_ (`a`, `b`, `c`, `d`, `e`, `f`, `g`, `h`).\n\n![](images\u002Finitial.gif)\n\n\u003Cpre>\nH\u003Csup>0\u003C\u002Fsup> = √primes \u003Cem>(first 32 bits of fractional part)\u003C\u002Fem>\n\u003C\u002Fpre>\n\nLike the constants, the initial hash value uses the fractional part of the **square root** of the first eight **prime numbers**. This gives us a random set of bits that we can use as a platform to begin the hash computation.\n\n\n### 10. Compression Function\n\nThis is the heart of the hash function.\n\nFor each word in the message schedule, we use the current values in the state registers to calculate two new **temporary words** (\u003Ccode>T\u003Csub>1\u003C\u002Fsub>\u003C\u002Fcode> and \u003Ccode>T\u003Csub>2\u003C\u002Fsub>\u003C\u002Fcode>).\n\n#### Temporary Word 1 ([`t1.rb`](t1.rb))\n\n![](images\u002Ft1.gif)\n\n\u003Cpre>\nT\u003Csub>1\u003C\u002Fsub> = Σ\u003Csub>1\u003C\u002Fsub>(e) + Ch(e, f, g) + h + K\u003Csub>t\u003C\u002Fsub> + W\u003Csub>t\u003C\u002Fsub>\n\u003C\u002Fpre>\n\nThis temporary word takes the next **word in the message schedule** along with the next **constant from the list**. These values added to a \u003Ccode>Σ\u003Csub>1\u003C\u002Fsub>\u003C\u002Fcode> rotation of the _fifth_ value in the state register, the `choice` of the values in the _last three_ registers, and the value of the _last_ register on its own.\n\n#### Temporary Word 2 ([`t2.rb`](t2.rb))\n\n![](images\u002Ft2.gif)\n\n\u003Cpre>\nT\u003Csub>2\u003C\u002Fsub> = Σ\u003Csub>0\u003C\u002Fsub>(a) + Maj(a, b, c)\n\u003C\u002Fpre>\n\nThis temporary word is calculated by adding a \u003Ccode>Σ\u003Csub>0\u003C\u002Fsub>\u003C\u002Fcode> rotation of the _first_ value in the state register to a `majority` of the values in the _first three_ registers.\n\n#### Compression ([`compression.rb`](compression.rb))\n\n![](images\u002Fcompression.gif)\n\nAfter calculating the two temporary words, we shift each value in the state registers down one position, and update the following registers:\n\n* The _first_ value in the state register becomes \u003Ccode>T\u003Csub>1\u003C\u002Fsub>\u003C\u002Fcode> + \u003Ccode>T\u003Csub>2\u003C\u002Fsub>\u003C\u002Fcode>.\n* The _fifth_ value in the state register has \u003Ccode>T\u003Csub>1\u003C\u002Fsub>\u003C\u002Fcode> added to it.\n\nThis is one \"round\" of compression, and is repeated for every word in the message schedule.\n\nAfter we have compressed the entire message schedule, we **add** the resulting hash value to the initial hash value we started with. This gives us the final hash value for this message block.\n\n---\n\nIf there are further message blocks to be processed, the current hash value will be used as the _initial hash value_ in the next compression.\n\n![](images\u002Fmerkle-damgard-construction.png)\n\n_**NOTE:** This process of applying a compression function to each message block and using the output as the input for the next compression is known as the **Merkle–Damgård construction**._\n\n### 11. Final Hash Value ([`final.rb`](final.rb))\n\n![](images\u002Ffinal.gif)\n\nWe will be left with eight 32-bit values in the state registers after applying the compression function to each message block.\n\nThe final hash value is just the _concatenation_ of these eight 32-bit values to produce a 256-bit **message digest**. For compactness this message digest is usually shown in hexadecimal.\n\n\n## Notes\n\n* This isn't the prettiest code I've ever written.\n* These scripts redraw the entire terminal screen for every frame of the animation, so the display can become disjointed at faster speeds.\n* All of the actual code for calculating SHA-256 hashes can be found in [`sha256lib.rb`](sha256lib.rb), all of the other files are animations.\n* I decided not to include the individual animations for [`expansion.rb`](expansion.rb), [`t1.rb`](t1.rb), [`t2.rb`](t2.rb) in the main [`sha256.rb`](sha256.rb) animation. This is to help speed up the flow of the animation.\n* In terms of security; I believe the **Sigma** functions help with the _diffusion of bits_, and the **Choice** and **Majority** functions give the hash function it's _one-wayness_ due to being _nonlinear_. The **addition modulus 2\u003Csup>32\u003C\u002Fsup>** is also _nonlinear_.\u003Csup>[1](#security)\u003C\u002Fsup>\n\n\n## Testimonials\n\n> that's dope - [esky33](https:\u002F\u002Ftwitter.com\u002FEsky33junglist\u002Fstatus\u002F1259789790943285248?s=20)\n\u003Cbr>\n\n## Links\n\n* [FIPS 180-4](https:\u002F\u002Fnvlpubs.nist.gov\u002Fnistpubs\u002FFIPS\u002FNIST.FIPS.180-4.pdf) - The official specification for the SHA-2 family of hash functions, including SHA-256.\n* [SHA-256 Examples](https:\u002F\u002Fcsrc.nist.gov\u002FCSRC\u002Fmedia\u002FProjects\u002FCryptographic-Standards-and-Guidelines\u002Fdocuments\u002Fexamples\u002FSHA256.pdf) - A couple of official hash examples to check your implementation with.\n\u003Cbr>\u003Cbr>\n* [Security Analysis of SHA-256 and Sisters](https:\u002F\u002Flink.springer.com\u002Fcontent\u002Fpdf\u002F10.1007%2F978-3-540-24654-1_13.pdf) - A paper by Henri Gilbert and Helena Handschuh explaining some security details about SHA-256.\n\u003C!-- * [SHA-256 Ruby](https:\u002F\u002Fgithub.com\u002Fnevizar\u002Fsha256_ruby\u002Fblob\u002Fmaster\u002Fsha256.rb) - A beautifully concise implementation of SHA-256 in Ruby. Was a great help when checking my code was working correctly. -->\n\n### Footnotes\n\n\u003Csmall>\u003Cem>\u003Ca id=\"security\">1\u003C\u002Fa>: Cryptography For Developers, Simon Johnson (pg. 218)\u003C\u002Fem>\u003C\u002Fsmall>\n\n\n\n\n","该项目是一个在终端中展示SHA-256哈希函数动画的工具。它使用Ruby语言编写，能够以可视化的方式展示数据被SHA-256算法处理的过程，并支持多种输入格式如文本、二进制和十六进制数据以及文件。用户还可以通过命令行参数调整动画速度或逐帧查看。此外，项目还提供了单独运行SHA-256内部组件的功能，对于学习密码学特别是SHA-256工作原理的人来说非常有用。适合于教育场景，帮助理解复杂的哈希计算过程。","2026-06-11 03:14:44","top_language"]