// MANGLER.CPP // // Copyright (C) 2004-2020 MicroNeil Research Corporation. // // This software is released under the MIT license. See LICENSE.TXT. // // Derived from Version 1 of Mangler Encryption Algorythm, 1984. // Derived from Version 2 of Mangler Encryption Algorythm, 1998. // // Mangler encryption engine object. // Using new optimized chaos driver for uniformity experiments. // Important in this experiment is proof of highest possible entropy. #include "mangler.hpp" namespace codedweller { unsigned char Mangler::ChaosDriver(void) { // Return the current return Fill[Fill[Position]^Fill[Position^0xff]]; // chaos engine output } // value. // As of version 3 the output of the chaos driver was strengthened for // cryptography and to increase the sensitivity of the output for use // as a random number generator. In version 2, the software would simply // return the fill value at the engine's current position. In the new // version two distinct fill values are involved in abstracting the // value of Position and determining the final output value and the Position // value itself is used to add complexity to the output. unsigned char Mangler::Rotate(unsigned char i) { // Bitwise rotates i return ( (i & 0x80)? // This operation is (i<<1)+1: // described without (i<<1) // using asm. ); } void Mangler::ChaosDriver(unsigned char i) { // Drives chaos engine. // First we move our mixing position in the fill buffer forward. Position=( // Move mixing position. Position+1+ // Move at least 1, then (Fill[Position]&0x0f) // maybe a few more. )%256; // But stay within the fill. // The fill position in version 2 was simply incremented. This allowed // for an attacker to predict something important about the state of // the chaos engine. The new method above uses abstraction through the // fill buffer to introduce "jitter" when setting a new position based // on data that is hidden from the outside. // Next we abstract the incoming character through the fill buffer and // use it to select fill data to rotate and swap. unsigned char Swap = ((Fill[Position]^Fill[i])+Position+i)%256; unsigned char Tmp; Tmp = Fill[Swap]; Fill[Swap]=Fill[Position]; Fill[Position]=Rotate(Tmp); // Whenever the Swap and Path positions are the same, the result is // that no data is swapped in the chaos field. We resolve that by // recalling the ChaosDriver. This has the added effect of increasing // the complexity and making it more difficult to predict the state // of the engine... particularly because the engine evloves to a new // state under these conditions without having exposed that change // to the outside world. if(Position==Swap) ChaosDriver(Tmp); // If we didn't swap, recurse. } // The encryption / decryption scheme works by modulating an input data // stream with a chaotic system and allowing the encrypted stream to drive // the chaotic system of both the transmitter and receiver. This will // synchronize the two chaotic systems and allow the receiving system to // "predict" the state of the transmiting system so that it can properly // demodulate the encrypted stream. Both chaotic systems must start in the // same state with the same fill data characteristics or else the two // chaotic systems evolve to further divergent states. unsigned char Mangler::Encrypt(unsigned char i) { unsigned char g = ChaosDriver() ^ i; // Take the output of the ChaosDriver(g); // chaos engine and use it return g; // to moduleate the input. } // Then drive the engine // with the encrypted data. unsigned char Mangler::Decrypt(unsigned char i) { unsigned char g = ChaosDriver() ^ i; // Take the output of the ChaosDriver(i); // chaos engine and use it return g; // to demodulate the input. } // then drive the engine // with the original input. Mangler::Mangler(void) : Position(0) { // The default constructor sets for(unsigned int c = 0;c<256;c++) // the key to the root primary Fill[c]=(unsigned char) c; // value and Position to 0. } } // End namespace codedweller