// 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) : 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.
   }


