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");
    }
Ejemplo n.º 2
0
    /// <summary>Decrypts the data and then verifys it.</summary>
    /// <param name="EncryptedData">The data to decrypt and verify.</param>
    /// <returns>The verified and decrypted data.</returns>
    public void DecryptAndVerify(SecurityDataMessage sdm) {
      if(_closed) {
        throw new Exception("SecurityHandler: closed");
      } else if(sdm.Epoch != Epoch) {
        throw new Exception(String.Format("Wrong index {0}, it should be {1}.",
              sdm.Epoch, Epoch));
      }

      int seqid = sdm.Seqid;

      // Verify the seqid
      // If greater than current, new seqid and allow packet
      // If less than current but within window, allow packet
      // Else throw exception
      if(UseWindow) {
        if(seqid == Int32.MaxValue) {
          Close();
          throw new Exception("Maximum amount of packets sent over SecurityHandler.");
        } else if(seqid + WINDOW_SIZE < _last_incoming_seqid) {
          throw new Exception(String.Format("Invalid seqid: {0}, current seqid: {1}, window: {2}.",
                              seqid, _last_incoming_seqid, WINDOW_SIZE));
        }
      }

      sdm.Decrypt(_decryptor);
      if(!sdm.Verify(_incoming_auth)) {
        throw new Exception("Invalid signature");
      }

      if(seqid > _last_incoming_seqid) {
        int tmp = Interlocked.Exchange(ref _last_incoming_seqid, seqid);
        if(tmp > _last_incoming_seqid) {
          seqid = tmp;
          tmp = Interlocked.Exchange(ref _last_incoming_seqid, seqid);
        }
        seqid = tmp;
      }
    }