|
|
|
|
|
|
|
|
|
|
|
// MANGLER.CPP |
|
|
|
|
|
// |
|
|
|
|
|
// (C) 1984-2009 MicroNeil Research Corporation |
|
|
|
|
|
// Derived from Version 1 of Mangler Encryption Algorythm, 1984. |
|
|
|
|
|
// Derived from Version 2 of Mangler Encryption Algorythm, 1998. |
|
|
|
|
|
// |
|
|
|
|
|
|
|
|
|
|
|
// 20021008 _M |
|
|
|
|
|
// Found and corrected range bug in ChaosDriver(void) where |
|
|
|
|
|
// ~Position might access a location outside the fill. Replaced |
|
|
|
|
|
// ~Position with Position^0xff which has the intended effect. |
|
|
|
|
|
|
|
|
|
|
|
// 20020119 _M Version 3.0 |
|
|
|
|
|
// |
|
|
|
|
|
// 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" |
|
|
|
|
|
|
|
|
|
|
|
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) { |
|
|
|
|
|
for(short c = 0;c<256;c++) // The default constructor sets |
|
|
|
|
|
Fill[c]=(unsigned char) c; // the key to the root primary |
|
|
|
|
|
Position = 0; // value and Position to 0. |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|