/// <summary>First signs the data and then encrypts it.</summary>
        /// <param name="UnecryptedData">The data to sign and encrypt.</param>
        /// <returns>The signed and encrypted data.</returns>
        public void SignAndEncrypt(SecurityDataMessage sdm)
        {
            if (_closed)
            {
                throw new Exception("SecurityHandler: closed");
            }
            // Get the sequence id and increment the counter
            int seqid = ++_last_outgoing_seqid;

            // We ask for an update at the half life and every 1000 packets thereafter
            if (seqid == HALF_LIFE || (seqid > HALF_LIFE && seqid % 1000 == 0))
            {
                if (Update != null)
                {
                    Update(Epoch, EventArgs.Empty);
                }
            }

            sdm.Seqid = seqid;
            sdm.Epoch = Epoch;
            sdm.Sign(_outgoing_auth);
            sdm.Encrypt(_encryptor);
        }
        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");
        }