#!/usr/bin/php millsize = 19; $this->beltwidth = 13; $this->beltheight = 3; $this->mill2belt = $this->beltwidth - 1; $this->m2bOffsetB = 1; $this->m2bOffsetM = 1; $this->b2mOffset = $this->beltwidth; $this->gammaOffset = 7; $this->theta = array(0,1,4); $this->thetaXOR = 0; $this->iota = array(0); $this->iotaXOR = 1; $this->wordsize = 32; $this->mask = 0xffffffff; $this->rmask = 0x7fffffff; $this->initval = 0; $this->millrounds = 1; } protected function init_rg() { # RG32 constants $this->mill = array(); $this->belt = array(); # Init mill for($a = 0; $a < $this->millsize; $a++) { $this->mill[$a] = $this->initval; } # Init belt for($a = 0; $a < $this->beltheight; $a++) { $this->belt[$a] = array(); for($b = 0; $b < $this->beltwidth; $b++) { $this->belt[$a][$b] = $this->initval; } } # Which word to show on output $this->phase = 2; } protected function millfunction() { $A = array(); # Copy of mill $rotate = 0; $tmp = 0; for($i=0;$i<$this->millsize;$i++) { # This is a more concise way of expressing # triangular numbers than in the spec # r=c+r&31 in C (& lower precedence than +) $rotate = ($rotate + $i) % $this->wordsize; $g = $i * $this->gammaOffset; $tmp = $this->mill[$g % $this->millsize]; $tmp ^= $this->mill[($g + 1) % $this->millsize] | ($this->mill[($g + 2) % $this->millsize] ^ $this->mask); # PHP32 can not do right shifts on 32-bit words # without an ugly hack, since PHP does not have # a logical right shift. Hence, rmask. if(!$rotate) {$A[$i] = $tmp;} else { $A[$i] = ((($tmp >> $rotate) & ($this->rmask >> ($rotate - 1))) | ($tmp << ($this->wordsize - $rotate))) & $this->mask; } } for($i=0;$i<$this->millsize;$i++) { $this->mill[$i] = $this->thetaXOR; foreach($this->theta as $t) { $this->mill[$i] ^= $A[($i + $t) % $this->millsize]; } } foreach($this->iota as $io) { $this->mill[$io] ^= $this->iotaXOR; } } protected function beltfunction() { $beltsave = array(); $millsave = array(); # Belt function: Simple rotation (Page 9) for($beltrow = 0; $beltrow < $this->beltheight; $beltrow++) { $beltsave[$beltrow] = $this->belt[$beltrow][ $this->beltwidth - 1]; for($beltcol = $this->beltwidth - 1; $beltcol > 0; $beltcol--) { $this->belt[$beltrow][$beltcol] = $this->belt[$beltrow][$beltcol - 1]; } $this->belt[$beltrow][$beltcol] = $beltsave[$beltrow]; } # Mill->Belt feedforward (Page 9) for($i = 0; $i < $this->mill2belt; $i++) { $this->belt[$i % $this->beltheight][ ($i + $this->m2bOffsetB) % $this->beltwidth] ^= $this->mill[($i + $this->m2bOffsetM) % $this->millsize]; } # Mill for($i = 0; $i < $this->millrounds; $i++) { $this->millfunction(); } # Belt->Mill feedforward for($i = 0; $i < $this->beltheight; $i++) { $this->mill[$this->b2mOffset + $i] ^= $beltsave[$i]; } } # This code assumes 3 words to map and 32-bit words # It also assumes that input is always a multiple of # eight bits long (RadioGatún is not defined for non-octet # input), and hard-codes 0x01 as RadioGatún’s padding (the # padding is not defined when RadioGatún’s word length is not # a multiple of 8) protected function input_map($in) { for(;;) { for($a = 0; $a < 3; $a++) { $s = 0; for($q = 0; $q < 4; $q++) { $w = ord($in); if(strlen($in) < 1) { $w = 1; } $s |= $w << (8 * $q); if(strlen($in) < 1) { $this->belt[$a][0] ^= $s; $this->mill[$a + 16] ^= $s; for($c = 0; $c < 17; $c++) { $this->beltfunction(); } return; } $in = substr($in, 1); } $this->belt[$a][0] ^= $s; $this->mill[$a + 16] ^= $s; } $this->beltfunction(); } } # Create a 32-bit word based on RG’s internal state # This code assumes that we pull two words from the mill before # running the beltmill, that 32-bit words are little-endian, that # the words are 32 bits long public function rg() { if($this->phase == 2) { $this->phase = 1; $this->beltfunction(); } else { $this->phase = 2; } $i = $this->mill[$this->phase]; $i = (($i & 0xff) << 24) | (($i & 0xff00) << 8) | (($i & 0xff0000) >> 8) | # Again, PHP32 has right-shift issues (($i >> 24) & 0xff); return $i; } protected function debug_show_mill() { for($a=0;$a<$this->millsize;$a++) { printf("m[%2d] = 0x%08x ",$a,$this->mill[$a]); if($a % 4 == 3) {print "\n";} } print "\n\n"; } protected function debug_show_belt() { for($a=0;$a<$this->beltheight;$a++) { for($b=0;$b<$this->beltwidth;$b++) { printf("b[%d][%2d] = 0x%08x ", $a, $b, $this->belt[$a][$b]); if(($b % 3) == 2) {print "\n";} } print "\n"; } } public function __construct($seed) { $this->rg32_params(); $this->init_rg(); $this->input_map($seed); } } # This is testing code which I used to make sure this code # generates correct test vectors. #@$in = $argv[1]; #$test = new rg32($in); #for($a=0;$a<8;$a++) { # printf("%08x", $test->rg()); #} #print "\n"; ?>