UsageEdit

This module calculates the RadioGatún[32] sum for a given string, returning it in a format suitable for showing a demonstration sum on a Wikipedia page. RadioGatún is a cryptographic hash function from 2006 which remains, as of 2022, unbroken.

To use:

{{#invoke:RadioGatun32|rg32|String to input}}

Or with the template (at Template:RadioGatun32):

{{RadioGatun32|String to input}}

If there is {{Background color|#888|d}} in the string to input, the calculated sum will be based on a string without the background color formatting.

The rg32hash callEdit

It is also possible to show the raw hexadecimal RadioGatun[32] sum of a given string without any formatting:

{{#invoke:RadioGatun32|rg32sum|String to input}}

For example, if we run:

{{#invoke:RadioGatun32|rg32sum|1234}}

We will get this:

9EBDD24F469993796C4AAC6A821735A65A3CDEF8A359944CE71F34E7A08E1182

This should output "9EBDD24F469993796C4AAC6A821735A65A3CDEF8A359944CE71F34E7A08E1182".

ExamplesEdit

{{#invoke:RadioGatun32|rg32|Hello, world}}

Will create this output:

RadioGatun[32]("Hello, world") =
D91BBD22BE5D01F091F26A16704CDA0E165588E025D9BA6619C5B01550756349

Here is the computed output:

RadioGatun[32]("Hello, world") =
D91BBD22BE5D01F091F26A16704CDA0E165588E025D9BA6619C5B01550756349

We can have background colors:

{{#invoke:RadioGatun32|rg32|{{Background color|#ff8cc0|Li}}{{Background color|#c08dff|fe}}!}}

Shows us this:

RadioGatun[32]("Template:Background colorTemplate:Background color!") =
8B14915DF10B04CF6DE9BBAD6A2FACC6855EAB4D618255626DDD3B0DFB9A95AC

The above should look exactly like this:

RadioGatun[32]("Template:Background colorTemplate:Background color!") =
80E706E851DCDE1170452EEC6EAD24F40E63B9A07B86D8D32053A1237835E03D

The computed sum will be for the string Life!, as can be seen in the following:

RadioGatun[32]("Life!") =
80E706E851DCDE1170452EEC6EAD24F40E63B9A07B86D8D32053A1237835E03D

The above should look like this:

RadioGatun[32]("Life!") =
80E706E851DCDE1170452EEC6EAD24F40E63B9A07B86D8D32053A1237835E03D

The background colors do not affect the computed RadioGatun[32] sum.

TestingEdit

Testing inside MediawikiEdit

To test this in Mediawiki, go to Module talk:RadioGatun32/testcases, and verify that one sees "All RadioGatun[32] test vectors pass". One can rerun the test by going to Module:RadioGatun32/testcases, clicking on "edit this page", then in the debug console at the bottom, typing in print(p.test()). One should then see "All RadioGatun[32] test vectors pass".

Another way to test this is to add {{#invoke:RadioGatun32/testcases|test}} to a page; wherever RadioGatun32/test is invoked, it should show "All RadioGatun[32] test vectors pass".

Testing outside MediawikiEdit

This module can either be run as a Mediawiki Lua module, or as a standalone Lua script. This very same script is also available on GitHub in a repo which includes automated tests to ensure implementations of RadioGatun[32] generate correct hashes against a number of test inputs, including all official RadioGatun[32] test vectors.

To test this code, in a *NIX compatible environment like Linux, with Git and a version of Lua above 5.1 and below 5.4 (Lua 5.4 dropped bit32; a Lua 5.1 implementation with bit32 support will also work), do the following:

git clone https://github.com/samboy/rg32hash
cd rg32hash/sqa
./do.test.sh ../Lua/rg32wiki.sh

See alsoEdit


-- Placed in the public domain 2020, 2022 Sam Trenholme

-- This is a version of RadioGatun[32] (RG32) which uses bit32.
-- Wikipedia has bit32 in an external library
if not bit32 then
  bit32 = require("bit32")
end

local p = {}

-- Note that belt and mill are 1-indexed here
local function beltMill(belt, mill)

  -- Mill to belt feedforward
  for z = 0, 11 do
    local offset = z + ((z % 3) * 13) + 1
    belt[offset] = bit32.bxor(belt[offset],mill[z + 2])
  end

  -- Mill core
  local rotate = 0
  local millPrime = {}
  for z = 0, 18 do
    rotate = rotate + z
    local view = (z * 7) % 19
    local num = mill[view + 1]
    view = (view + 1) % 19
    local viewPrime = (view + 1) % 19
    num = bit32.bxor(num,bit32.bor(mill[view + 1],
                     bit32.bnot(mill[viewPrime + 1])))
    num = bit32.rrotate(num,rotate)
    millPrime[z + 1] = num
  end
  for z = 0, 18 do
    local view = (z + 1) % 19
    local viewPrime = (z + 4) % 19
    mill[z + 1] = bit32.bxor(millPrime[z + 1],
        millPrime[view + 1],millPrime[viewPrime + 1])
  end

  -- Belt rotate
  for z = 39, 1, -1 do
     belt[z + 1] = belt[z]
  end
  for z = 0, 2 do
     belt[(z * 13) + 1] = belt[((z + 1) * 13) + 1]
  end

  -- Belt to mill
  for z = 0, 2 do
     mill[14 + z] = bit32.bxor(belt[(z * 13) + 1],mill[14 + z])
  end

  -- Iota
  mill[1] = bit32.bxor(mill[1],1)
end

-- Debug function to show the belt and mill
local function showBeltMill(belt, mill)
  for z = 1, 13 do
    print(string.format("%2d %08x %08x %08x %08x",z,mill[z],belt[z],
                        belt[z + 13],belt[z + 26]))
  end
  for z = 14, 19 do
    print(string.format("%2d %08x",z,mill[z]))
  end
end

local function initBeltMill()
  local belt = {}
  local mill = {}
  for z = 1, 40 do
    belt[z] = 0
  end
  for z = 1, 19 do
    mill[z] = 0
  end
  return belt, mill
end

-- Output strings which are hex numbers in the same endian order
-- as RadioGatun[32] test vectors, given a float
local function makeLittleEndianHex(i)
  local out = ""
  for z = 1, 4 do
    i = math.floor(i)
    out = out .. string.format("%02X",i % 256)
    i = i / 256
  end
  return out
end

-- Output a 256-bit digest string, given a radiogatun state.  Affects belt and
-- mill, returns string
local function makeRG32sum(belt, mill)
  local out = ""
  for z = 1, 4 do
    out = out .. makeLittleEndianHex(mill[2]) .. makeLittleEndianHex(mill[3])
    beltMill(belt, mill)
  end
  return out
end

-- RadioGatun input map; given string return belt, mill
local function RG32inputMap(i)
  local belt, mill
  belt, mill = initBeltMill()
  local phase = 0;
  for a = 1, string.len(i) do
    local c = string.byte(i, a)
    local b
    c = c % 256
    c = c * (2 ^ (8 * (phase % 4)))
    b = math.floor(phase / 4) % 3
    belt[(13 * b) + 1] = bit32.bxor(belt[(13 * b) + 1],c)
    mill[17 + b] = bit32.bxor(mill[17 + b],c)
    phase = phase + 1
    if phase % 12 == 0 then
      beltMill(belt, mill)
    end
  end

  -- Padding byte
  local b = math.floor(phase / 4) % 3
  local c = 2 ^ (8 * (phase % 4))
  belt[(13 * b) + 1] = bit32.bxor(belt[(13 * b) + 1],c)
  mill[17 + b] = bit32.bxor(mill[17 + b],c)

  -- Blank rounds
  for z = 1, 18 do
    beltMill(belt,mill)
  end
  return belt, mill
end

-- Get the input string from a function input
-- depending on how the parent function is called, this can be a Mediawiki 
-- table with all args or it can be a simple string.
local function grabString(i)
  local input = i
  if type(input) == "table" then
    local args = nil
    local pargs = nil
    args = input.args
    pargs = input:getParent().args
    if args and args[1] then 
      input = args[1]
    elseif pargs and pargs[1] then
      input = pargs[1]
    else
      input = "1234" -- Default value
    end
  end
  return input
end

-- Given an input string, make a string with the hex RadioGatun[32] sum
function p.rg32sum(i)
  local belt, mill = RG32inputMap(grabString(i))
  return makeRG32sum(belt,mill)
end

-- Given an input to hash, return a formatted version of the hash
-- with both the input and hash value
function p.rg32(i)
  local input = grabString(i)
  local rginput
  -- Remove formatting from the string we give to the rg32 engine
  rginput = input:gsub("{{Background color|#%w+|(%w+)}}","%1")
  rginput = rginput:gsub("<[^>]+>","") -- Remove HTML tags
  rginput = rginput:gsub("%[%[Category[^%]]+%]%]","") -- Remove categories
  local sum = p.rg32sum(rginput)
  -- This is the output in Mediawiki markup format we give to
  -- the caller of this function
  return(' RadioGatun[32]("' .. input .. '") =\n ' .. sum)
end

-- This script is a standalone Lua script outside of the Wikipedia
if not mw then
  if arg and arg[1] then
    print(p.rg32(arg[1]))
  else
    print(p.rg32(
'The quick brown fox jumps over the lazy {{Background color|#87CEEB|d}}og'))
  end
end

return p