and implement with:
<?php require_once('../../library/initialise.php'); class Enigma_SteckerBoardTest extends PHPUnit_Framework_TestCase { /** * Test various stecker combinations, swapped and non-swapped characters * @dataProvider steckerSwapsDataProvider * @param $steckers Array pairs of letters * @param $in String single character * @param $out String single character * @return null */ function testSubstitutions($steckers, $in, $out) { $steckerBoard=new Enigma_SteckerBoard(); $steckerBoard->setSteckers($steckers); $this->assertSame( $out, $steckerBoard->getOutputCharacterForInputCharacter($in), "Stecker must substitute pair as specified" ); $this->assertSame( $in, $steckerBoard->getOutputCharacterForInputCharacter($out), "Stecker substitution must be reciprocal" ); } function steckerSwapsDataProvider() { 'D'=>'N','G'=>'R','I'=>'S','K'=>'C','Q'=>'X', 'T'=>'M','P'=>'V','H'=>'Y','F'=>'W','B'=>'J' ), 'K', 'C', ), 'D'=>'N','G'=>'R','I'=>'S','K'=>'C','Q'=>'X', 'T'=>'M','P'=>'V','H'=>'Y','F'=>'W','B'=>'J' ), 'E', 'E', ), ), ) ); return ($testData); }
With a little modification, we can adopt our previous CLI test script to try a steckered message. However, we need to make a slight tweak to the Enigma_Machine class to use the Steckerboard, which is currently disabled.
<?php class Enigma_SteckerBoard implements Enigma_Encryptor_Interface { public function clearAllSteckers() { } public function setStecker($from,$to) { throw new Exception("Invalid stecker pair $from-$to"); } throw new Exception("Stecker socket $from already used"); } throw new Exception("Stecker socket $to already used"); } $this->_steckers[$from]=$to; $this->_steckers[$to]=$from; } public function setSteckers($assocArray) { $this->clearAllSteckers(); foreach($assocArray as $from=>$to) { $this->setStecker($from,$to); } } public function getOutputCharacterForInputCharacter ($inputCharacter) { $char=$this->_steckers[$inputCharacter]; } else { $char=$inputCharacter; } return $char; } }
We can take a genuine wartime message from Stefan Krah's M4 Project, and adapt our previous testRig.php to simulate a steckered four-wheel device:
/** * Constructor * * @param $numSlots integer Number of Rotor slots * @param $hasSteckerBoard boolean Does this machine have a steckerboard * @return null */ public function __construct($numSlots=3, $hasSteckerBoard=true) { throw new Exception('Number of slots must be positive integer'); } throw new Exception('Steckerboard flag must be boolean'); } $this->_numSlots=$numSlots; $this->_hasSteckerBoard=$hasSteckerBoard; if($this->_hasSteckerBoard) { // Can implement this later! $this->_steckerBoard=new Enigma_SteckerBoard; } for($i=0; $i<$this->_numSlots; $i++) { $this->_slots[$i]=new Enigma_RotorSlot; if($i>0) { //higher slots watch lower ones $this->_slots[$i-1]->registerTurnoverObserver($this->_slots[$i]); } } }
(Note that we're using a new rotor and reflector, both of which were unique to the Naval M4 Enigma - see the repository for their implementation).
<?php require_once ('../library/initialise.php'); $messageString='NCZW VUSX PNYM INHZ XMQX SFWX WLKJ AHSH NMCO CCAK UQPM KCSM HKSE INJU SBLK IOSX CKUB HMLL XCSJ USRR DVKO HULX WCCB GVLI YXEO AHXR HKKF VDRE WEZL XOBA FGYU JQUK GRTV UKAM EURB VEKS UHHV OYHA BCJW MAKL FKLM YFVN RIZR VVRT KOFD ANJM OLBG FFLE OPRG TFLV RHOW OPBE KVWM UQFM PWPA RMFH AGKX IIBG '; //var_dump($messageArray); foreach($messageArray as $char) { } } 'N'=>'W','O'=>'P','Q'=>'Y','R'=>'Z','V'=>'X'); $device=new Enigma_Machine(4,true); $rotors[0]=new Enigma_Rotor_I; $rotors[0]->setRingOffset('V'); $rotors[1]=new Enigma_Rotor_IV; $rotors[1]->setRingOffset('A'); $rotors[2]=new Enigma_Rotor_II; $rotors[2]->setRingOffset('A'); $rotors[3]=new Enigma_Rotor_Beta; $rotors[3]->setRingOffset('A'); $device->setRotors($rotors); $reflector=new Enigma_Reflector_Bdunn; $device->setReflector($reflector); $device->getSteckerBoard()->setSteckers($steckers); foreach ($messageArrayClean as $char) { $char=$device->getOutputCharacterForInputCharacter($char); echo $char; } echo ("\n\n");
silverbox:cli wechsler$ php -q m4TestRigWithDeviceAndSteckers.php NCZWVUSXPNYMINHZXMQXSFWXWLKJAHSHNMCOCCAKUQPMKCSMHKSEINJUSBLKIOSXCKUBHMLLXCSJUSRRDVKOHULXWCCBGVLIYXEOAHXRHKKFVDREWEZLXOBAFGYUJQUKGRTVUKAMEURBVEKSUHHVOYHABCJWMAKLFKLMYFVNRIZRVVRTKOFDANJMOLBGFFLEOPRGTFLVRHOWOPBEKVWMUQFMPWPARMFHAGKXIIBG VONVONJLOOKSJHFFTTTEINSEINSDREIZWOYYQNNSNEUNINHALTXXBEIANGRIFFUNTERWASSERGEDRUECKTYWABOSXLETZTERGEGNERSTANDNULACHTDREINULUHRMARQUANTONJOTANEUNACHTSEYHSDREIYZWOZWONULGRADYACHTSMYSTOSSENACHXEKNSVIERMBFAELLTYNNNNNNOOOVIERYSICHTEINSNULLNot what you'd call a user-friendly output, to be honest, but on the flipside it's historically accurate. Even if you speak German - and most of the codebreakers didn't - it's in an unfriendly format, and full of military terms and abbreviations. All that the codebreakers needed to know was that they'd produced something that looked reasonably like German, and then they'd pass it over to the intelligence team for analysis.
All content copyright Richard George (richard@phase.org), 2009-2010
Sponsored links to recommended books: