module sha256

module lib/sha256.mu

import "sha256"

sha256 — the SHA-256 cryptographic hash (FIPS 180-4), pure mu.

sha256.sum(bytes) -> a 32-byte digest (list of byte values)

bytes is a list of byte values (0..255); use encoding.bytes(str) to hash a string and encoding.hex(digest) for a hex string. All arithmetic stays within 32 bits via MASK; rotates mask the low n bits BEFORE the left shift so intermediates never exceed 2^32 (mu ints are ~63-bit); ~x within 32 bits is (MASK ^ x).

Values

MASK#

MASK

Undocumented.

Source lib/sha256.mu:10
MASK := 4294967295   // 0xFFFFFFFF

Functions

sum#

fn sum(msg)

sum(msg) : msg is a list of byte ints -> a 32-byte digest list.

Source lib/sha256.mu:34
fn sum(msg) {
  k := _k()
  h := [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]

  // --- padding ---
  ml := len(msg) * 8               // message length in bits
  m := []
  i := 0
  while i < len(msg) { m = append(m, msg[i])  i = i + 1 }
  m = append(m, 128)               // 0x80
  while (len(m) % 64) != 56 { m = append(m, 0) }
  bi := 0
  while bi < 8 { m = append(m, (ml >> (8 * (7 - bi))) & 255)  bi = bi + 1 }   // 64-bit big-endian length

  // --- process each 64-byte block ---
  blk := 0
  while blk < len(m) {
    w := []
    t := 0
    while t < 16 {
      o := blk + t * 4
      word := (((m[o] << 24) | (m[o+1] << 16)) | (m[o+2] << 8)) | m[o+3]
      w = append(w, word & MASK)
      t = t + 1
    }
    while t < 64 {
      v := (((_ssig1(w[t-2]) + w[t-7]) + _ssig0(w[t-15])) + w[t-16]) & MASK
      w = append(w, v)
      t = t + 1
    }
    a := h[0]  b := h[1]  c := h[2]  d := h[3]  e := h[4]  f := h[5]  g := h[6]  hh := h[7]
    t = 0
    while t < 64 {
      t1 := ((((hh + _bsig1(e)) + _ch(e, f, g)) + k[t]) + w[t]) & MASK
      t2 := (_bsig0(a) + _maj(a, b, c)) & MASK
      hh = g  g = f  f = e
      e = (d + t1) & MASK
      d = c  c = b  b = a
      a = (t1 + t2) & MASK
      t = t + 1
    }
    h[0] = (h[0] + a) & MASK  h[1] = (h[1] + b) & MASK  h[2] = (h[2] + c) & MASK  h[3] = (h[3] + d) & MASK
    h[4] = (h[4] + e) & MASK  h[5] = (h[5] + f) & MASK  h[6] = (h[6] + g) & MASK  h[7] = (h[7] + hh) & MASK
    blk = blk + 64
  }

  // --- serialize 8 words big-endian -> 32 bytes ---
  out := []
  wi := 0
  while wi < 8 {
    bb := 0
    while bb < 4 { out = append(out, (h[wi] >> (8 * (3 - bb))) & 255)  bb = bb + 1 }
    wi = wi + 1
  }
  return out
}

Internal helpers

Underscore-prefixed names are implementation detail. They are listed so the module's source reads without surprises, not as API — they may change at any time.

_bsig0(x)
_bsig1(x)
_ch(x, y, z)
_k()round constants K[0..63]
_maj(x, y, z)
_rotr(x, n)
_shr(x, n)
_ssig0(x)
_ssig1(x)