DISK 18 / SHA-256

the hash that fingerprints nearly every file and download in the world, written out by hand: 64 rounds of shuffling, adding and rotating bits. it fingerprints your name, then your name with one letter changed, and counts how many of the 256 bits came out different. about half, every time: that is the point

a floppy disk out of the vending machine, run by pino on the computer at the internet cafe. the US National Security Agency, published as FIPS 180-2 in 2002; written for the cafe.

what it printed:

SHA-256  //  64 rounds, by hand

the empty string   e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
"abc"              ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

"pino"             a55c93846cec6f8780e3f00b112d6b897e8e74b02b52ddce0280b067a3a294cf
"pinp"             37593471203ac780e04c1ebfc5fc5dc8323599e8fa2bb7581f8642a1fccc8b50

one letter changed, 134 of 256 bits came out different.

what is on the disk:

function sha256(msg) {
  var K = [], H = [], p = 0, c = 2
  while (p < 64) { var prime = true; for (var d = 2; d * d <= c; d++) if (c % d === 0) { prime = false; break } if (prime) { if (p < 8) H[p] = Math.pow(c, 1 / 2) * 4294967296 | 0; K[p++] = Math.pow(c, 1 / 3) * 4294967296 | 0 } c++ }
  var bytes = []
  for (var i = 0; i < msg.length; i++) bytes.push(msg.charCodeAt(i) & 255)
  var bitLen = bytes.length * 8
  bytes.push(0x80)
  while (bytes.length % 64 !== 56) bytes.push(0)
  for (var s = 7; s >= 0; s--) bytes.push(s > 3 ? 0 : (bitLen >>> (s * 8)) & 255)
  var rot = function (x, n) { return (x >>> n) | (x << (32 - n)) }
  for (var o = 0; o < bytes.length; o += 64) {
    var w = []
    for (var j = 0; j < 16; j++) w[j] = bytes[o + j * 4] << 24 | bytes[o + j * 4 + 1] << 16 | bytes[o + j * 4 + 2] << 8 | bytes[o + j * 4 + 3]
    for (j = 16; j < 64; j++) {
      var s0 = rot(w[j - 15], 7) ^ rot(w[j - 15], 18) ^ (w[j - 15] >>> 3), s1 = rot(w[j - 2], 17) ^ rot(w[j - 2], 19) ^ (w[j - 2] >>> 10)
      w[j] = (w[j - 16] + s0 + w[j - 7] + s1) | 0
    }
    var a = H[0], b = H[1], cc = H[2], d2 = H[3], e = H[4], f = H[5], g = H[6], h = H[7]
    for (j = 0; j < 64; j++) {
      var t1 = (h + (rot(e, 6) ^ rot(e, 11) ^ rot(e, 25)) + ((e & f) ^ (~e & g)) + K[j] + w[j]) | 0
      var t2 = ((rot(a, 2) ^ rot(a, 13) ^ rot(a, 22)) + ((a & b) ^ (a & cc) ^ (b & cc))) | 0
      h = g; g = f; f = e; e = (d2 + t1) | 0; d2 = cc; cc = b; b = a; a = (t1 + t2) | 0
    }
    H[0] = (H[0] + a) | 0; H[1] = (H[1] + b) | 0; H[2] = (H[2] + cc) | 0; H[3] = (H[3] + d2) | 0
    H[4] = (H[4] + e) | 0; H[5] = (H[5] + f) | 0; H[6] = (H[6] + g) | 0; H[7] = (H[7] + h) | 0
  }
  return H.map(function (x) { var s = (x >>> 0).toString(16); while (s.length < 8) s = '0' + s; return s }).join('')
}
function diff(a, b) { var n = 0; for (var i = 0; i < a.length; i++) { var x = parseInt(a[i], 16) ^ parseInt(b[i], 16); while (x) { n += x & 1; x >>= 1 } } return n }
print('SHA-256  //  64 rounds, by hand')
print('')
print('the empty string   ' + sha256(''))
print('"abc"              ' + sha256('abc'))
print('')
var one = sha256('pino'), two = sha256('pinp')
print('"pino"             ' + one)
print('"pinp"             ' + two)
print('')
print('one letter changed, ' + diff(one, two) + ' of 256 bits came out different.')

more of these