Crypto Scripts

Instructions

Copy script and save it with a .rb extension. Then, open Terminal, and enter:

cd ~/your_path/your_script_folder
ruby script_name.rb

ADD

Add

# -----
# Input
# -----
# defaults
numbers =
[0b01000000000000001111111111111111,
0b01000000000000000000000000000000,
0b01000000000000000000000000000000,
0b01000000000000000000000000000000,
0b01000000000000000000000000000000,
]
# arguments passed
if ARGV.size >= 2
  numbers = ARGV.map {|x| x.to_i(2)} # convert binary strings to integers
end

# ---------
# Animation
# ---------
total = numbers.inject(:+)
width = total.to_s(2).size

(numbers.size + 1).times do |i|
  system "clear"
  numbers.each.with_index do |x, j|
    print ("%032b" % x).rjust(width, " ")
    if j > 0
      if j <= i
        print " +"
      end
    end
    print "\n"
  end
  puts "--------------------------------".rjust(width, " ")
  
  if i == 0
    puts "" # numbers[0].to_s(2).rjust(32, "0").rjust(width, " ")
  elsif i < numbers.size # for each addition
    puts numbers[0..i].inject(:+).to_s(2).rjust(32, "0").rjust(width, " ")
    sleep 0.4 if i == numbers.size-1 # slight delay before the modulus function
  else
    puts (numbers[0..i].inject(:+) % 2**32).to_s(2).rjust(32, "0").rjust(width, " ") + " mod 2**32"
  end
  sleep 0.4
end
sleep 1.0 


Blocks

Blocks

require_relative "sha256lib.rb"

# -------
# Default
# -------
if !defined? $input
  # default
  $input = "abc"
  $message = $input.unpack("B*")[0]
  # argument passed
  $message = ARGV[0] if ARGV[0] # accept binary message string
  
  # calculate padded message
  $padded = padding($message)
end

# --------------
# Message Blocks
# --------------
$blocks = split($padded, 512)

# ---------
# Animation
# ---------
system "clear"
puts $state + "\n" if defined? $state
puts "--------------"
puts "message blocks:"
puts "--------------"
delay(:normal)

system "clear"
puts $state + "\n" if defined? $state
puts "--------------"
puts "message blocks:"
puts "--------------"
$blocks.each.with_index do |block, i|
  puts "#{i}: #{block}"
  delay(:normal)
end
delay(:slow)

# Save Final State
contents = "" # contruct string with each block so we can use it inside the final frame
$blocks.each.with_index do |block, i|
  contents << "#{i}: #{block}"
  contents << "\n" if i < $blocks.size - 1 # do not add extra new line after last block
end

$state = <<-FRAME
#{$state}
--------------
message blocks:
--------------
#{contents}
FRAME

Ch

Ch

# coding: utf-8
require_relative "sha256lib.rb"

# ------
# Choice
# ------
# Ch(x, y, z) = (x & y) ^ (~x & z)
#
# For each x bit:
#   * If x is 1 choose y
#   * If x is 0 choose z

# -----
# Input
# -----
# defaults
x = 0b00000000111111110000000011111111 # 0x428a2f98
y = 0b00000000000000001111111111111111 # 0x71374491
z = 0b11111111111111110000000000000000 # 0xb5c0fbcf
# arguments passed
if ARGV.size == 3
  x = ARGV[0].to_i(2)
  y = ARGV[1].to_i(2)
  z = ARGV[2].to_i(2)
end

# ---------
# Animation
# ---------
32.downto(1) do |i|
  system "clear"
  puts "▼".rjust(i+3, " ")
  puts "x: #{bits(x)}" #{bits(x)[i-1]}
  puts "y: #{bits(y)} #{bits(x)[i-1] == '1' ? '◄' : ''}"
  puts "z: #{bits(z)} #{bits(x)[i-1] == '1' ? '' : '◄'}"
  puts "   #{'-'*32}"
  puts bits( (x & y) ^ (~x & z) )[i-1..-1].rjust(35, " ")
  sleep(0.1)
end
sleep 1

Compression

Compression

# coding: utf-8
require_relative "sha256lib.rb"

# -------
# Default
# -------
if !defined? $input
  $input = "abc"
  $message = $input.unpack("B*")[0] # 011000010110001001100011
  $padded = padding($message)
  $blocks = split($padded, 512)

  # message block
  $block_number = 0 # message block number
  $block = $blocks[$block_number]
  
  # arguments passed
  if ARGV[0] # message block
    $block = ARGV[0].rjust(512, "0") # accept binary string as message block
  end

  # message schedule
  $schedule = calculate_schedule($block)
end

# Starting Hash Values - Use Initital Hash Values or hash values from previous compression
if $block_number == 0
  initial = IV          # Use initial hash values
  $hash = initial.clone # Set the initial hash values
else
  initial = $hash.clone # Use the result of the previous compression
end

# Schedule (Wt)
w = $schedule

# Constants (Kt)
k = K

# --------
# Settings
# --------
indent = " " * 2

# ---------
# Animation
# ---------

# Start
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number})"
puts "#{indent}-----------"
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:normal)

# Start
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:normal)

# Start
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts
puts
puts
puts
puts
puts
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:normal)

# Start
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts
puts
puts
puts
puts
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:normal)

# Start
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts
puts
puts
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:slowest)

# Start
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
puts
puts
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:normal)

# Start
t1 = add(w[0], k[0], usigma1($hash[4]), ch($hash[4], $hash[5], $hash[6]), $hash[7])
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0  = #{bits(t1)}"
puts
puts
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:normal)

# Start
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0  = #{bits(t1)}"
puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
puts
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:normal)

# Start
t2 = add(usigma0($hash[0]), maj($hash[0], $hash[1], $hash[2]))
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0  = #{bits(t1)}"
puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
puts
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:slowest)

# Start
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0  = #{bits(t1)}"
puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
puts
puts "#{indent}a = #{bits($hash[0])} ↓"
puts "#{indent}b = #{bits($hash[1])} ↓"
puts "#{indent}c = #{bits($hash[2])} ↓"
puts "#{indent}d = #{bits($hash[3])} ↓"
puts "#{indent}e = #{bits($hash[4])} ↓"
puts "#{indent}f = #{bits($hash[5])} ↓"
puts "#{indent}g = #{bits($hash[6])} ↓"
puts "#{indent}h = #{bits($hash[7])}"
delay(:normal)

# Start - Rotate Register Upwards
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0  = #{bits(t1)}"
puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
puts
puts "#{indent}a = "
puts "#{indent}b = #{bits($hash[0])} ↓"
puts "#{indent}c = #{bits($hash[1])} ↓"
puts "#{indent}d = #{bits($hash[2])} ↓"
puts "#{indent}e = #{bits($hash[3])} ↓"
puts "#{indent}f = #{bits($hash[4])} ↓"
puts "#{indent}g = #{bits($hash[5])} ↓"
puts "#{indent}h = #{bits($hash[6])} ↓"
delay(:normal)

# Start - a is T1 + T2
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0  = #{bits(t1)}"
puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
puts
puts "#{indent}a =                                  <- T1 + T2"
puts "#{indent}b = #{bits($hash[0])}"
puts "#{indent}c = #{bits($hash[1])}"
puts "#{indent}d = #{bits($hash[2])}"
puts "#{indent}e = #{bits($hash[3])}"
puts "#{indent}f = #{bits($hash[4])}"
puts "#{indent}g = #{bits($hash[5])}"
puts "#{indent}h = #{bits($hash[6])}"
delay(:normal)

# Start - a is T1 + T2
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0  = #{bits(t1)}"
puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
puts
puts "#{indent}a = #{bits(add(t1, t2))} <- T1 + T2"
puts "#{indent}b = #{bits($hash[0])}"
puts "#{indent}c = #{bits($hash[1])}"
puts "#{indent}d = #{bits($hash[2])}"
puts "#{indent}e = #{bits($hash[3])}"
puts "#{indent}f = #{bits($hash[4])}"
puts "#{indent}g = #{bits($hash[5])}"
puts "#{indent}h = #{bits($hash[6])}"
delay(:normal)

# Start - Add T1 to e
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0  = #{bits(t1)}"
puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
puts
puts "#{indent}a = #{bits(add(t1, t2))} <- T1 + T2"
puts "#{indent}b = #{bits($hash[0])}"
puts "#{indent}c = #{bits($hash[1])}"
puts "#{indent}d = #{bits($hash[2])}"
puts "#{indent}e = #{bits($hash[3])} + T1"
puts "#{indent}f = #{bits($hash[4])}"
puts "#{indent}g = #{bits($hash[5])}"
puts "#{indent}h = #{bits($hash[6])}"
delay(:normal)

# Start - Add T1 to e
system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
puts "#{indent}K0 = #{bits(k[0])} (constant)"
puts
puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0  = #{bits(t1)}"
puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
puts
puts "#{indent}a = #{bits(add(t1, t2))} <- T1 + T2"
puts "#{indent}b = #{bits($hash[0])}"
puts "#{indent}c = #{bits($hash[1])}"
puts "#{indent}d = #{bits($hash[2])}"
puts "#{indent}e = #{bits(add($hash[3], t1))} + T1"
puts "#{indent}f = #{bits($hash[4])}"
puts "#{indent}g = #{bits($hash[5])}"
puts "#{indent}h = #{bits($hash[6])}"
delay(:slowest)

# Apply Changes
$hash[7] = $hash[6]
$hash[6] = $hash[5]
$hash[5] = $hash[4]
$hash[4] = $hash[3]
$hash[3] = $hash[2]
$hash[2] = $hash[1]
$hash[1] = $hash[0]
$hash[0] = ""

$hash[4] = add($hash[4], t1)
$hash[0] = add(t1, t2)

# -------------------
# Remaining Animation
# -------------------
1.upto(63) do |i|

  # T1 = h + Σ1(e) + Ch(e, f, g) + Kt + Wt
  t1 = add(w[i], k[i], usigma1($hash[4]), ch($hash[4], $hash[5], $hash[6]), $hash[7])

  # T2 = Σ0(a) + Maj(a, b, c)
  t2 = add(usigma0($hash[0]), maj($hash[0], $hash[1], $hash[2]))

  # Frame - T1, T2
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
  puts "#{indent}-----------"
  puts "#{indent}W#{i} = #{bits(w[i])} (message schedule)"
  puts "#{indent}K#{i} = #{bits(k[i])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K#{i.to_s.ljust(2, " ")} + W#{i.to_s.ljust(2, " ")} = #{bits(t1)}"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
  puts
  puts "#{indent}a = #{bits($hash[0])} <- T1 + T2"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])} + T1"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:fastest)

  # Frame - Shift Up
  $hash[7] = $hash[6]
  $hash[6] = $hash[5]
  $hash[5] = $hash[4]
  $hash[4] = $hash[3]
  $hash[3] = $hash[2]
  $hash[2] = $hash[1]
  $hash[1] = $hash[0]
  $hash[0] = ""

  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
  puts "#{indent}-----------"
  puts "#{indent}W#{i} = #{bits(w[i])} (message schedule)"
  puts "#{indent}K#{i} = #{bits(k[i])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K#{i.to_s.ljust(2, " ")} + W#{i.to_s.ljust(2, " ")} = #{bits(t1)}"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
  puts
  puts "#{indent}a =                                  <- T1 + T2"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])} + T1"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:fastest)

  # Frame - Update e and a
  $hash[4] = ($hash[4] + t1) % 2 ** 32
  $hash[0] = (t1 + t2) % 2 ** 32

  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
  puts "#{indent}-----------"
  puts "#{indent}W#{i} = #{bits(w[i])} (message schedule)"
  puts "#{indent}K#{i} = #{bits(k[i])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K#{i.to_s.ljust(2, " ")} + W#{i.to_s.ljust(2, " ")} = #{bits(t1)}"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)                = #{bits(t2)}"
  puts
  puts "#{indent}a = #{bits($hash[0])} <- T1 + T2"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])} + T1"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:fastest)
end
delay(:slowest)

system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts
puts
puts
puts
puts
puts
puts "#{indent}a = #{bits($hash[0])}"
puts "#{indent}b = #{bits($hash[1])}"
puts "#{indent}c = #{bits($hash[2])}"
puts "#{indent}d = #{bits($hash[3])}"
puts "#{indent}e = #{bits($hash[4])}"
puts "#{indent}f = #{bits($hash[5])}"
puts "#{indent}g = #{bits($hash[6])}"
puts "#{indent}h = #{bits($hash[7])}"
delay(:normal)

system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts
puts
puts
puts
puts
puts
puts "#{indent}a = #{" " * 32}   #{bits($hash[0])}"
puts "#{indent}b = #{" " * 32}   #{bits($hash[1])}"
puts "#{indent}c = #{" " * 32}   #{bits($hash[2])}"
puts "#{indent}d = #{" " * 32}   #{bits($hash[3])}"
puts "#{indent}e = #{" " * 32}   #{bits($hash[4])}"
puts "#{indent}f = #{" " * 32}   #{bits($hash[5])}"
puts "#{indent}g = #{" " * 32}   #{bits($hash[6])}"
puts "#{indent}h = #{" " * 32}   #{bits($hash[7])}"
delay(:normal)

system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts
puts
puts
puts
puts
puts "#{indent}    H#{$block_number}:"
puts "#{indent}a = #{bits(initial[0])}   #{bits($hash[0])}"
puts "#{indent}b = #{bits(initial[1])}   #{bits($hash[1])}"
puts "#{indent}c = #{bits(initial[2])}   #{bits($hash[2])}"
puts "#{indent}d = #{bits(initial[3])}   #{bits($hash[3])}"
puts "#{indent}e = #{bits(initial[4])}   #{bits($hash[4])}"
puts "#{indent}f = #{bits(initial[5])}   #{bits($hash[5])}"
puts "#{indent}g = #{bits(initial[6])}   #{bits($hash[6])}"
puts "#{indent}h = #{bits(initial[7])}   #{bits($hash[7])}"
delay(:normal)

system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts
puts
puts
puts
puts
puts "#{indent}    H#{$block_number}:"
puts "#{indent}a = #{bits(initial[0])} + #{bits($hash[0])}"
puts "#{indent}b = #{bits(initial[1])} + #{bits($hash[1])}"
puts "#{indent}c = #{bits(initial[2])} + #{bits($hash[2])}"
puts "#{indent}d = #{bits(initial[3])} + #{bits($hash[3])}"
puts "#{indent}e = #{bits(initial[4])} + #{bits($hash[4])}"
puts "#{indent}f = #{bits(initial[5])} + #{bits($hash[5])}"
puts "#{indent}g = #{bits(initial[6])} + #{bits($hash[6])}"
puts "#{indent}h = #{bits(initial[7])} + #{bits($hash[7])}"
delay(:slow)

system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number} -> H#{$block_number+1})"
puts "#{indent}-----------"
puts
puts
puts
puts
puts
puts "#{indent}    H#{$block_number+1}:"
puts "#{indent}a = #{bits(add(initial[0], $hash[0]))}"
puts "#{indent}b = #{bits(add(initial[1], $hash[1]))}"
puts "#{indent}c = #{bits(add(initial[2], $hash[2]))}"
puts "#{indent}d = #{bits(add(initial[3], $hash[3]))}"
puts "#{indent}e = #{bits(add(initial[4], $hash[4]))}"
puts "#{indent}f = #{bits(add(initial[5], $hash[5]))}"
puts "#{indent}g = #{bits(add(initial[6], $hash[6]))}"
puts "#{indent}h = #{bits(add(initial[7], $hash[7]))}"
delay(:slow)

system "clear"
puts $state + "\n" if defined? $state
puts "#{indent}-----------"
puts "#{indent}compression: (H#{$block_number+1})"
puts "#{indent}-----------"
puts "#{indent}a = #{bits(add(initial[0], $hash[0]))}"
puts "#{indent}b = #{bits(add(initial[1], $hash[1]))}"
puts "#{indent}c = #{bits(add(initial[2], $hash[2]))}"
puts "#{indent}d = #{bits(add(initial[3], $hash[3]))}"
puts "#{indent}e = #{bits(add(initial[4], $hash[4]))}"
puts "#{indent}f = #{bits(add(initial[5], $hash[5]))}"
puts "#{indent}g = #{bits(add(initial[6], $hash[6]))}"
puts "#{indent}h = #{bits(add(initial[7], $hash[7]))}"
delay(:end)

$hash[0] = add(initial[0], $hash[0])
$hash[1] = add(initial[1], $hash[1])
$hash[2] = add(initial[2], $hash[2])
$hash[3] = add(initial[3], $hash[3])
$hash[4] = add(initial[4], $hash[4])
$hash[5] = add(initial[5], $hash[5])
$hash[6] = add(initial[6], $hash[6])
$hash[7] = add(initial[7], $hash[7])

# Save Final State
$state = <<-FRAME
#{$state}
#{indent}-----------
#{indent}compression: (H#{$block_number+1})
#{indent}-----------
#{indent}a = #{bits($hash[0])}
#{indent}b = #{bits($hash[1])}
#{indent}c = #{bits($hash[2])}
#{indent}d = #{bits($hash[3])}
#{indent}e = #{bits($hash[4])}
#{indent}f = #{bits($hash[5])}
#{indent}g = #{bits($hash[6])}
#{indent}h = #{bits($hash[7])}
FRAME


Constants

Constants

# coding: utf-8
require_relative "sha256lib.rb"

# ---------
# Constants - K
# ---------
# SHA256 uses the same sequence of sixty-four constant 32-bit words.
#
# These words represent the first thirty-two bits of the fractional parts of the cube roots of the first sixty-four prime numbers. These are "nothing up my sleeve" constants.

# The first sixty-four primes
primes =  [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311]

# Store results for display later
roots = [];
constants = [];
hexs = [];

# For each prime number
primes.each do |prime|

  # Get the cube root of the prime
  root = prime ** (1/3.0)
  roots << root

  # Get fractional part of the number
  fractional = root - root.floor

  # Convert fractional part to hexadecimal
  #
  # Example:
  #
  #  3√2 = 1.259921049895
  #        0.259921049895       <- fractional part is what we want
  #
  #  Keep multiplying the fractional part by 16 and taking the integer as the next hex character.
  #
  #        0.259921049895 * 16  <- multiply by 16
  #      = 4.15873679832        <- the integer part is used for the hexadecimal result
  #
  #        0.15873679832  * 16
  #      = 2.53978877312
  #
  #        0.53978877312  * 16
  #      = 8.63662036992
  #
  #        ...
  #
  #  Hex:  428a2f98
  #
  hex = ""
  8.times do # 32 bits = 8 hex characters
    product = fractional * 16 # multiply fraction by 16
    carry = product.floor     # the integer part of the product is used for the next hexadecimal character
    fractional = product - product.floor # the fractional part of the product is used for next round
    hex << carry.to_s(16)
  end

  # Save results
  hexs << hex
  constants << hex.to_i(16)
end

# ---------
# Animation
# ---------
system "clear"
puts "-------------"
puts "constants (K)"
puts "-------------"
sleep 0.1
(64+1+3).times do |i| # extra 3 iterations to see through
  system "clear"
  puts "-------------"
  puts "constants (K)"
  puts "-------------"
  i.times do |j|
    # 3 or more behind
    if j <= i-4
      puts "#{j.to_s.ljust(2, " ")} = #{bits(constants[j])}"
    end

    # 2 behind
    if j == i-3
      puts "#{j.to_s.ljust(2, " ")} = 3√#{primes[j].to_s.ljust(3, " ")} =   #{bits(constants[j])}"
    end

    # 1 behind
    if j == i-2
      puts "#{j.to_s.ljust(2, " ")} = 3√#{primes[j].to_s.ljust(3, " ")} =   #{(roots[j] - roots[j].floor).to_s[2..-1]}"
    end

    # current
    if j == i-1
      puts "#{j.to_s.ljust(2, " ")} = 3√#{primes[j].to_s.ljust(3, " ")} = #{roots[j]}"
    end

    # dont try and show trailing 64, 65, 66 (this is just to format last 3)
    break if j >= 63
  end

  sleep 0.1
end
sleep 1


Expansion

Expansion

# coding: utf-8
require_relative "sha256lib.rb"

# -------
# Default
# -------
if !defined? $input
  # default
  $input = "abc"
  $message = $input.unpack("B*")[0] # 011000010110001001100011
  $padded = padding($message)
  $blocks = split($padded, 512)
  $block_number = 0               # message block number
  $block = $blocks[$block_number]
  $t = 63 # the word in the message schedule we want to calculate
  
  # arguments passed
  if ARGV[0] # message block
    $block = ARGV[0].rjust(512, "0") # accept binary string as message block
  end
  
  if ARGV[1] # word number
    $t = ARGV[1].to_i # choose a word in the message schedule to calculate (16-63)
  end
end

# The message block provides the first 16 words for the message schedule (512 bits / 32 bits = 16 words)
$schedule = $block.scan(/.{32}/).map { |w| w.to_i(2) } # convert from binary string to integer for calculations

# Calculate remaining 48 words
16.upto(63) do |i|
  $schedule << add(sigma1($schedule[i - 2]), $schedule[i - 7], sigma0($schedule[i - 15]), $schedule[i - 16])
end

# convenient variables for word numbers in the schedule
t    = ($t-0).to_s.ljust(2, " ")
t_1  = ($t-1).to_s.ljust(2, " ")
t_2  = ($t-2).to_s.ljust(2, " ")
t_3  = ($t-3).to_s.ljust(2, " ")
t_4  = ($t-4).to_s.ljust(2, " ")
t_5  = ($t-5).to_s.ljust(2, " ")
t_6  = ($t-6).to_s.ljust(2, " ")
t_7  = ($t-7).to_s.ljust(2, " ")
t_8  = ($t-8).to_s.ljust(2, " ")
t_9  = ($t-9).to_s.ljust(2, " ")
t_10 = ($t-10).to_s.ljust(2, " ")
t_11 = ($t-11).to_s.ljust(2, " ")
t_12 = ($t-12).to_s.ljust(2, " ")
t_13 = ($t-13).to_s.ljust(2, " ")
t_14 = ($t-14).to_s.ljust(2, " ")
t_15 = ($t-15).to_s.ljust(2, " ")
t_16 = ($t-16).to_s.ljust(2, " ")

# --------
# Settings
# --------
indent = " " * 2

# ---------
# Animation
# ---------

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits($schedule[$t-15])} ROTR 7
#{indent}W#{t_14} #{bits($schedule[$t-14])}      #{bits($schedule[$t-15])} ROTR 18
#{indent}W#{t_13} #{bits($schedule[$t-13])}      #{bits($schedule[$t-15])}  SHR 3
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
7.times do |i|
  system "clear"
  puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(rotr(i + 1, $schedule[$t-15]))} ROTR 7
#{indent}W#{t_14} #{bits($schedule[$t-14])}      #{bits($schedule[$t-15])} ROTR 18
#{indent}W#{t_13} #{bits($schedule[$t-13])}      #{bits($schedule[$t-15])}  SHR 3
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
  delay(:fastest)
end
delay(:normal)

# Frame
18.times do |i|
  system "clear"
  puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(rotr(7, $schedule[$t-15]))} ROTR 7
#{indent}W#{t_14} #{bits($schedule[$t-14])}      #{bits(rotr(i + 1, $schedule[$t-15]))} ROTR 18
#{indent}W#{t_13} #{bits($schedule[$t-13])}      #{bits($schedule[$t-15])}  SHR 3
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
  delay(:fastest)
end
delay(:normal)

# Frame
3.times do |i|
  system "clear"
  puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(rotr(7, $schedule[$t-15]))} ROTR 7
#{indent}W#{t_14} #{bits($schedule[$t-14])}      #{bits(rotr(18, $schedule[$t-15]))} ROTR 18
#{indent}W#{t_13} #{bits($schedule[$t-13])}      #{bits(shr(i + 1, $schedule[$t-15]))}  SHR 3
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:fastest)
end
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(rotr(7, $schedule[$t-15]))} ROTR 7
#{indent}W#{t_14} #{bits($schedule[$t-14])}      #{bits(rotr(18, $schedule[$t-15]))} ROTR 18
#{indent}W#{t_13} #{bits($schedule[$t-13])}      #{bits(shr(3, $schedule[$t-15]))} XOR
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(rotr(7, $schedule[$t-15]))}
#{indent}W#{t_14} #{bits($schedule[$t-14])}      #{bits(rotr(18, $schedule[$t-15]) ^ shr(3, $schedule[$t-15]))} XOR
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(rotr(7, $schedule[$t-15]) ^ rotr(18, $schedule[$t-15]) ^ shr(3, $schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(sigma0($schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }  ->  #{bits($schedule[$t-7])}
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(sigma0($schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }  ->  #{bits($schedule[$t-7])}
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }      #{bits($schedule[$t-2])} ROTR 17
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }      #{bits($schedule[$t-2])} ROTR 19
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }  ->  #{bits($schedule[$t-2])}  SHR 10
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
17.times do |i|
  system "clear"
  puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(sigma0($schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }  ->  #{bits($schedule[$t-7])}
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }      #{bits(rotr(i + 1, $schedule[$t-2]))} ROTR 17
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }      #{bits($schedule[$t-2])} ROTR 19
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }  ->  #{bits($schedule[$t-2])}  SHR 10
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:fastest)
end
delay(:normal)

# Frame
19.times do |i|
  system "clear"
  puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(sigma0($schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }  ->  #{bits($schedule[$t-7])}
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }      #{bits(rotr(17, $schedule[$t-2]))} ROTR 17
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }      #{bits(rotr(i + 1, $schedule[$t-2]))} ROTR 19
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }  ->  #{bits($schedule[$t-2])}  SHR 10
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:fastest)
end
delay(:normal)

# Frame
10.times do |i|
  system "clear"
  puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(sigma0($schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }  ->  #{bits($schedule[$t-7])}
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }      #{bits(rotr(17, $schedule[$t-2]))} ROTR 17
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }      #{bits(rotr(19, $schedule[$t-2]))} ROTR 19
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }  ->  #{bits(shr(i + 1, $schedule[$t-2]))}  SHR 10
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:fastest)
end
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(sigma0($schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }  ->  #{bits($schedule[$t-7])}
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }      #{bits(rotr(17, $schedule[$t-2]))} XOR
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }      #{bits(rotr(19, $schedule[$t-2]))}
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }  ->  #{bits(shr(10, $schedule[$t-2]))}
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(sigma0($schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }  ->  #{bits($schedule[$t-7])}
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }      #{bits(rotr(19, $schedule[$t-2]) ^ rotr(17, $schedule[$t-2]))} XOR
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }  ->  #{bits(shr(10, $schedule[$t-2]))}
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:normal)

# Frame
system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(sigma0($schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }  ->  #{bits($schedule[$t-7])}
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }  ->  #{bits(rotr(19, $schedule[$t-2]) ^ rotr(17, $schedule[$t-2]) ^ shr(10, $schedule[$t-2]))} σ1
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   }                                  = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:slow)

# Frame
result = add(sigma1($schedule[$t-2]), $schedule[$t-7], sigma0($schedule[$t-15]), $schedule[$t-16])

system "clear"
puts <<-MS
#{indent}----------------
#{indent}message schedule: (expansion)
#{indent}----------------
#{indent}W#{t_16} #{bits($schedule[$t-16])}  ->  #{bits($schedule[$t-16])}
#{indent}W#{t_15} #{bits($schedule[$t-15])}  ->  #{bits(sigma0($schedule[$t-15]))} σ0
#{indent}W#{t_14} #{bits($schedule[$t-14])}
#{indent}W#{t_13} #{bits($schedule[$t-13])}
#{indent}W#{t_12} #{bits($schedule[$t-12])}
#{indent}W#{t_11} #{bits($schedule[$t-11])}
#{indent}W#{t_10} #{bits($schedule[$t-10])}
#{indent}W#{t_9 } #{bits($schedule[$t-9]) }
#{indent}W#{t_8 } #{bits($schedule[$t-8]) }
#{indent}W#{t_7 } #{bits($schedule[$t-7]) }  ->  #{bits($schedule[$t-7])}
#{indent}W#{t_6 } #{bits($schedule[$t-6]) }
#{indent}W#{t_5 } #{bits($schedule[$t-5]) }
#{indent}W#{t_4 } #{bits($schedule[$t-4]) }
#{indent}W#{t_3 } #{bits($schedule[$t-3]) }
#{indent}W#{t_2 } #{bits($schedule[$t-2]) }  ->  #{bits(sigma1($schedule[$t-2]))} σ1
#{indent}W#{t_1 } #{bits($schedule[$t-1]) }
#{indent}W#{t   } #{bits(result)} = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)
MS
delay(:end)

# Spare Frame
# system "clear"
# puts <<-MS
# 47 00000110010111000100001111011010  ->  00000110010111000100001111011010
# 48 11111011001111101000100111001011  ->  11111011001111101000100111001011 ROTR 7
# 49 11001100011101100001011111011011      11111011001111101000100111001011 ROTR 18
# 50 10111001111001100110110000110100      11111011001111101000100111001011  SHR 3
# 51 10101001100110010011011001100111
# 52 10000100101110101101111011011101
# 53 11000010000101000110001010111100
# 54 00010100100001110100011100101100
# 55 10110010000011110111101010011001
# 56 11101111010101111011100111001101  ->  11101111010101111011100111001101
# 57 11101011111001101011001000111000
# 58 10011111111000110000100101011110
# 59 01111000101111001000110101001011
# 60 10100100001111111100111100010101
# 61 01100110100010110010111111111000  ->  01100110100010110010111111111000 ROTR 17
# 62 11101110101010111010001011001100      01100110100010110010111111111000 ROTR 19
# 63                                       01100110100010110010111111111000  SHR 10
# MS
# sleep 0.2


Final

Final

  # coding: utf-8
  require_relative "sha256lib.rb"
  
  # -------
  # Default
  # -------
  if !defined? $input
    # default
    $input = "abc"
    # argument passed
    $input = ARGV[0] if ARGV[0] # only accept strings for now
    
    $message = $input.unpack("B*")[0] # 011000010110001001100011
    $padded = padding($message)
    $blocks = split($padded, 512)
    
    # Set initial hash state using initial hash values
    $hash = IV
  
    # For each message block
    $blocks.each do |block|
      # Prepare 64 word message schedule
      schedule = calculate_schedule(block)
  
      # Remember starting hash values
      initial = $hash.clone
  
      # Apply compression function to update hash values
      $hash = compression(initial, schedule, constants = K)
    end
  end
  
  # Start
  system "clear"
  puts $state + "\n" if defined? $state
  puts "----------------"
  puts "final hash value: (H#{$blocks.size})"
  puts "----------------"
  registers = ("a".."h").to_a
  8.times do |i|
    puts "#{registers[i]} = #{bits($hash[i])}"
  end
  delay(:slowest)
  
  # Frame - Hexadecimal
  system "clear"
  puts $state + "\n" if defined? $state
  puts "----------------"
  puts "final hash value: (H#{$blocks.size})"
  puts "----------------"
  8.times do |i|
    puts "#{registers[i]} = #{bits($hash[i])} = #{hex($hash[i])}"
  end
  delay(:slowest)
  
  # Frame - Concatenate
  $digest = ""
  8.times do |i|
    $digest << hex($hash[i])
    system "clear"
    puts $state + "\n" if defined? $state
    puts "----------------"
    puts "final hash value: (H#{$blocks.size})"
    puts "----------------"
    8.times do |j|
      puts "#{registers[j]} = #{bits($hash[j])} = #{hex($hash[j])}"
    end
    puts
    puts "#{$digest}"
    delay(:fastest)
  end
  delay(:end)
  delay(:end) # extra delay for the absolute final frame
  


Sha256 (Sha Lib)

Sha256

  # =======
  # SHA-256
  # =======
  
  # -----
  # Utils - Handy functions for converting integers and strings to binary
  # -----
  # Convert integer to binary string (32 bits)
  def bits(x, n = 32)
    if x >= 0
      return "%0#{n}b" % x
    else
      # Note: Ruby NOT function returns a negative number, and .to_s(2) displays this mathematical representation in base 2.
      # Note: So to get the expected unsigned notation you need to get the individual bits instead.
      # Note: When doing so, ignore the first bit because that's the sign bit.
      # https://www.calleerlandsson.com/rubys-bitwise-operators/
      return (n - 1).downto(0).map { |i| x[i] }.join
    end
  end
  
  # Convert integer to hexadecimal string (32 bits)
  def hex(i)
    return i.to_s(16).rjust(8, "0")
  end
  
  # Convert string to binary string
  def bitstring(string)
    bytes = string.bytes              # convert ascii characters to bytes (integers)
    binary = bytes.map { |x| bits(x, 8) } # convert bytes to binary strings (8 bits in a byte)
    return binary.join
  end
  
  # Use standard delay times between frames
  def delay(speed)
    if $delay == "enter"
      STDIN.gets # gets on its own will try and read the contents of files passed in through ARGV (then use STDIN if not)
    elsif $delay == "nodelay"
      sleep 0
    else
      # Set speed
      multiplier = 1
      case $delay
      when "fast"
        multiplier = 0.5
      end
  
      case speed
      when :fastest
        sleep 0.1 * multiplier
      when :fast
        sleep 0.2 * multiplier
      when :normal
        sleep 0.4 * multiplier
      when :slow
        sleep 0.6 * multiplier
      when :slowest
        sleep 0.8 * multiplier
      when :end
        sleep 1.0 * multiplier
      else
        sleep speed
      end
    end
  end
  
  # Detect input type base on prefix (i.e. binary, hex, or otherwise just a string)
  def input_type(input)
    # Check for hex or binary prefix
    case input[0..1]
    when "0b"
      # check it's a valid binary string
      if input[2..-1] =~ /[^0-1]/ # only 1s and 0s
        puts "Invalid binary string: #{input}"
        exit
      end
      return "binary"
    when "0x"
      # check it's a valid hex string
      if input[2..-1] !~ /^[0-9A-F]+$/i # only hex chars (case-insensitive)
        puts "Invalid hex string: #{input}"
        exit
      end
      return "hex"
    else
      return "string"
    end
  end
  
  # Convert input (hex, ascii) to array of bytes
  def bytes(input, type)
    case type
    when "binary"
      bin = input[2..-1] # trim 0b prefix
      if (bin.size % 8 == 0) # if we have been given a bitstring that makes up an exact number of bytes (8 bits in a byte)
        bytes = bin.scan(/.{8}/).map {|byte| byte.to_i(2)} # convert the bits to array of bytes (in decimal)
      else
        bytes = "(bitstring is not an exact amount of bytes)" # helpful note
      end
    when "hex"
      hex = input[2..-1] # trim 0x prefix
      bytes = [hex].pack("H*").unpack("C*") # convert hex string to bytes
    else
      bytes = input.bytes # convert ASCII string to bytes
    end
  
    return bytes
  end
  
  # ----------
  # Operations
  # ----------
  # Addition modulo 2**32
  def add(*x)
    total = x.inject(:+)
    return total % 2 ** 32 # limits result of addition to 32 bits
  end
  
  # Rotate right (circular right shift)
  def rotr(n, x)
    right = (x >> n)              # right shift
    left = (x << 32 - n)          # left shift
    result = right | left         # combine to create rotation effect
    return result & (2 ** 32 - 1) # use mask to truncate result to 32 bits
  end
  
  # Shift right
  def shr(n, x)
    result = x >> n
    return result
  end
  
  # ---------
  # Functions - Combined rotations and shifts using operations above
  # ---------
  # σ0
  def sigma0(x)
    return rotr(7, x) ^ rotr(18, x) ^ shr(3, x)
  end
  
  # σ1
  def sigma1(x)
    return rotr(17, x) ^ rotr(19, x) ^ shr(10, x)
  end
  
  # Σ0 (uppercase)
  def usigma0(x)
    return rotr(2, x) ^ rotr(13, x) ^ rotr(22, x)
  end
  
  # Σ1
  def usigma1(x)
    return rotr(6, x) ^ rotr(11, x) ^ rotr(25, x)
  end
  
  # Choice - Use first bit to choose the (1)second or (0)third bit
  def ch(x, y, z)
    return (x & y) ^ (~x & z)
  end
  
  # Majority - Result is the majority of the three bits
  def maj(x, y, z)
    return (x & y) ^ (x & z) ^ (y & z)
  end
  
  # -------------
  # Preprocessing
  # -------------
  # Pad binary string message to multiple of 512 bits
  def padding(message)
    l = message.size  # size of message (in bits)
    k = (448 - l - 1) % 512 # pad with zeros up to 448 bits (64 bits short of 512 bits)
    l64 = bits(l, 64) # binary representation of message size (64 bits in length)
    return message + "1" + ("0" * k) + l64 # don't forget "1" bit between message and padding
  end
  
  # Cut padded message in to 512-bit message blocks
  def split(message, size = 512)
    return message.scan(/.{#{size}}/)
  end
  
  # ----------------
  # Message Schedule
  # ----------------
  # Calculate the 64 words for the message schedule from the message block
  def calculate_schedule(block)
    # The message block provides the first 16 words for the message schedule (512 bits / 32 bits = 16 words)
    schedule = block.scan(/.{32}/).map { |w| w.to_i(2) } # convert from binary string to integer for calculations
  
    # Calculate remaining 48 words
    16.upto(63) do |i|
      schedule << add(sigma1(schedule[i - 2]), schedule[i - 7], sigma0(schedule[i - 15]), schedule[i - 16])
    end
  
    return schedule
  end
  
  # ---------
  # Constants
  # ---------
  # Constants = Cube roots of the first 64 prime numbers (first 32 bits of the fractional part)
  K = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311].map { |prime| prime ** (1 / 3.0) }.map { |i| (i - i.floor) }.map { |i| (i * 2 ** 32).floor }
  
  # -----------
  # Compression - Run compression function on the message schedule and constants
  # -----------
  # Initial Hash Values = Square roots of the first 8 prime numbers (first 32 bits of the fractional part)
  IV = [2, 3, 5, 7, 11, 13, 17, 19].map { |prime| prime ** (1 / 2.0) }.map { |i| (i - i.floor) }.map { |i| (i * 2 ** 32).floor }
  
  def compression(initial, schedule, constants)
    # state register - set initial values ready for the compression function
    h = initial[7]
    g = initial[6]
    f = initial[5]
    e = initial[4]
    d = initial[3]
    c = initial[2]
    b = initial[1]
    a = initial[0]
  
    # compression function - update state for every word in the message schedule
    64.times do |i|
      # calculate temporary words
      t1 = add(schedule[i], constants[i], usigma1(e), ch(e, f, g), h)
      t2 = add(usigma0(a), maj(a, b, c))
  
      # rotate state registers one position and add in temporary words
      h = g
      g = f
      f = e
      e = add(d, t1)
      d = c
      c = b
      b = a
      a = add(t1, t2)
    end
  
    # Final hash values are previous intermediate hash values added to output of compression function
    hash = []
    hash[7] = add(initial[7], h)
    hash[6] = add(initial[6], g)
    hash[5] = add(initial[5], f)
    hash[4] = add(initial[4], e)
    hash[3] = add(initial[3], d)
    hash[2] = add(initial[2], c)
    hash[1] = add(initial[1], b)
    hash[0] = add(initial[0], a)
    #hash = initial.zip(updated).map {|i, u| add(i, u)} # succinct method for adding one array on top of another (but not as readable)
  
    # return final state
    return hash
  end
  
  # -------
  # SHA-256 - Complete SHA-256 function
  # -------
  def sha256(string)
    # 0. Convert String to Binary
    # ---------------------------
    message = bitstring(string)
  
    # 1. Preprocessing
    # ----------------
    # Pad message
    padded = padding(message)
  
    # Split up in to 512 bit message blocks
    blocks = split(padded, 512)
  
    # 2. Hash Computation
    # -------------------
    # Set initial hash state using initial hash values
    hash = IV
  
    # For each message block
    blocks.each do |block|
      # Prepare 64 word message schedule
      schedule = calculate_schedule(block)
  
      # Remember starting hash values
      initial = hash.clone
  
      # Apply compression function to update hash values
      hash = compression(initial, schedule, constants = K)
    end
  
    # 3. Result
    # ---------
    # Convert hash values to hexadecimal and concatenate
    return hash.map { |w| "%08x" % w }.join
  end
  
  # --------
  # Examples
  # --------
  #require 'digest' # for testing
  #puts sha256("") == Digest::SHA256.hexdigest("") #=> e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  #puts sha256("abc") == Digest::SHA256.hexdigest("abc") #=> ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
  #puts sha256("learnmeabitcoin") == Digest::SHA256.hexdigest("learnmeabitcoin") #=> ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b58258739cb013db2
  #puts sha256("xyz"*1000) == Digest::SHA256.hexdigest("xyz"*1000)

Initial

Initial

  require_relative "sha256lib.rb"
  
  # -------------------
  # Initial Hash Values - H0
  # -------------------
  # The first thirty-two bits of the fractional parts of the square roots of the first eight prime numbers.
  #
  # Why?
  #  * These initial values don't _need_ to be anything in particular.
  #  * These are random-looking, irrational, and relatively independent from each other.
  #  * Using publicly-available numbers means that the initial hash values are less likely to have been chosen to allow for a backdoor.
  
  # H0 = 6a09e667
  # H1 = bb67ae85
  # H2 = 3c6ef372
  # H3 = a54ff53a
  # H4 = 510e527f
  # H5 = 9b05688c
  # H6 = 1f83d9ab
  # H7 = 5be0cd19
  
  primes = [2, 3, 5, 7, 11, 13, 17, 19]
  
  # --------
  # Settings
  # --------
  indent = " " * 2
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression:"
  puts "#{indent}-----------"
  registers = ("a".."h").to_a
  8.times do |i|
    puts "#{indent}#{registers[i]} ="
  end
  delay(:slow)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H0)"
  puts "#{indent}-----------"
  8.times do |i|
    puts "#{indent}#{registers[i]} ="
  end
  delay(:slow)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H0) (initial hash value)"
  puts "#{indent}-----------"
  8.times do |i|
    puts "#{indent}#{registers[i]} ="
  end
  delay(:slowest)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H0) (initial hash value)"
  puts "#{indent}-----------"
  8.times do |i|
    puts "#{indent}#{registers[i]} = √#{primes[i]}"
  end
  delay(:slowest)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H0) (initial hash value)"
  puts "#{indent}-----------"
  8.times do |i|
    puts "#{indent}#{registers[i]} = #{Math.sqrt(primes[i]).round(10)}"
  end
  delay(:slow)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H0) (initial hash value)"
  puts "#{indent}-----------"
  8.times do |i|
    puts "#{indent}#{registers[i]} = #{(Math.sqrt(primes[i]) - Math.sqrt(primes[i]).floor).round(10)}"
  end
  delay(:slow)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H0) (initial hash value)"
  puts "#{indent}-----------"
  8.times do |i|
    puts "#{indent}#{registers[i]} = #{(Math.sqrt(primes[i]) - Math.sqrt(primes[i]).floor).round(10)} * 2^32"
  end
  delay(:slow)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H0) (initial hash value)"
  puts "#{indent}-----------"
  8.times do |i|
    puts "#{indent}#{registers[i]} = #{((Math.sqrt(primes[i]) - Math.sqrt(primes[i]).floor) * 2 ** 32).floor}"
  end
  delay(:slow)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H0) (initial hash value)"
  puts "#{indent}-----------"
  8.times do |i|
    puts "#{indent}#{registers[i]} = #{bits(((Math.sqrt(primes[i]) - Math.sqrt(primes[i]).floor) * 2 ** 32).floor)}"
  end
  delay(:slow)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (H0)"
  puts "#{indent}-----------"
  8.times do |i|
    puts "#{indent}#{registers[i]} = #{bits(((Math.sqrt(primes[i]) - Math.sqrt(primes[i]).floor) * 2 ** 32).floor)}"
  end
  delay(:end)


Maj

Maj

  # coding: utf-8
  require_relative "sha256lib.rb"
  
  # --------
  # Majority
  # --------
  # Maj(x, y, z) = (x & y) ^ (x & z) ^ (y & z)
  #
  # Use the majority of x, y, z to set the result bit.
  
  # -----
  # Input
  # -----
  # defaults
  x = 0b00000000111111110000000011111111 # 0x428a2f98
  y = 0b00000000000000001111111111111111 # 0x71374491
  z = 0b11111111111111110000000000000000 # 0xb5c0fbcf
  # arguments passed
  if ARGV.size == 3
    x = ARGV[0].to_i(2)
    y = ARGV[1].to_i(2)
    z = ARGV[2].to_i(2)
  end
  
  # ---------
  # Animation
  # ---------
  32.downto(1) do |i|
    system "clear"
    maj = bits( (x & y) ^ (x & z) ^ (y & z) )
    puts "▼".rjust(i+3, " ")
    puts "x: #{bits(x)} #{bits(x)[i-1]}"
    puts "y: #{bits(y)} #{bits(y)[i-1]}"
    puts "z: #{bits(z)} #{bits(z)[i-1]}"
    puts "   #{'-'*32}"
    puts maj[i-1..-1].rjust(35, " ")
    sleep(0.1)
  end
  sleep 1


Message

Message

  require_relative 'sha256lib.rb'
  
  # -------
  # Default
  # -------
  if !defined? $input
    # default
    $input   = "abc"
    $type    = "string"
    # argument passed
    $input = ARGV[0] if ARGV[0] # only accept strings for now
    # calculate message
    $bytes   = $input.bytes
    $message = $input.bytes.map {|x| x.to_s(2).rjust(8, "0")}.join
  end
  
  # puts string.bytes.inspect                     # [97, 98, 99]
  # puts string.bytes.map{|x| x.to_s(16)}.inspect # ["61", "62", "63"]
  # puts string.bytes.map{|x| x.to_s(2)}.inspect  # ["1100001", "1100010", "1100011"]
  # puts string.unpack("B*")                      # 011000010110001001100011
  
  # ---------
  # Animation
  # ---------
  system "clear"
  puts "-------"
  puts "message:"
  puts "-------"
  delay(:fast)
  
  system "clear"
  puts "-------"
  puts "message:"
  puts "-------"
  puts "input:   #{$input} (#{$type})"
  delay(:normal)
  
  system "clear"
  puts "-------"
  puts "message:"
  puts "-------"
  puts "input:   #{$input} (#{$type})"
  puts "bytes:   #{$bytes.inspect}" if defined? $bytes
  delay(:normal)
  
  system "clear"
  puts "-------"
  puts "message:"
  puts "-------"
  puts "input:   #{$input} (#{$type})"
  puts "bytes:   #{$bytes.inspect}" if defined? $bytes
  puts "message: #{$message}"
  delay(:end)
  
  # Save Final State
  $state = <<-FRAME
  -------
  message:
  -------
  input:   #{$input} (#{$type})
  bytes:   #{$bytes.inspect}
  message: #{$message}
  FRAME


Padding

Padding

  require_relative "sha256lib.rb"
  
  # -------
  # Default
  # -------
  if !defined? $input
    # default
    $input = "abc"
    $message = $input.unpack("B*")[0] # 011000010110001001100011
    # argument passed
    $message = ARGV[0] if ARGV[0] # accept binary message string
  end
  
  # -------
  # Padding
  # -------
  
  # pad the message so that it's a multiple of 512 bits
  $l = $message.size      # length of message
  $k = (448 - $l - 1) % 512 # pad with zeros up to 448 bits (64 short of 512 bits)
  
  #        message                  padding            size M
  # -------------------------------------------------------------
  # |         M         |1|...00000000000000000000|...0000001100|
  # -------------------------------------------------------------
  #  <----------------- 448 bits ----------------> <- 64 bits ->
  
  $padded = $message + "1" + ("0" * $k) + $l.to_s(2).rjust(64, "0")
  
  # ---------
  # Animation
  # ---------
  system "clear"
  puts $state + "\n" if defined? $state
  puts "-------"
  puts "padding:"
  puts "-------"
  delay(:normal)
  
  system "clear"
  puts $state + "\n" if defined? $state
  puts "-------"
  puts "padding: (#{$message.size} bits)"
  puts "-------"
  puts "message: #{$message}"
  delay(:normal)
  
  system "clear"
  puts $state + "\n" if defined? $state
  puts "-------"
  puts "padding: (#{($message + "1").size} bits)"
  puts "-------"
  puts "message: #{$message}1"
  delay(:normal)
  
  system "clear"
  puts $state + "\n" if defined? $state
  puts "-------"
  puts "padding: (#{($message + "1").size} bits -> #{($message + "1").size + $k} bits)"
  puts "-------"
  print "message: #{$message}1"
  if $delay == "enter" || $delay == "nodelay" # show all padded zeros in one go if we're stepping through with keyboard
    puts "0" * $k
  else
    $k.times do |i|
      print "0"
      sleep 0.005
    end
  end
  delay(:normal)
  
  system "clear"
  puts $state + "\n" if defined? $state
  puts "-------"
  puts "padding: (#{($message + "1").size + $k} bits)"
  puts "-------"
  print "message: #{$message}1#{"0" * $k}"
  delay(:normal)
  
  system "clear"
  puts $state + "\n" if defined? $state
  puts "-------"
  puts "padding: (#{$padded.size} bits)"
  puts "-------"
  puts "message: #{$padded}"
  delay(:end)
  
  # Save Final State
  $state = <<-FRAME
  #{$state}
  -------
  padding: (#{$padded.size} bits)
  -------
  message: #{$padded}
  FRAME


Rotr

Rotr

# -----------
# Shift Right
# -----------
def rotr(n, x)
  mask = 2**32 - 1
  right = (x >> n) & mask
  left  = (x << 32-n) & mask
  result = right | left
  return result
end

# -----
# Input
# -----
# defaults
x = 0b11111111000000001111111100000000 #0b11101001101101011101101110100101
n = 32
# arguments passed
x = ARGV[0].to_i(2) if ARGV[0] # binary
n = ARGV[1].to_i    if ARGV[1] # integer
# check arguments
if ARGV[0] && ARGV[0].size > 32
  puts "We only operate on 32-bit words in SHA-256. Your x is #{ARGV[0].size} bits."; exit
end

# ---------
# Animation
# ---------
s = n.to_s.ljust(2, " ")
n.times do |i|
  system "clear"
  i += 1

  puts "      x: #{"%032b" % x}"
  puts "ROTR #{s}: #{"%032b" % rotr(i, x)}"

  sleep 0.10
end
sleep 0.5


Schedule

Schedule

  # coding: utf-8
  require_relative "sha256lib.rb"
  
  # -------
  # Default
  # -------
  if !defined? $input
    # default
    $input = "abc"
    $message = $input.unpack("B*")[0] # 011000010110001001100011
    $padded = padding($message)
    $blocks = split($padded, 512)
    $block_number = 0               # message block number
    $block = $blocks[$block_number]
    
    # argument passed
    $block = ARGV[0] if ARGV[0] # accept 512 bit binary string as message block
  end
  
  # Set variables (these are global variables given to us by the parent sha256.rb script)
  if defined? $block
    $block = $block
    $block_number = $block_number
  end
  
  # ----------------
  # Message Schedule
  # ----------------
  # Get size of block
  size = $block.size
  
  # The message block provides the first 16 words for the message schedule (512 bits / 32 bits = 16 words)
  $schedule = $block.scan(/.{32}/).map { |w| w.to_i(2) } # convert from binary string to integer for calculations
  
  # Remember the values used to calculate each word from 16 to 63
  memory = Array.new(16) # leave first 16 blank because they were not calculated from previous values
  
  # Calculate remaining 48 words
  16.upto(63) do |i|
    $schedule << add(sigma1($schedule[i - 2]), $schedule[i - 7], sigma0($schedule[i - 15]), $schedule[i - 16])
    memory << [sigma1($schedule[i - 2]), $schedule[i - 7], sigma0($schedule[i - 15]), $schedule[i - 16]] # store the values used in the calculation as we go
  end
  
  # --------
  # Settings
  # --------
  indent = " " * 2
  
  # ---------
  # Animation
  # ---------
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-------"
  puts "#{indent}block #{$block_number}:"
  puts "#{indent}-------"
  puts "#{indent}#{$block}"
  delay(:slowest)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-------"
  puts "#{indent}block #{$block_number}:"
  puts "#{indent}-------"
  puts "#{indent}#{$block}"
  puts
  puts "#{indent}----------------"
  puts "#{indent}message schedule:"
  puts "#{indent}----------------"
  delay(:slowest)
  
  # Frame
  64.times do |i|
    system "clear"
    puts $state + "\n" if defined? $state
    puts "#{indent}-------"
    puts "#{indent}block #{$block_number}:"
    puts "#{indent}-------"
    if i <= 15
      puts "#{indent}#{$block[((i + 1) * 32)..-1].ljust(size, " ")}"
    else
      puts "#{indent}#{" " * size}" # leave space where it used to be
    end
    puts
    puts "#{indent}----------------"
    puts "#{indent}message schedule:"
    puts "#{indent}----------------"
  
    (i + 1).times do |j|
      # first 16 value are just words from the message block
      if i <= 15
        puts "#{indent}W#{j.to_s.ljust(2, " ")} #{bits($schedule[j])}"
      end
      # show values used in calculation for last 48 words
      if i >= 16
        if j < i - 16
          # show nothing
        elsif j == i - 16
          puts "#{indent}W#{j.to_s.ljust(2, " ")} #{bits($schedule[j])} ->    #{bits(memory[i][3])}"
        elsif j == i - 15
          puts "#{indent}W#{j.to_s.ljust(2, " ")} #{bits($schedule[j])} -> σ0 #{bits(memory[i][2])}"
        elsif j == i - 7
          puts "#{indent}W#{j.to_s.ljust(2, " ")} #{bits($schedule[j])} ->    #{bits(memory[i][1])}"
        elsif j == i - 2
          puts "#{indent}W#{j.to_s.ljust(2, " ")} #{bits($schedule[j])} -> σ1 #{bits(memory[i][0])}"
        elsif j == i
          puts "#{indent}W#{j.to_s.ljust(2, " ")} #{bits($schedule[j])} = σ1(t-2) + (t-7) + σ0(t-15) + (t-16)"
        else
          puts "#{indent}W#{j.to_s.ljust(2, " ")} #{bits($schedule[j])}"
        end
      end
    end
  
    # pause before calculating remaining 48 words after the initial 16
    if i == 15
      delay(:normal)
    else
      delay(:fastest)
    end
  end
  delay(:normal)
  
  # Frame
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-------"
  puts "#{indent}block #{$block_number}:"
  puts "#{indent}-------"
  puts "#{indent}#{" " * size}"
  puts
  puts "#{indent}----------------"
  puts "#{indent}message schedule:"
  puts "#{indent}----------------"
  47.upto(63) do |i|
    puts "#{indent}W#{i.to_s.ljust(2, " ")} #{bits($schedule[i])}"
  end
  delay(:end)
  
  # Save Final State
  $state = <<-FRAME
  #{$state}
  #{indent}-------
  #{indent}block #{$block_number}:
  #{indent}-------
  #{indent}#{" " * size}
  
  #{indent}----------------
  #{indent}message schedule:
  #{indent}----------------
  #{indent}W#{47.to_s.ljust(2, " ")} #{bits($schedule[47])}
  #{indent}W#{48.to_s.ljust(2, " ")} #{bits($schedule[48])}
  #{indent}W#{49.to_s.ljust(2, " ")} #{bits($schedule[49])}
  #{indent}W#{50.to_s.ljust(2, " ")} #{bits($schedule[50])}
  #{indent}W#{51.to_s.ljust(2, " ")} #{bits($schedule[51])}
  #{indent}W#{52.to_s.ljust(2, " ")} #{bits($schedule[52])}
  #{indent}W#{53.to_s.ljust(2, " ")} #{bits($schedule[53])}
  #{indent}W#{54.to_s.ljust(2, " ")} #{bits($schedule[54])}
  #{indent}W#{55.to_s.ljust(2, " ")} #{bits($schedule[55])}
  #{indent}W#{56.to_s.ljust(2, " ")} #{bits($schedule[56])}
  #{indent}W#{57.to_s.ljust(2, " ")} #{bits($schedule[57])}
  #{indent}W#{58.to_s.ljust(2, " ")} #{bits($schedule[58])}
  #{indent}W#{59.to_s.ljust(2, " ")} #{bits($schedule[59])}
  #{indent}W#{60.to_s.ljust(2, " ")} #{bits($schedule[60])}
  #{indent}W#{61.to_s.ljust(2, " ")} #{bits($schedule[61])}
  #{indent}W#{62.to_s.ljust(2, " ")} #{bits($schedule[62])}
  #{indent}W#{63.to_s.ljust(2, " ")} #{bits($schedule[63])}
  FRAME
  
  system "clear"
  puts $state


Compression

Compression

require_relative "sha256lib.rb"

# -------
# Default
# -------
if !defined? $input
  # Command Line Arguments
  $input = ARGV[0] || "abc"    # "string"|"0xaabbcc"|"0b10110100"
  $delay = ARGV[1] || "normal" # [enter|normal|fast|nodelay]

  # Detect input type (binary, hex, or string)
  $type = input_type($input)

  # Convert input to bytes (if possible)
  $bytes = bytes($input, $type)

  # Set message (binary representation of data)
  if $type == "string" || $type == "hex"
    $message = $bytes.map { |x| x.to_s(2).rjust(8, "0") }.join # convert bytes to binary string
  end
  if $type == "binary"
    $message = $input[2..-1] # input is already in binary, so just trim the leading 0b from the input
  end

  # Note about hitting enter to step
  if $delay == "enter"
    puts "Hit enter to step through."
    STDIN.gets
  end

  # Catch Ctrl-C to prevent unsightly errors when terminating early
  Signal.trap("SIGINT") do
    exit
  end
end

# 1. Message
load "message.rb"

# 2. Padding
load "padding.rb"

# 3. Message Blocks
load "blocks.rb"

# For each block
$blocks.each.with_index do |block, i|
  # make variables global so scripts can access them
  $block = block
  $block_number = i

  # 4. Message Schedule
  load "schedule.rb"

  # 5. Compression (Initial Hash Values)
  load "initial.rb" if $block_number == 0 # Only set initial hash values on first run

  # 5. Compression
  load "compression.rb" # Use hash values from previous compression otherwise
end

# 6. Final Hash
load "final.rb"


Shr

Shr

# -----------
# Shift Right
# -----------
def shr(n, x)
  x >> n
end

# -----
# Input
# -----
# defaults
x = 0b11111111000000001111111100000000 #0b11101001101101011101101110100101
n = 32     
# arguments passed
x = ARGV[0].to_i(2) if ARGV[0] # binary
n = ARGV[1].to_i    if ARGV[1] # integer
# check arguments
if ARGV[0] && ARGV[0].size > 32
  puts "We only operate on 32-bit words in SHA-256. Your x is #{ARGV[0].size} bits."; exit
end

# ---------
# Animation
# ---------
s = n.to_s.ljust(2, " ")
n.times do |i|
  system "clear"
  i += 1

  puts "      x: #{"%032b" % x}"
  puts " SHR #{s}: #{"%032b" % shr(i, x)}"

  sleep 0.1
end
sleep 0.4


Sigma0

Sigma0

  # coding: utf-8
  require_relative "sha256lib.rb"
  
  # -----
  # σ0(x)
  # -----
  # σ0(x) = ROTR(7, x) ^ ROTR(18, x) ^ SHR(3, x)
  
  # -----
  # Input
  # -----
  # default
  x = 0b00000000000000000011111111111111 # 0b11101001101101011101101110100101
  # argument passed
  x = ARGV[0].to_i(2) if ARGV[0] # binary
  # check arguments
  if ARGV[0] && ARGV[0].size > 32
    puts "We only operate on 32-bit words in SHA-256. Your x is #{ARGV[0].size} bits."; exit
  end
  
  # ---------
  # Animation
  # ---------
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 7:  #{bits(x)}"
  puts "ROTR 18: #{bits(x)}"
  puts " SHR 3:  #{bits(x)}"
  puts "         #{'-'*32}"
  puts "σ0(x):"
  sleep(0.1)
  
  # ROTR(7, x)
  (7+1).times do |i|
    system "clear"
    puts "x:       #{bits(x)}"
    puts "         #{'-'*32}"
    puts "ROTR 7:  #{bits(rotr(i, x))}"
    puts "ROTR 18: #{bits(x)}"
    puts " SHR 3:  #{bits(x)}"
    puts "         #{'-'*32}"
    puts "σ0(x):"
    sleep(0.1)
  end
  sleep(0.1)
  
  # ROTR(18, x)
  (18+1).times do |i|
    system "clear"
    puts "x:       #{bits(x)}"
    puts "         #{'-'*32}"
    puts "ROTR 7:  #{bits(rotr(7, x))}"
    puts "ROTR 18: #{bits(rotr(i, x))}"
    puts " SHR 3:  #{bits(x)}"
    puts "         #{'-'*32}"
    puts "σ0(x):"
    sleep(0.1)
  end
  sleep(0.1)
  
  # SHR(3, x)
  (3+1).times do |i|
    system "clear"
    puts "x:       #{bits(x)}"
    puts "         #{'-'*32}"
    puts "ROTR 7:  #{bits(rotr(7, x))}"
    puts "ROTR 18: #{bits(rotr(18, x))}"
    puts " SHR 3:  #{bits(shr(i, x))}"
    puts "         #{'-'*32}"
    puts "σ0(x):"
    sleep(0.1)
  end
  sleep(0.1)
  
  # ROTR(7, x) ^ ROTR(18, x) ^ SHR(3, x)
  32.downto(1) do |i|
    system "clear"
    puts "x:       #{bits(x)}"
    puts "         #{'-'*32}"
    puts "ROTR 7:  #{bits(rotr(7, x))}"
    puts "ROTR 18: #{bits(rotr(18, x))} XOR"
    puts " SHR 3:  #{bits(shr(3, x))} XOR"
    puts "         #{'-'*32}"
    puts "σ0(x):   #{bits(rotr(7, x) ^ rotr(18, x) ^ shr(3, x))[i-1..-1].rjust(32, " ")}"
    sleep(0.1)
  end
  sleep(1)


Sigma1

Sigma1

  # coding: utf-8
  require_relative "sha256lib.rb"
  
  # -----
  # σ1(x)
  # -----
  # σ1(x) = ROTR(17, x) ^ ROTR(19, x) ^ SHR(10, x)
  
  # -----
  # Input
  # -----
  # default
  x = 0b00000000000000000011111111111111 # 0b11101001101101011101101110100101
  # argument passed
  x = ARGV[0].to_i(2) if ARGV[0] # binary
  # check arguments
  if ARGV[0] && ARGV[0].size > 32
    puts "We only operate on 32-bit words in SHA-256. Your x is #{ARGV[0].size} bits."; exit
  end
  
  # ---------
  # Animation
  # ---------
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 17: #{bits(x)}"
  puts "ROTR 19: #{bits(x)}"
  puts " SHR 10: #{bits(x)}"
  puts "         #{'-'*32}"
  puts "σ1(x):"
  sleep(0.1)
  
  # ROTR(17, x)
  (17+1).times do |i|
    system "clear"
    puts "x:       #{bits(x)}"
    puts "         #{'-'*32}"
    puts "ROTR 17: #{bits(rotr(i, x))}"
    puts "ROTR 19: #{bits(x)}"
    puts " SHR 10: #{bits(x)}"
    puts "         #{'-'*32}"
    puts "σ1(x):"
    sleep(0.1)
  end
  sleep(0.1)
  
  # ROTR(19, x)
  (19+1).times do |i|
    system "clear"
    puts "x:       #{bits(x)}"
    puts "         #{'-'*32}"
    puts "ROTR 17: #{bits(rotr(17, x))}"
    puts "ROTR 19: #{bits(rotr(i, x))}"
    puts " SHR 10: #{bits(x)}"
    puts "         #{'-'*32}"
    puts "σ1(x):"
    sleep(0.1)
  end
  sleep(0.1)
  
  # SHR(10, x)
  (10+1).times do |i|
    system "clear"
    puts "x:       #{bits(x)}"
    puts "         #{'-'*32}"
    puts "ROTR 17: #{bits(rotr(17, x))}"
    puts "ROTR 19: #{bits(rotr(19, x))}"
    puts " SHR 10: #{bits(shr(i, x))}"
    puts "         #{'-'*32}"
    puts "σ1(x):"
    sleep(0.1)
  end
  sleep(0.1)
  
  # ROTR(17, x) ^ ROTR(19, x) ^ SHR(10, x)
  32.downto(1) do |i|
    system "clear"
    puts "x:       #{bits(x)}"
    puts "         #{'-'*32}"
    puts "ROTR 17: #{bits(rotr(17, x))}"
    puts "ROTR 19: #{bits(rotr(19, x))} XOR"
    puts " SHR 10: #{bits(shr(10, x))} XOR"
    puts "         #{'-'*32}"
    puts "σ1(x):   #{bits(rotr(17, x) ^ rotr(19, x) ^ shr(10, x))[i-1..-1].rjust(32, " ")}"
    sleep(0.1)
  end
  sleep(1)


T1

T1

  # coding: utf-8
  require_relative "sha256lib.rb"
  
  # -------
  # Default
  # -------
  if !defined? $input
    $input = "abc"
    $message = $input.unpack("B*")[0] # 011000010110001001100011
    $padded = padding($message)
    $blocks = split($padded, 512)
  
    # message block
    $block_number = 0 # message block number
    $block = $blocks[$block_number]
  
    # message schedule
    $schedule = calculate_schedule($block)
  end
  
  # Schedule (Wt)
  w = $schedule
  
  # Constants (Kt)
  k = K
  
  # Initial Hash Values
  initial = IV
  $hash = initial.clone
  
  # --------
  # Settings
  # --------
  indent = " " * 2
  
  # ---------
  # Animation
  # ---------
  
  # Start
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts
  puts
  puts
  puts
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Start
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts
  puts
  puts
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Start
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Start
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 ="
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:slow)
  
  # Start
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:slow)
  
  # Ch(e, f, g)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])} ->"
  puts "#{indent}f = #{bits($hash[5])} ->"
  puts "#{indent}g = #{bits($hash[6])} ->"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Ch(e, f, g)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])} -> #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])} -> #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])} -> #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Ch(e, f, g)
  32.downto(1) do |i|
    system "clear"
    puts $state + "\n" if defined? $state
    puts "#{indent}-----------"
    puts "#{indent}compression: (T1)"
    puts "#{indent}-----------"
    puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
    puts "#{indent}K0 = #{bits(k[0])} (constant)"
    puts
    puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
    puts
    puts
    puts "#{indent}a = #{bits($hash[0])}"
    puts "#{indent}b = #{bits($hash[1])}"
    puts "#{indent}c = #{bits($hash[2])}"
    puts "#{indent}d = #{bits($hash[3])}    #{"▼".rjust(i, " ")}"
    puts "#{indent}e = #{bits($hash[4])} -> #{bits($hash[4])}"
    puts "#{indent}f = #{bits($hash[5])} -> #{bits($hash[5])} #{bits($hash[4])[i-1] == '1' ? '◄' : ' '}"
    puts "#{indent}g = #{bits($hash[6])} -> #{bits($hash[6])} #{bits($hash[4])[i-1] == '0' ? '◄' : ' '}"
    puts "#{indent}h = #{bits($hash[7])}    #{bits(ch($hash[4], $hash[5], $hash[6]))[i-1..-1].rjust(32, " ")} Ch(e, f, g)"
    delay(:fastest)
  end
  delay(:normal)
  
  # Ch(e, f, g)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])} -> #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])} -> #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])} -> #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  delay(:normal)
  
  # Ch(e, f, g)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  delay(:normal)
  
  # Ch(e, f, g)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ1(e)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])} -> "
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:fast)
  
  # Σ1(e)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])} -> #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:fast)
  
  # Σ1(e)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits($hash[4])}"
  puts "#{indent}e = #{bits($hash[4])} -> #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:fast)
  
  # Σ1(e)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}    #{bits($hash[4])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits($hash[4])}"
  puts "#{indent}e = #{bits($hash[4])} -> #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ1(e)
  6.times do |i|
    system "clear"
    puts $state + "\n" if defined? $state
    puts "#{indent}-----------"
    puts "#{indent}compression: (T1)"
    puts "#{indent}-----------"
    puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
    puts "#{indent}K0 = #{bits(k[0])} (constant)"
    puts
    puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
    puts
    puts
    puts "#{indent}a = #{bits($hash[0])}"
    puts "#{indent}b = #{bits($hash[1])}"
    puts "#{indent}c = #{bits($hash[2])}    #{bits(rotr(i+1, $hash[4]))} ROTR 6"
    puts "#{indent}d = #{bits($hash[3])}    #{bits($hash[4])}"
    puts "#{indent}e = #{bits($hash[4])} -> #{bits($hash[4])}"
    puts "#{indent}f = #{bits($hash[5])}"
    puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
    puts "#{indent}h = #{bits($hash[7])}"
    delay(:fastest)
  end
  delay(:normal)
  
  # Σ1(e)
  11.times do |i|
    system "clear"
    puts $state + "\n" if defined? $state
    puts "#{indent}-----------"
    puts "#{indent}compression: (T1)"
    puts "#{indent}-----------"
    puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
    puts "#{indent}K0 = #{bits(k[0])} (constant)"
    puts
    puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
    puts
    puts
    puts "#{indent}a = #{bits($hash[0])}"
    puts "#{indent}b = #{bits($hash[1])}"
    puts "#{indent}c = #{bits($hash[2])}    #{bits(rotr(6, $hash[4]))} ROTR 6"
    puts "#{indent}d = #{bits($hash[3])}    #{bits(rotr(i+1, $hash[4]))} ROTR 11"
    puts "#{indent}e = #{bits($hash[4])} -> #{bits($hash[4])}"
    puts "#{indent}f = #{bits($hash[5])}"
    puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
    puts "#{indent}h = #{bits($hash[7])}"
    delay(:fastest)
  end
  delay(:normal)
  
  # Σ1(e)
  25.times do |i|
    system "clear"
    puts $state + "\n" if defined? $state
    puts "#{indent}-----------"
    puts "#{indent}compression: (T1)"
    puts "#{indent}-----------"
    puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
    puts "#{indent}K0 = #{bits(k[0])} (constant)"
    puts
    puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
    puts
    puts
    puts "#{indent}a = #{bits($hash[0])}"
    puts "#{indent}b = #{bits($hash[1])}"
    puts "#{indent}c = #{bits($hash[2])}    #{bits(rotr(6, $hash[4]))} ROTR 6"
    puts "#{indent}d = #{bits($hash[3])}    #{bits(rotr(11, $hash[4]))} ROTR 11"
    puts "#{indent}e = #{bits($hash[4])} -> #{bits(rotr(i+1, $hash[4]))} ROTR 25"
    puts "#{indent}f = #{bits($hash[5])}"
    puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
    puts "#{indent}h = #{bits($hash[7])}"
    delay(:fastest)
  end
  delay(:normal)
  
  # Σ1(e)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}    #{bits(rotr(6, $hash[4]))}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(rotr(11, $hash[4]))}"
  puts "#{indent}e = #{bits($hash[4])} -> #{bits(rotr(25, $hash[4]))}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ1(e)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}    #{bits(rotr(6, $hash[4]))} XOR"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(rotr(11, $hash[4]))}"
  puts "#{indent}e = #{bits($hash[4])} -> #{bits(rotr(25, $hash[4]))}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ1(e)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(rotr(11, $hash[4]) ^ rotr(6, $hash[4]))} XOR"
  puts "#{indent}e = #{bits($hash[4])} -> #{bits(rotr(25, $hash[4]))}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ1(e)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])} -> #{bits(rotr(11, $hash[4]) ^ rotr(6, $hash[4]) ^ rotr(25, $hash[4]))} Σ1(e)"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ1(e)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}    #{bits(usigma1($hash[4]))} Σ1(e)"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # h
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}    #{bits(usigma1($hash[4]))} Σ1(e)"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])} -> "
  delay(:normal)
  
  # h
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}    #{bits(usigma1($hash[4]))} Σ1(e)"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])} -> #{bits($hash[7])}"
  delay(:normal)
  
  # h
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}    #{bits(usigma1($hash[4]))} Σ1(e)"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])} -> #{bits($hash[7])} h"
  delay(:normal)
  
  # h
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}    #{bits(usigma1($hash[4]))} Σ1(e)"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}    #{bits($hash[7])} h"
  delay(:normal)
  
  # T1
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0 = "
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}    #{bits(usigma1($hash[4]))} Σ1(e)"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}    #{bits($hash[7])} h"
  delay(:normal)
  
  # T1
  system "clear"
  t1 = add(w[0], k[0], usigma1($hash[4]), ch($hash[4], $hash[5], $hash[6]), $hash[7])
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T1)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0 = #{bits(t1)}"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}    #{bits(usigma1($hash[4]))} Σ1(e)"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}    #{bits(ch($hash[4], $hash[5], $hash[6]))} Ch(e, f, g)"
  puts "#{indent}h = #{bits($hash[7])}    #{bits($hash[7])} h"
  delay(:end)


T2

T2

  # coding: utf-8
  require_relative "sha256lib.rb"
  
  # -------
  # Default
  # -------
  if !defined? $input
    $input = "abc"
    $message = $input.unpack("B*")[0] # 011000010110001001100011
    $padded = padding($message)
    $blocks = split($padded, 512)
  
    # message block
    $block_number = 0 # message block number
    $block = $blocks[$block_number]
  
    # message schedule
    $schedule = calculate_schedule($block)
  end
  
  # Schedule (Wt)
  w = $schedule
  
  # Constants (Kt)
  k = K
  
  # Initial Hash Values
  initial = IV
  $hash = initial.clone
  
  # T1
  t1 = add(w[0], k[0], usigma1($hash[4]), ch($hash[4], $hash[5], $hash[6]), $hash[7])
  
  # --------
  # Settings
  # --------
  indent = " " * 2
  
  # ---------
  # Animation
  # ---------
  
  # Start
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Start
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 ="
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Start
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Maj(a, b, c)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> "
  puts "#{indent}b = #{bits($hash[1])} -> "
  puts "#{indent}c = #{bits($hash[2])} -> "
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Maj(a, b, c)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])} -> #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])} -> #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Maj(a, b, c)
  32.downto(1) do |i|
    system "clear"
    puts $state + "\n" if defined? $state
    puts "#{indent}-----------"
    puts "#{indent}compression: (T2)"
    puts "#{indent}-----------"
    puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
    puts "#{indent}K0 = #{bits(k[0])} (constant)"
    puts
    puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
    puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
    puts "#{indent}    #{  " " * 32    }    #{"▼".rjust(i, " ")}"
    puts "#{indent}a = #{bits($hash[0])} -> #{bits($hash[0])} #{bits(initial[0])[i-1]}"
    puts "#{indent}b = #{bits($hash[1])} -> #{bits($hash[1])} #{bits(initial[1])[i-1]}"
    puts "#{indent}c = #{bits($hash[2])} -> #{bits($hash[2])} #{bits(initial[2])[i-1]}"
    puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))[i-1..-1].rjust(32, " ")} Maj(a, b, c)"
    puts "#{indent}e = #{bits($hash[4])}"
    puts "#{indent}f = #{bits($hash[5])}"
    puts "#{indent}g = #{bits($hash[6])}"
    puts "#{indent}h = #{bits($hash[7])}"
    delay(:fastest)
  end
  delay(:normal)
  
  # Maj(a, b, c)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])} -> #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])} -> #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Maj(a, b, c)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} ->"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:fast)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:fast)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}    #{bits($hash[0])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:fast)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> #{bits($hash[0])}"
  puts "#{indent}b = #{bits($hash[1])}    #{bits($hash[0])}"
  puts "#{indent}c = #{bits($hash[2])}    #{bits($hash[0])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ0(a)
  2.times do |i|
    system "clear"
    puts $state + "\n" if defined? $state
    puts "#{indent}-----------"
    puts "#{indent}compression: (T2)"
    puts "#{indent}-----------"
    puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
    puts "#{indent}K0 = #{bits(k[0])} (constant)"
    puts
    puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
    puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
    puts
    puts "#{indent}a = #{bits($hash[0])} -> #{bits(rotr(i+1, $hash[0]))} ROTR 2"
    puts "#{indent}b = #{bits($hash[1])}    #{bits($hash[0])}"
    puts "#{indent}c = #{bits($hash[2])}    #{bits($hash[0])}"
    puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
    puts "#{indent}e = #{bits($hash[4])}"
    puts "#{indent}f = #{bits($hash[5])}"
    puts "#{indent}g = #{bits($hash[6])}"
    puts "#{indent}h = #{bits($hash[7])}"
    delay(:fastest)
  end
  delay(:normal)
  
  # Σ0(a)
  13.times do |i|
    system "clear"
    puts $state + "\n" if defined? $state
    puts "#{indent}-----------"
    puts "#{indent}compression: (T2)"
    puts "#{indent}-----------"
    puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
    puts "#{indent}K0 = #{bits(k[0])} (constant)"
    puts
    puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
    puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
    puts
    puts "#{indent}a = #{bits($hash[0])} -> #{bits(rotr(2, $hash[0]))} ROTR 2"
    puts "#{indent}b = #{bits($hash[1])}    #{bits(rotr(i+1, $hash[0]))} ROTR 13"
    puts "#{indent}c = #{bits($hash[2])}    #{bits($hash[0])}"
    puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
    puts "#{indent}e = #{bits($hash[4])}"
    puts "#{indent}f = #{bits($hash[5])}"
    puts "#{indent}g = #{bits($hash[6])}"
    puts "#{indent}h = #{bits($hash[7])}"
    delay(:fastest)
  end
  delay(:normal)
  
  # Σ0(a)
  22.times do |i|
    system "clear"
    puts $state + "\n" if defined? $state
    puts "#{indent}-----------"
    puts "#{indent}compression: (T2)"
    puts "#{indent}-----------"
    puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
    puts "#{indent}K0 = #{bits(k[0])} (constant)"
    puts
    puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
    puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
    puts
    puts "#{indent}a = #{bits($hash[0])} -> #{bits(rotr(2, $hash[0]))} ROTR 2"
    puts "#{indent}b = #{bits($hash[1])}    #{bits(rotr(13, $hash[0]))} ROTR 13"
    puts "#{indent}c = #{bits($hash[2])}    #{bits(rotr(i+1, $hash[0]))} ROTR 22"
    puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
    puts "#{indent}e = #{bits($hash[4])}"
    puts "#{indent}f = #{bits($hash[5])}"
    puts "#{indent}g = #{bits($hash[6])}"
    puts "#{indent}h = #{bits($hash[7])}"
    delay(:fastest)
  end
  delay(:normal)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> #{bits(rotr(2, $hash[0]))}"
  puts "#{indent}b = #{bits($hash[1])}    #{bits(rotr(13, $hash[0]))}"
  puts "#{indent}c = #{bits($hash[2])}    #{bits(rotr(22, $hash[0]))}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> #{bits(rotr(2, $hash[0]))}"
  puts "#{indent}b = #{bits($hash[1])}    #{bits(rotr(13, $hash[0]))}"
  puts "#{indent}c = #{bits($hash[2])}    #{bits(rotr(22, $hash[0]))} XOR"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> #{bits(rotr(2, $hash[0]))}"
  puts "#{indent}b = #{bits($hash[1])}    #{bits(rotr(13, $hash[0]) ^ rotr(22, $hash[0]))} XOR"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])} -> #{bits(rotr(2, $hash[0]) ^ rotr(13, $hash[0]) ^ rotr(22, $hash[0]))} Σ0(a)"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c)"
  puts
  puts "#{indent}a = #{bits($hash[0])}    #{bits(usigma0($hash[0]))} Σ0(a)"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ0(a)
  system "clear"
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c) = "
  puts
  puts "#{indent}a = #{bits($hash[0])}    #{bits(usigma0($hash[0]))} Σ0(a)"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:normal)
  
  # Σ0(a)
  system "clear"
  t2 = add(usigma0($hash[0]), maj($hash[0], $hash[1], $hash[2]))
  puts $state + "\n" if defined? $state
  puts "#{indent}-----------"
  puts "#{indent}compression: (T2)"
  puts "#{indent}-----------"
  puts "#{indent}W0 = #{bits(w[0])} (message schedule)"
  puts "#{indent}K0 = #{bits(k[0])} (constant)"
  puts
  puts "#{indent}T1 = Σ1(e) + Ch(e, f, g) + h + K0  + W0"
  puts "#{indent}T2 = Σ0(a) + Maj(a, b, c) = #{bits(t2)}"
  puts
  puts "#{indent}a = #{bits($hash[0])}    #{bits(usigma0($hash[0]))} Σ0(a)"
  puts "#{indent}b = #{bits($hash[1])}"
  puts "#{indent}c = #{bits($hash[2])}"
  puts "#{indent}d = #{bits($hash[3])}    #{bits(maj($hash[0], $hash[1], $hash[2]))} Maj(a, b, c)"
  puts "#{indent}e = #{bits($hash[4])}"
  puts "#{indent}f = #{bits($hash[5])}"
  puts "#{indent}g = #{bits($hash[6])}"
  puts "#{indent}h = #{bits($hash[7])}"
  delay(:end)


Usigma0

usigma0

# coding: utf-8
require_relative "sha256lib.rb"

# -----
# Σ0(x)
# -----
# Σ0(x) = ROTR(2, x) ^ ROTR(13, x) ^ ROTR(22, x)

# -----
# Input
# -----
# default
x = 0b00000000000000000011111111111111 # 0b11101001101101011101101110100101
# argument passed
x = ARGV[0].to_i(2) if ARGV[0] # binary
# check arguments
if ARGV[0] && ARGV[0].size > 32
  puts "We only operate on 32-bit words in SHA-256. Your x is #{ARGV[0].size} bits."; exit
end

# ---------
# Animation
# ---------
system "clear"
puts "x:       #{bits(x)}"
puts "         #{'-'*32}"
puts "ROTR 2:  #{bits(x)}"
puts "ROTR 13: #{bits(x)}"
puts "ROTR 22: #{bits(x)}"
puts "         #{'-'*32}"
puts "Σ0(x):"
sleep(0.1)

# ROTR(2, x)
(2+1).times do |i|
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 2:  #{bits(rotr(i, x))}"
  puts "ROTR 13: #{bits(x)}"
  puts "ROTR 22: #{bits(x)}"
  puts "         #{'-'*32}"
  puts "Σ0(x):"
  sleep(0.1)
end
sleep(0.1)

# ROTR(13, x)
(13+1).times do |i|
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 2:  #{bits(rotr(2, x))}"
  puts "ROTR 13: #{bits(rotr(i, x))}"
  puts "ROTR 22: #{bits(x)}"
  puts "         #{'-'*32}"
  puts "Σ0(x):"
  sleep(0.1)
end
sleep(0.1)

# ROTR(22, x)
(22+1).times do |i|
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 2:  #{bits(rotr(2, x))}"
  puts "ROTR 13: #{bits(rotr(13, x))}"
  puts "ROTR 22: #{bits(rotr(i, x))}"
  puts "         #{'-'*32}"
  puts "Σ0(x):"
  sleep(0.1)
end
sleep(0.1)

# ROTR(2, x) ^ ROTR(13, x) ^ ROTR(22, x)
32.downto(1) do |i|
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 2:  #{bits(rotr(2, x))}"
  puts "ROTR 13: #{bits(rotr(13, x))} XOR"
  puts "ROTR 22: #{bits(rotr(22, x))} XOR"
  puts "         #{'-'*32}"
  puts "Σ0(x):   #{bits(rotr(2, x) ^ rotr(13, x) ^ rotr(22, x))[i-1..-1].rjust(32, " ")}"
  sleep(0.1)
end
sleep(1)


Usigma1

Usigma1

# coding: utf-8
require_relative "sha256lib.rb"

# -----
# Σ1(x)
# -----
# Σ1(x) = ROTR(6, x) ^ ROTR(11, x) ^ ROTR(25, x)

# -----
# Input
# -----
# default
x = 0b00000000000000000011111111111111 # 0b01010001000011100101001001111111
# argument passed
x = ARGV[0].to_i(2) if ARGV[0] # binary
# check arguments
if ARGV[0] && ARGV[0].size > 32
  puts "We only operate on 32-bit words in SHA-256. Your x is #{ARGV[0].size} bits."; exit
end

# ---------
# Animation
# ---------
system "clear"
puts "x:       #{bits(x)}"
puts "         #{'-'*32}"
puts "ROTR 6:  #{bits(x)}"
puts "ROTR 11: #{bits(x)}"
puts "ROTR 25: #{bits(x)}"
puts "         #{'-'*32}"
puts "Σ1(x):"
sleep(0.1)

# ROTR(6, x)
(6+1).times do |i|
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 6:  #{bits(rotr(i, x))}"
  puts "ROTR 11: #{bits(x)}"
  puts "ROTR 25: #{bits(x)}"
  puts "         #{'-'*32}"
  puts "Σ1(x):"
  sleep(0.1)
end
sleep(0.1)

# ROTR(11, x)
(11+1).times do |i|
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 6:  #{bits(rotr(6, x))}"
  puts "ROTR 11: #{bits(rotr(i, x))}"
  puts "ROTR 25: #{bits(x)}"
  puts "         #{'-'*32}"
  puts "Σ1(x):"
  sleep(0.1)
end
sleep(0.1)

# ROTR(25, x)
(25+1).times do |i|
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 6:  #{bits(rotr(6, x))}"
  puts "ROTR 11: #{bits(rotr(11, x))}"
  puts "ROTR 25: #{bits(rotr(i, x))}"
  puts "         #{'-'*32}"
  puts "Σ1(x):"
  sleep(0.1)
end
sleep(0.1)

# ROTR(6, x) ^ ROTR(11, x) ^ ROTR(25, x)
32.downto(1) do |i|
  system "clear"
  puts "x:       #{bits(x)}"
  puts "         #{'-'*32}"
  puts "ROTR 6:  #{bits(rotr(6, x))}"
  puts "ROTR 11: #{bits(rotr(11, x))} XOR"
  puts "ROTR 25: #{bits(rotr(25, x))} XOR"
  puts "         #{'-'*32}"
  puts "Σ1(x):   #{bits(rotr(6, x) ^ rotr(11, x) ^ rotr(25, x))[i-1..-1].rjust(32, " ")}"
  sleep(0.1)
end
sleep(1)


Xor

Xor

  # -----
  # Input
  # -----
  # just do a simple XOR if binary string arguments passed
  if ARGV.size >= 2
    width = ARGV.map(&:size).max # work out the longest binary string (for display purposes)
    system "clear"
    ARGV.each do |binary|
      puts binary.rjust(width, " ")
    end
    puts "-" * width
    puts ARGV.map{|x| x.to_i(2)}.reduce(0, :^).to_s(2).rjust(width, "0")
    exit
  end
  
  # ---------
  # Animation
  # ---------
  # If no arguments passed, show an animation that showcases the XOR operator across 3 inputs
  off   = 0b00000000000000000000000000000000
  on    = 0b11111111111111111111111111111111
  split = 0b10101010101010101010101010101010
  delay = 0.4
  
  # Up To All 1
  system "clear"
  puts ("%032b" % off)
  puts ("%032b" % off) + " XOR"
  puts ("%032b" % off) + " XOR"
  puts "--------------------------------"
  puts "%032b" % (off ^ off ^ off)
  sleep delay
  
  system "clear"
  puts ("%032b" % on)
  puts ("%032b" % off) + " XOR"
  puts ("%032b" % off) + " XOR"
  puts "--------------------------------"
  puts "%032b" % (on ^ off ^ off)
  sleep delay
  
  system "clear"
  puts ("%032b" % on)
  puts ("%032b" % on)  + " XOR"
  puts ("%032b" % off) + " XOR"
  puts "--------------------------------"
  puts "%032b" % (on ^ on ^ off)
  sleep delay
  
  system "clear"
  puts ("%032b" % on)
  puts ("%032b" % on)  + " XOR"
  puts ("%032b" % on)  + " XOR"
  puts "--------------------------------"
  puts "%032b" % (on ^ on ^ on)
  sleep delay
  
  # Back To All 0
  system "clear"
  puts ("%032b" % off)
  puts ("%032b" % on)  + " XOR"
  puts ("%032b" % on)  + " XOR"
  puts "--------------------------------"
  puts "%032b" % (off ^ on ^ on)
  sleep delay
  
  system "clear"
  puts ("%032b" % off)
  puts ("%032b" % off)  + " XOR"
  puts ("%032b" % on)  + " XOR"
  puts "--------------------------------"
  puts "%032b" % (off ^ off ^ on)
  sleep delay
  
  system "clear"
  puts ("%032b" % off)
  puts ("%032b" % off)  + " XOR"
  puts ("%032b" % off)  + " XOR"
  puts "--------------------------------"
  puts "%032b" % (off ^ off ^ off)
  sleep delay
  
  # Only One 1
  system "clear"
  puts ("%032b" % on)
  puts ("%032b" % off) + " XOR"
  puts ("%032b" % off) + " XOR"
  puts "--------------------------------"
  puts "%032b" % (on ^ off ^ off)
  sleep delay
  
  system "clear"
  puts ("%032b" % off)
  puts ("%032b" % on)  + " XOR"
  puts ("%032b" % off) + " XOR"
  puts "--------------------------------"
  puts "%032b" % (off ^ on ^ off)
  sleep delay
  
  system "clear"
  puts ("%032b" % off)
  puts ("%032b" % off) + " XOR"
  puts ("%032b" % on)  + " XOR"
  puts "--------------------------------"
  puts "%032b" % (off ^ off ^ on)
  sleep delay
  
  # Majority 1
  system "clear"
  puts ("%032b" % off)
  puts ("%032b" % on)  + " XOR"
  puts ("%032b" % on)  + " XOR"
  puts "--------------------------------"
  puts "%032b" % (off ^ on ^ on)
  sleep delay
  
  system "clear"
  puts ("%032b" % on)
  puts ("%032b" % off) + " XOR"
  puts ("%032b" % on)  + " XOR"
  puts "--------------------------------"
  puts "%032b" % (on ^ off ^ on)
  sleep delay
  
  system "clear"
  puts ("%032b" % on)
  puts ("%032b" % on)  + " XOR"
  puts ("%032b" % off)  + " XOR"
  puts "--------------------------------"
  puts "%032b" % (on ^ on ^ off)
  sleep delay
  
  # All 1
  system "clear"
  puts ("%032b" % on)
  puts ("%032b" % on)  + " XOR"
  puts ("%032b" % on)  + " XOR"
  puts "--------------------------------"
  puts "%032b" % (on ^ on ^ on)
  sleep delay
  sleep delay
  
  # Split
  system "clear"
  puts ("%032b" % on)
  puts ("%032b" % on)    + " XOR"
  puts ("%032b" % split) + " XOR"
  puts "--------------------------------"
  puts "%032b" % (on ^ on ^ split)
  sleep delay
  
  # Split - Rotate
  def rotr(n, x)
    mask = 2**32 - 1
    right = (x >> n) & mask
    left  = (x << 32-n) & mask
    result = right | left
  end
  
  9.times do |i|
    system "clear"
    puts ("%032b" % on)
    puts ("%032b" % on)    + " XOR"
    puts ("%032b" % rotr(i, split)) + " XOR"
    puts "--------------------------------"
    puts "%032b" % (on ^ on ^ rotr(i, split))
    sleep delay/2
  end
  sleep delay
  
  9.times do |i|
    system "clear"
    puts ("%032b" % on)
    puts ("%032b" % off)    + " XOR"
    puts ("%032b" % rotr(i, split)) + " XOR"
    puts "--------------------------------"
    puts "%032b" % (on ^ off ^ rotr(i, split))
    sleep delay/2
  end
  sleep delay
  
  9.times do |i|
    system "clear"
    puts ("%032b" % off)
    puts ("%032b" % off)    + " XOR"
    puts ("%032b" % rotr(i, split)) + " XOR"
    puts "--------------------------------"
    puts "%032b" % (off ^ off ^ rotr(i, split))
    sleep delay/2
  end
  sleep delay