///  <summary>Creates a new SecurityHandler.  The algorithm used is to
 /// sign the data, append that to the end, and then encrypt the data.</summary>
 /// <param name="in_sa">Used for decrypting.</param>
 /// <param name="out_sa">Used for encrypting.</param>
 /// <param name="in_ha">Used for verifying.</param>
 /// <param name="out_ha">Used for signing.</param>
 /// <param name="epoch">A number to uniquely identify this SH.</param> */
 public SecurityHandler(SymmetricAlgorithm in_sa, SymmetricAlgorithm out_sa,
     HashAlgorithm in_ha, HashAlgorithm out_ha, short epoch)
 {
   _sync = new Object();
   StartTime = DateTime.UtcNow;
   _incoming_auth = in_ha;
   _outgoing_auth = out_ha;
   _encryptor = new SymmetricEncryption(in_sa);
   _decryptor = new SymmetricEncryption(out_sa);
   Epoch = epoch;
   _last_outgoing_seqid = 0;
   _last_incoming_seqid = 0;
   UseWindow = true;
 }
    public void Incoming() {
      SymmetricAlgorithm sa = new RijndaelManaged();
      SymmetricEncryption se = new SymmetricEncryption(sa);
      HashAlgorithm hash = new SHA1CryptoServiceProvider();

      int spi = 12345;
      int epoch = 67890;
      int seqid = 1222;

      Random rand = new Random();
      byte[] data = new byte[144];
      rand.NextBytes(data);
      MemBlock mdata = MemBlock.Reference(data);

      byte[] to_sign = new byte[12 + data.Length];
      int pos = 0;
      NumberSerializer.WriteInt(spi, to_sign, pos);
      pos += 4;
      NumberSerializer.WriteInt(epoch, to_sign, pos);
      pos += 4;
      NumberSerializer.WriteInt(seqid, to_sign, pos);
      pos += 4;
      data.CopyTo(to_sign, pos);

      byte[] signature = hash.ComputeHash(to_sign);
      byte[] to_encrypt = new byte[4 + data.Length + signature.Length];
      pos = 0;
      NumberSerializer.WriteInt(data.Length, to_encrypt, pos);
      pos += 4;
      data.CopyTo(to_encrypt, pos);
      pos += data.Length;
      signature.CopyTo(to_encrypt, pos);

      byte[] encrypted = se.EncryptData(to_encrypt);
      byte[] packet = new byte[12 + encrypted.Length];
      pos = 0;
      NumberSerializer.WriteInt(spi, packet, pos);
      pos += 4;
      NumberSerializer.WriteInt(epoch, packet, pos);
      pos += 4;
      NumberSerializer.WriteInt(seqid, packet, pos);
      pos += 4;
      encrypted.CopyTo(packet, pos);

      MemBlock mpacket = MemBlock.Reference(packet);

      // check 
      SecurityDataMessage sdm_e = new SecurityDataMessage(packet);
      sdm_e.Decrypt(se);
      Assert.AreEqual(spi, sdm_e.SPI, "SPI");
      Assert.AreEqual(epoch, sdm_e.Epoch, "Epoch");
      Assert.AreEqual(seqid, sdm_e.Seqid, "Seqid");
      Assert.AreEqual(mdata, sdm_e.Data, "Data");
      Assert.IsTrue(sdm_e.Verify(hash), "Signature");
      Assert.AreEqual(mpacket, sdm_e.Packet, "Packet");

      SecurityDataMessage sdm_d = new SecurityDataMessage();
      sdm_d.SPI = spi;
      sdm_d.Epoch = epoch;
      sdm_d.Seqid = seqid;
      sdm_d.Data = data;
      sdm_d.Sign(hash);
      sdm_d.Encrypt(se);
      sdm_e = new SecurityDataMessage(sdm_d.Packet);
      sdm_e.Decrypt(se);

      Assert.AreEqual(spi, sdm_e.SPI, "SPI");
      Assert.AreEqual(epoch, sdm_e.Epoch, "Epoch");
      Assert.AreEqual(seqid, sdm_e.Seqid, "Seqid");
      Assert.AreEqual(mdata, sdm_e.Data, "Data");
      Assert.IsTrue(sdm_e.Verify(hash), "Signature");
      Assert.AreEqual(sdm_d.Packet, sdm_e.Packet, "Packet");
    }
 ///<summary>Decrypts the packet given a SymmetricEncryption returning true
 ///if it was able to decrypt it.</summary>
 public bool Decrypt(SymmetricEncryption se) {
   byte[] decrypted = se.DecryptData(_encrypted_data);
   int pos = 0;
   int data_len = NumberSerializer.ReadInt(decrypted, pos);
   pos += 4;
   _data = MemBlock.Reference(decrypted, pos, data_len);
   pos += data_len;
   _signature = MemBlock.Reference(decrypted, pos, decrypted.Length - pos);
   return true;
 }
 ///<summary>Encrypts the packet given a SymmetricEncryption.</summary>
 public void Encrypt(SymmetricEncryption se) {
   byte[] to_encrypt = new byte[4 + _data.Length + _signature.Length];
   int pos = 0;
   NumberSerializer.WriteInt(_data.Length, to_encrypt, pos);
   pos += 4;
   _data.CopyTo(to_encrypt, pos);
   pos += _data.Length;
   _signature.CopyTo(to_encrypt, pos);
   _encrypted_data = se.EncryptData(to_encrypt);
   _update_icpacket = true;
 }
 public void TDES()
 {
   SymmetricEncryption enc = new SymmetricEncryption(new TripleDESCryptoServiceProvider());
   for(int i = 1000; i < 1025; i ++) {
     byte[] data = new byte[1010];
     RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
     rng.GetBytes(data);
     byte[] encd = enc.EncryptData(data);
     if(i % 12 == 0) {
       continue;
     }
     byte[] decd = enc.DecryptData(encd);
     MemBlock mdecd = MemBlock.Reference(decd);
     MemBlock mdata = MemBlock.Reference(data);
     Assert.AreEqual(mdecd, mdata, "TDESEncryption: " + i);
   }
 }