diff --git a/lib/modules/Crypto.pmod/module.pmod b/lib/modules/Crypto.pmod/module.pmod
index a08da57..5efedc1 100644
--- a/lib/modules/Crypto.pmod/module.pmod
+++ b/lib/modules/Crypto.pmod/module.pmod
@@ -112,3 +112,156 @@ function(string:string) rot13 = Crypto.Substitution()->set_rot_key()->crypt;
 #else
 constant this_program_does_not_exist=1;
 #endif /* constant(Nettle.HashState) */
+
+class _CRC16
+{
+   inherit .CRCState;
+
+   .CRCState `()() { 
+
+   ::init("CRC16", 16, ({ 16, 15, 2, 0 }), 0 , 1, 0, 0 ); 
+   return this;
+   }
+
+}
+
+_CRC16 CRC16 = _CRC16();
+
+
+
+class CRCState
+{
+   string name="";
+   int width;
+   int lsbfirst=0;
+   int lsbfirstdata=0;
+   int xormask=0;
+   int bitmask;
+   int polymask;
+   int inbitmask;
+   int outbitmask;
+   int value;
+
+   //! Initialize the CRC object.
+   //! @param width
+   //!    The length of the polynomial.
+   //! @param polynomial
+   //!    The polynomial, either an array or integer.
+   //! @param seed
+   //!    The starting value of the algoritm
+   //! @param lsbfirst
+   //!    Calculate the CRC from msb to lsb (zero) or lsb to msb (non zero).
+   //! @param lsbfirstdata
+   //!    Calculate the data words from msb to lsb (zero) or lsb to msb (non zero).
+   //!    If lsbfirstdata is zero, lsbfirstdata behaviour follows lsbfirst.
+   //!  @param xormask
+   //!     The output mask for the final computed CRC.
+   void init ( string name, int(0..) width, int|array polynomial, int seed, int lsbfirst, int lsbfirstdata, int xormask )
+   {
+      this->name=name;
+      this->value = seed;
+      this->width=width;
+      this->lsbfirst=lsbfirst;
+      this->lsbfirstdata=lsbfirstdata | lsbfirst;
+      this->xormask=xormask;
+
+      int word = 0;
+      if (arrayp(polynomial))
+      {
+         foreach(polynomial,int n)
+            word |= 1 << n;
+      }
+      else
+         word=polynomial;
+
+      bitmask = (1 << width) -1;
+      polymask = word & bitmask;
+
+      if(lsbfirst)
+      {
+         polymask = Int.reflect(polymask,width);
+         inbitmask = 1 << (width -1 );
+         outbitmask = 1;
+      }
+      else
+      {
+         this->inbitmask = 1;
+         this->outbitmask = 1 << ( width -1 );
+      }
+
+
+   }
+
+   //! Add's one bit to the CRC calculation.
+   void take_bit( int bit )
+   {
+      int outbit;
+      if ( bit > 1 || bit < 0 )
+         werror( "Values other then 0 or 1 are not allowed for bits\n");
+      outbit = ((this->value & this->outbitmask) !=0 );
+      if ( lsbfirst )
+         value >>= 1;
+      else
+         value <<= 1;
+      value &= bitmask;
+      if ( outbit ^ bit )
+         value ^= polymask;
+   }
+
+   //! Add one word (int) to the CRC calculation.
+   //! @param word
+   //!    The added word (int)
+   //! @param width
+   //!    The bitlength of the word value.
+   //!    If none given a bitlength of 8 is assumed.
+   void take_word( int word, int|void width )
+   {
+      int len = 8;
+      if ( width > 0 )
+         len = width;
+      if ( this->lsbfirstdata )
+         for ( int i = 0; i < len; i++ )
+            this->take_bit( (word >> i) & 1 );
+      else
+         for ( int i = (len-1) ; i >= 0 ; i-- )
+            this->take_bit( (word >> i) & 1 );
+
+   }
+
+   //! Add a string to the CRC computation.
+   //! @param data
+   //!    The string to be added.
+   CRCState update( string data )
+   {
+     int len = String.width( data );
+     foreach( data/"", string data)
+         take_word( data[0] , len);
+     return this;
+   }
+
+   //! Creates a CRC checksum of the string @param data.
+   string hash( string data )
+   {
+      this->update( data );
+      return this->digest();
+   }
+
+   //! Returns the computed CRC value with xormask applied.
+   //! @param length
+   //!    length of the returned hash value. The returned string is
+   //!    zerro padded for lengths larger than the hash length.
+   //!    if length < hash length the complete hash string is returned.
+   string digest(void|int length)
+   {
+      string format;
+
+      if(length)
+         format = sprintf("%%0%dX",length);
+      else
+         format = "%X";
+      return sprintf(format,value ^ xormask);
+   }
+}
+
+
+
