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
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.
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.')