/**
         * Loop to encode a data packet nIterations times.
         * @param nIterations The number of iterations.
         * @param useComplex If true, use a large name, large content and all fields.
         * If false, use a small name, small content
         * and only required fields.
         * @param useCrypto If true, sign the data packet.  If false, use a blank
         * signature.
         * @param keyType KeyType.RSA or EC, used if useCrypto is true.
         * @param encoding Set encoding[0] to the wire encoding.
         * @return The number of seconds for all iterations.
         */
        private static double benchmarkEncodeDataSeconds(int nIterations, bool useComplex, bool useCrypto, KeyType keyType,
        Blob[] encoding)
        {
            Name name;
              Blob content;
              if (useComplex) {
            // Use a large name and content.
            name = new Name
              ("/ndn/ucla.edu/apps/lwndn-test/numbers.txt/%FD%05%05%E8%0C%CE%1D/%00");

            StringBuilder contentStream = new StringBuilder();
            int count = 1;
            contentStream.append(count++);
            while (contentStream.toString().Length < 1115)
              contentStream.append(" ").append(count++);
            content = new Blob(contentStream.toString());
              }
              else {
            // Use a small name and content.
            name = new Name("/test");
            content = new Blob("abc");
              }
              Name.Component finalBlockId =
            new Name.Component(new Blob(new byte[] { (byte)0 }));

              // Initialize the KeyChain storage in case useCrypto is true.
              MemoryIdentityStorage identityStorage = new MemoryIdentityStorage();
              MemoryPrivateKeyStorage privateKeyStorage = new MemoryPrivateKeyStorage();
              KeyChain keyChain = new KeyChain
            (new IdentityManager(identityStorage, privateKeyStorage),
              new SelfVerifyPolicyManager(identityStorage));
              Name keyName = new Name("/testname/DSK-123");
              Name certificateName = keyName.getSubName(0, keyName.size() - 1).append
            ("KEY").append(keyName.get(-1)).append("ID-CERT").append("0");
              privateKeyStorage.setKeyPairForKeyName
              (keyName, KeyType.RSA, new ByteBuffer(DEFAULT_RSA_PUBLIC_KEY_DER),
            new ByteBuffer(DEFAULT_RSA_PRIVATE_KEY_DER));

              Blob signatureBits = new Blob(new byte[256]);
              Blob emptyBlob = new Blob(new byte[0]);

              double start = getNowSeconds();
              for (int i = 0; i < nIterations; ++i) {
            Data data = new Data(name);
            data.setContent(content);
            if (useComplex) {
              data.getMetaInfo().setFreshnessPeriod(30000);
              data.getMetaInfo().setFinalBlockId(finalBlockId);
            }

            if (useCrypto)
              // This sets the signature fields.
              keyChain.sign(data, certificateName);
            else {
              // Imitate IdentityManager.signByCertificate to set up the signature
              //   fields, but don't sign.
              KeyLocator keyLocator = new KeyLocator();
              keyLocator.setType(KeyLocatorType.KEYNAME);
              keyLocator.setKeyName(certificateName);
              Sha256WithRsaSignature sha256Signature =
            (Sha256WithRsaSignature)data.getSignature();
              sha256Signature.setKeyLocator(keyLocator);
              sha256Signature.setSignature(signatureBits);
            }

            encoding[0] = data.wireEncode();
              }
              double finish = getNowSeconds();

              return finish - start;
        }
        /// <summary>
        /// Append a timestamp component and a random value component to interest's
        /// name. This ensures that the timestamp is greater than the timestamp used in
        /// the previous call. Then use keyChain to sign the interest which appends a
        /// SignatureInfo component and a component with the signature bits. If the
        /// interest lifetime is not set, this sets it.
        /// </summary>
        ///
        /// <param name="interest">The interest whose name is append with components.</param>
        /// <param name="keyChain">The KeyChain for calling sign.</param>
        /// <param name="certificateName">The certificate name of the key to use for signing.</param>
        /// <param name="wireFormat"></param>
        public void generate(Interest interest, KeyChain keyChain,
				Name certificateName, WireFormat wireFormat)
        {
            double timestamp;
             lock (lastTimestampLock_) {
                        timestamp = Math.Round(net.named_data.jndn.util.Common.getNowMilliseconds(),MidpointRounding.AwayFromZero);
                        while (timestamp <= lastTimestamp_)
                            timestamp += 1.0d;
                        // Update the timestamp now while it is locked. In the small chance that
                        //   signing fails, it just means that we have bumped the timestamp.
                        lastTimestamp_ = timestamp;
                    }

            // The timestamp is encoded as a TLV nonNegativeInteger.
            TlvEncoder encoder = new TlvEncoder(8);
            encoder.writeNonNegativeInteger((long) timestamp);
            interest.getName().append(new Blob(encoder.getOutput(), false));

            // The random value is a TLV nonNegativeInteger too, but we know it is 8 bytes,
            //   so we don't need to call the nonNegativeInteger encoder.
            ByteBuffer randomBuffer = ILOG.J2CsMapping.NIO.ByteBuffer.allocate(8);
            // Note: SecureRandom is thread safe.
            net.named_data.jndn.util.Common.getRandom().nextBytes(randomBuffer.array());
            interest.getName().append(new Blob(randomBuffer, false));

            keyChain.sign(interest, certificateName, wireFormat);

            if (interest.getInterestLifetimeMilliseconds() < 0)
                // The caller has not set the interest lifetime, so set it here.
                interest.setInterestLifetimeMilliseconds(1000.0d);
        }
        static void Main(string[] args)
        {
            var data = new Data();
              data.wireDecode(new Blob(TlvData));
              Console.Out.WriteLine("Decoded Data:");
              dumpData(data);

              // Set the content again to clear the cached encoding so we encode again.
              data.setContent(data.getContent());
              var encoding = data.wireEncode();

              var reDecodedData = new Data();
              reDecodedData.wireDecode(encoding);
              Console.Out.WriteLine("");
              Console.Out.WriteLine("Re-decoded Data:");
              dumpData(reDecodedData);

              var identityStorage = new MemoryIdentityStorage();
              var privateKeyStorage = new MemoryPrivateKeyStorage();
              var keyChain = new KeyChain
            (new IdentityManager(identityStorage, privateKeyStorage),
              new SelfVerifyPolicyManager(identityStorage));

              // Initialize the storage.
              var keyName = new Name("/testname/DSK-123");
              var certificateName = keyName.getSubName(0, keyName.size() - 1).append
            ("KEY").append(keyName.get(-1)).append("ID-CERT").append("0");
              identityStorage.addKey(keyName, KeyType.RSA, new Blob(DEFAULT_RSA_PUBLIC_KEY_DER));
              privateKeyStorage.setKeyPairForKeyName
            (keyName, KeyType.RSA, new ByteBuffer(DEFAULT_RSA_PUBLIC_KEY_DER),
              new ByteBuffer(DEFAULT_RSA_PRIVATE_KEY_DER));

              VerifyCallbacks callbacks = new VerifyCallbacks("Re-decoded Data");
              keyChain.verifyData(reDecodedData, callbacks, callbacks);

              var freshData = new Data(new Name("/ndn/abc"));
              freshData.setContent(new Blob("SUCCESS!"));
              freshData.getMetaInfo().setFreshnessPeriod(5000);
              freshData.getMetaInfo().setFinalBlockId(new Name("/%00%09").get(0));
              keyChain.sign(freshData, certificateName);
              Console.Out.WriteLine("");
              Console.Out.WriteLine("Freshly-signed Data:");
              dumpData(freshData);

              callbacks = new VerifyCallbacks("Freshly-signed Data");
              keyChain.verifyData(freshData, callbacks, callbacks);
        }