void
DummyClientFace::enableRegistrationReply()
{
  onSendInterest.connect([this] (const Interest& interest) {
    static const Name localhostRegistration("/localhost/nfd/rib");
    if (!localhostRegistration.isPrefixOf(interest.getName()))
      return;

    nfd::ControlParameters params(interest.getName().get(-5).blockFromValue());
    params.setFaceId(1);
    params.setOrigin(0);
    if (interest.getName().get(3) == name::Component("register")) {
      params.setCost(0);
    }

    nfd::ControlResponse resp;
    resp.setCode(200);
    resp.setBody(params.wireEncode());

    shared_ptr<Data> data = make_shared<Data>(interest.getName());
    data->setContent(resp.wireEncode());

    KeyChain keyChain;
    keyChain.sign(*data, security::SigningInfo(security::SigningInfo::SIGNER_TYPE_SHA256));

    this->getIoService().post([this, data] { this->receive(*data); });
  });
}
BOOST_FIXTURE_TEST_CASE(Exemption, CommandInterestFixture)
{
  KeyChain keyChain;
  Name identity("/TestCommandInterest/AnyKey");

  Name certName;
  BOOST_REQUIRE_NO_THROW(certName = keyChain.createIdentity(identity));

  CommandInterestGenerator generator;
  CommandInterestValidator validator;

  validator.addInterestBypassRule("^<TestCommandInterest><Exemption>");

  //Test a legitimate command
  shared_ptr<Interest> commandInterest1 =
    make_shared<Interest>("/TestCommandInterest/Exemption/Command1");
  generator.generateWithIdentity(*commandInterest1, identity);
  validator.validate(*commandInterest1,
                     bind(&CommandInterestFixture::validated, this, _1),
                     bind(&CommandInterestFixture::validationFailed, this, _1, _2));

  BOOST_CHECK_EQUAL(m_validity, true);

  BOOST_CHECK_NO_THROW(keyChain.deleteIdentity(identity));
}
int
ndnsec_unlock_tpm(int argc, char** argv)
{
#ifdef NDN_CXX_HAVE_GETPASS
  using namespace ndn;
  namespace po = boost::program_options;

  std::string keyName;

  po::options_description description("General Usage\n  ndnsec unlock-tpm [-h] \nGeneral options");
  description.add_options()
    ("help,h", "produce help message")
    ;

  po::variables_map vm;

  try
    {
      po::store(po::parse_command_line(argc, argv, description), vm);
      po::notify(vm);
    }
  catch (const std::exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      std::cerr << description << std::endl;
      return 1;
    }

  if (vm.count("help") != 0)
    {
      std::cerr << description << std::endl;
      return 0;
    }

  bool isUnlocked = false;

  KeyChain keyChain;

  char* password;
  password = getpass("Password to unlock the TPM: ");
  isUnlocked = keyChain.unlockTpm(password, strlen(password), true);
  memset(password, 0, strlen(password));

  if (isUnlocked)
    {
      std::cerr << "OK: TPM is unlocked" << std::endl;
      return 0;
    }
  else
    {
      std::cerr << "ERROR: TPM is still locked" << std::endl;
      return 1;
    }
#else
  std::cerr << "ERROR: Command not supported on this platform" << std::endl;
  return 1;
#endif // NDN_CXX_HAVE_GETPASS
}
BOOST_FIXTURE_TEST_CASE(ConstructorEmpty2Config, TestHomeAndPibFixture<PibPathEmptyFile>)
{
  createClientConf({"tpm=tpm-file:%PATH%"});

  BOOST_REQUIRE_NO_THROW(KeyChain());

  KeyChain keyChain;
  BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:");
  BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-file:" + m_pibDir);
  BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:" + m_pibDir);
}
inline void
CommandInterestGenerator::generate(Interest& interest,
                                   const Name& certificateName /*= Name()*/)
{
  if (certificateName.empty())
    m_keyChain.sign(interest);
  else
    m_keyChain.sign(interest,
                    security::SigningInfo(security::SigningInfo::SIGNER_TYPE_CERT,
                                          certificateName));
}
Exemple #6
0
void
CommandInterestGenerator::generate
  (Interest& interest, KeyChain& keyChain, const Name& certificateName,
   WireFormat& wireFormat)
{
  MillisecondsSince1970 timestamp = ::round(ndn_getNowMilliseconds());
  while (timestamp <= lastTimestamp_)
    timestamp += 1.0;

  // The timestamp is encoded as a TLV nonNegativeInteger.
  TlvEncoder encoder(8);
  encoder.writeNonNegativeInteger((uint64_t)timestamp);
  interest.getName().append(Blob(encoder.finish()));

  // 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.
  uint8_t randomBuffer[8];
  ndn_Error error;
  if ((error = CryptoLite::generateRandomBytes(randomBuffer, sizeof(randomBuffer))))
    throw runtime_error(ndn_getErrorString(error));
  interest.getName().append(randomBuffer, sizeof(randomBuffer));

  keyChain.sign(interest, certificateName, wireFormat);

  if (interest.getInterestLifetimeMilliseconds() < 0)
    // The caller has not set the interest lifetime, so set it here.
    interest.setInterestLifetimeMilliseconds(1000.0);

  // We successfully signed the interest, so update the timestamp.
  lastTimestamp_ = timestamp;
}
int main(int argc, char** argv)
{
  try {
    Name prefix("/nfd/edu/ucla/remap/test");
    // Route to aleph.ndn.ucla.edu.  Have to use the canonical name with
    // an IP address and port.
    string uri = "udp4://128.97.98.7:6363";

    // The default Face connects to the local NFD.
    Face face;

    // Use the system default key chain and certificate name to sign commands.
    KeyChain keyChain;
    face.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName());

    // Create the /localhost/nfd/faces/query command interest, including the
    // FaceQueryFilter. Construct the FaceQueryFilter using the structure in
    // face-query-filter.pb.h which was produced by protoc.
    ndn_message::FaceQueryFilterMessage message;
    ndn_message::FaceQueryFilterMessage_FaceQueryFilter* filter =
      message.add_face_query_filter();
    filter->set_uri(uri);
    Blob encodedFilter = ProtobufTlv::encode(message);

    Interest interest(Name("/localhost/nfd/faces/query"));
    interest.getName().append(encodedFilter);

    bool enabled = true;
    SegmentFetcher::fetch
      (face, interest, SegmentFetcher::DontVerifySegment,
       bind(&processFaceStatus, _1, prefix, uri, &face, &enabled),
       bind(&onError, _1, _2, &enabled));

    // Loop calling processEvents until a callback sets enabled = false.
    while (enabled) {
      face.processEvents();
      // We need to sleep for a few milliseconds so we don't use 100% of the CPU.
      usleep(10000);
    }
  } catch (std::exception& e) {
    cout << "exception: " << e.what() << endl;
  }
  return 0;
}
Exemple #8
0
int main(int argc, char** argv)
{

    std::string logfile = createLogDir("./logs");
    GLogger glog( argv[0], logfile.c_str() );
    std::cout << "Log to path: " << logfile << std::endl;

    try {
        boost::asio::io_service ioService;

        ptr_lib::shared_ptr<ThreadsafeFace> face;
        face.reset(new ThreadsafeFace (ioService, "localhost"));

        // Use the system default key chain and certificate name to sign commands.
        KeyChain keyChain;
        face->setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName());

        // Also use the default certificate name to sign data packets.
        Publisher publisher(ioService, face, keyChain, keyChain.getDefaultCertificateName());

        if( !publisher.init() )
        {
            cout << "Publisher init fail" << endl;
            return 0;
        }
        else
        {
            std::thread *captureThread =
                    new std::thread(bind(&Publisher::start,&publisher));

            captureThread->detach();

            LOG(INFO) << "ioservice start" << endl;
            boost::asio::io_service::work work(ioService);
            ioService.run();
            LOG(INFO) << "ioservice started" << endl;
        }
    }
    catch (std::exception& e) {
        cout << "exception: " << e.what() << endl;
    }
    return 0;
}
Exemple #9
0
void
CommandInterestGenerator::generate
  (Interest& interest, KeyChain& keyChain, const Name& certificateName,
   WireFormat& wireFormat)
{
  prepareCommandInterestName(interest, wireFormat);
  keyChain.sign(interest, certificateName, wireFormat);

  if (interest.getInterestLifetimeMilliseconds() < 0)
    // The caller has not set the interest lifetime, so set it here.
    interest.setInterestLifetimeMilliseconds(1000.0);
}
Exemple #10
0
TEST_F(TestInterestMethods, VerifyDigestSha256)
{
  // Create a KeyChain but we don't need to add keys.
  ptr_lib::shared_ptr<MemoryIdentityStorage> identityStorage
    (new MemoryIdentityStorage());
  KeyChain keyChain
    (ptr_lib::make_shared<IdentityManager>
      (identityStorage, ptr_lib::make_shared<MemoryPrivateKeyStorage>()),
     ptr_lib::make_shared<SelfVerifyPolicyManager>(identityStorage.get()));

  ptr_lib::shared_ptr<Interest> interest(new Interest(Name("/test/signed-interest")));
  keyChain.signWithSha256(*interest);

  VerifyCounter counter;
  keyChain.verifyInterest
    (interest, bind(&VerifyCounter::onVerified, &counter, _1),
     // Cast to disambiguate from the deprecated OnVerifyInterestFailed.
     (const OnInterestValidationFailed)bind
       (&VerifyCounter::onInterestValidationFailed, &counter, _1, _2));
  ASSERT_EQ(counter.onValidationFailedCallCount_, 0) << "Signature verification failed";
  ASSERT_EQ(counter.onVerifiedCallCount_, 1) << "Verification callback was not used.";
}
int main(int argc, char** argv)
{
  try {
    Face face("localhost");
        
    shared_ptr<MemoryIdentityStorage> identityStorage(new MemoryIdentityStorage());
    shared_ptr<MemoryPrivateKeyStorage> privateKeyStorage(new MemoryPrivateKeyStorage());
    KeyChain keyChain
      (make_shared<IdentityManager>(identityStorage, privateKeyStorage), make_shared<NoVerifyPolicyManager>());
    keyChain.setFace(&face);
    
    // Initialize the storage.
    Name keyName("/testname/DSK-123");
    Name certificateName = keyName.getSubName(0, keyName.size() - 1).append("KEY").append
           (keyName.get(keyName.size() - 1)).append("ID-CERT").append("0");
    identityStorage->addKey(keyName, KEY_TYPE_RSA, Blob(DEFAULT_PUBLIC_KEY_DER, sizeof(DEFAULT_PUBLIC_KEY_DER)));
    privateKeyStorage->setKeyPairForKeyName
      (keyName, DEFAULT_PUBLIC_KEY_DER, sizeof(DEFAULT_PUBLIC_KEY_DER), DEFAULT_PRIVATE_KEY_DER, sizeof(DEFAULT_PRIVATE_KEY_DER));
   
    Echo echo(keyChain, certificateName);
    Name prefix("/testecho");
    cout << "Register prefix  " << prefix.toUri() << endl;
    face.registerPrefix(prefix, ref(echo), ref(echo));
    
    // The main event loop.  
    // Wait forever to receive one interest for the prefix.
    while (echo.responseCount_ < 1) {
      face.processEvents();
      // We need to sleep for a few milliseconds so we don't use 100% of the CPU.
      usleep(10000);
    }
  } catch (std::exception& e) {
    cout << "exception: " << e.what() << endl;
  }
  return 0;
}
/**
 * Loop to decode a data packet nIterations times using C++.
 * @param nIterations The number of iterations.
 * @param useCrypto If true, verify the signature.  If false, don't verify.
 * @param encoding The wire encoding to decode.
 * @return The number of seconds for all iterations.
 */
static double
benchmarkDecodeDataSecondsCpp(int nIterations, bool useCrypto, const Blob& encoding)
{
  // Initialize the KeyChain storage in case useCrypto is true.
  ptr_lib::shared_ptr<MemoryIdentityStorage> identityStorage(new MemoryIdentityStorage());
  ptr_lib::shared_ptr<MemoryPrivateKeyStorage> privateKeyStorage(new MemoryPrivateKeyStorage());
  KeyChain keyChain
    (ptr_lib::make_shared<IdentityManager>(identityStorage, privateKeyStorage),
     ptr_lib::make_shared<SelfVerifyPolicyManager>(identityStorage.get()));
  Name keyName("/testname/DSK-123");
  identityStorage->addKey(keyName, KEY_TYPE_RSA, Blob(DEFAULT_RSA_PUBLIC_KEY_DER, sizeof(DEFAULT_RSA_PUBLIC_KEY_DER)));

  double start = getNowSeconds();
  for (int i = 0; i < nIterations; ++i) {
    ptr_lib::shared_ptr<Data> data(new Data());
    data->wireDecode(encoding);

    if (useCrypto)
      keyChain.verifyData(data, onVerified, onVerifyFailed);
  }
  double finish = getNowSeconds();

  return finish - start;
}
		void onHelloInterest(const InterestFilter& filter, const Interest& interest){
// 			std::cout <<"Received hello interest\n";
 			std::cout << "\n\n\n----------this is test No. "  <<++count << "------\n"<< std::endl;

			
			Name fileName(interest.getName());
			int *content = new int[3];
			content[0] = m_FileSize;
			content[1] = m_SegmentSize;
			content[2] = m_ContentSize;
			
			
			fileBuffer = new char[m_FileSize];
			
			
			shared_ptr<Data> data = make_shared<Data>();
			data->setName(fileName);
			data->setFreshnessPeriod(time::seconds(10));
			data->setContent(reinterpret_cast<const uint8_t*>(content), 3 * sizeof(int));
			m_keyChain.sign(*data);
// 			m_keyChain.signWithSha256(*data);
			m_face.put(*data);
	
		}
BOOST_FIXTURE_TEST_CASE(ConstructorEmptyConfig, TestHomeAndPibFixture<PibPathSqlite3Empty>)
{
  createClientConf({"pib=pib-sqlite3:%PATH%"});

#if defined(NDN_CXX_HAVE_OSX_SECURITY)
  std::string oldHOME;
  if (std::getenv("OLD_HOME"))
    oldHOME = std::getenv("OLD_HOME");

  std::string HOME;
  if (std::getenv("HOME"))
    HOME = std::getenv("HOME");

  if (!oldHOME.empty())
    setenv("HOME", oldHOME.c_str(), true);
  else
    unsetenv("HOME");
#endif

  BOOST_REQUIRE_NO_THROW(KeyChain());
  KeyChain keyChain;
  BOOST_CHECK_EQUAL(keyChain.getPib().getPibLocator(), "pib-sqlite3:" + m_pibDir);

#if defined(NDN_CXX_HAVE_OSX_SECURITY)
  BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-osxkeychain:");
  BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-osxkeychain:");
#else
  BOOST_CHECK_EQUAL(keyChain.getPib().getTpmLocator(), "tpm-file:");
  BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-file:");
#endif

#if defined(NDN_CXX_HAVE_OSX_SECURITY)
  if (!HOME.empty())
    setenv("HOME", HOME.c_str(), true);
  else
    unsetenv("HOME");
#endif
}
int
ndnsec_delete(int argc, char** argv)
{
  using namespace ndn;
  namespace po = boost::program_options;

  // bool deleteId = true;
  bool isDeleteKey = false;
  bool isDeleteCert = false;
  std::string name;

  po::options_description description("General Usage\n  ndnsec delete [-h] [-k|c] name\nGeneral options");
  description.add_options()
    ("help,h", "produce help message")
    ("delete-key,k", "(Optional) delete a key if specified.")
    ("delete-key2,K", "(Optional) delete a key if specified.")
    ("delete-cert,c", "(Optional) delete a certificate if specified.")
    ("delete-cert2,C", "(Optional) delete a certificate if specified.")
    ("name,n", po::value<std::string>(&name), "By default, it refers to an identity."
     "If -k is specified, it refers to a key."
     "If -c is specified, it refers to a certificate.");
    ;

  po::positional_options_description p;
  p.add("name", 1);

  po::variables_map vm;
  try
    {
      po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
                vm);
      po::notify(vm);
    }
  catch (const std::exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      std::cerr << description << std::endl;
      return 1;
    }

  if (vm.count("help") != 0)
    {
      std::cerr << description << std::endl;;
      return 0;
    }

  if (vm.count("name") == 0)
    {
      std::cerr << "ERROR: name must be specified" << std::endl;
      std::cerr << description << std::endl;
      return 1;
    }

  if (vm.count("delete-cert") != 0 || vm.count("delete-cert2") != 0)
    {
      isDeleteCert = true;
      // deleteId = false;
    }
  else if (vm.count("delete-key") != 0 || vm.count("delete-key2") != 0)
    {
      isDeleteKey = true;
      // deleteId = false;
    }

  KeyChain keyChain;

  if (isDeleteCert)
    {
      keyChain.deleteCertificate(name);
    }
  else if (isDeleteKey)
    {
      keyChain.deleteKey(name);
    }
  else
    {
      keyChain.deleteIdentity(name);
    }

  return 0;
}
int
ndnsec_cert_gen(int argc, char** argv)
{
  using boost::tokenizer;
  using boost::escaped_list_separator;

  using namespace ndn;
  using namespace ndn::time;
  namespace po = boost::program_options;

  std::string notBeforeStr;
  std::string notAfterStr;
  std::string subjectName;
  std::string requestFile("-");
  std::string signId;
  std::string subjectInfo;
  std::string certPrefix;
  bool hasSignId = false;

  po::options_description description(
    "General Usage\n"
    "  ndnsec cert-gen [-h] [-S date] [-E date] [-N subject-name] [-I subject-info] "
        "[-s sign-id] [-p cert-prefix] request\n"
    "General options");

  description.add_options()
    ("help,h", "produce help message")
    ("not-before,S",     po::value<std::string>(&notBeforeStr),
                         "certificate starting date, YYYYMMDDhhmmss")
    ("not-after,E",      po::value<std::string>(&notAfterStr),
                         "certificate ending date, YYYYMMDDhhmmss")
    ("subject-name,N",   po::value<std::string>(&subjectName),
                         "subject name")
    ("subject-info,I",   po::value<std::string>(&subjectInfo),
                         "subject info, pairs of OID and string description: "
                         "\"2.5.4.10 'University of California, Los Angeles'\"")
    ("sign-id,s",        po::value<std::string>(&signId),
                         "signing Identity, system default identity if not specified")
    ("cert-prefix,p", po::value<std::string>(&certPrefix),
                         "cert prefix, which is the part of certificate name before "
                         "KEY component")
    ("request,r",        po::value<std::string>(&requestFile),
                         "request file name, - for stdin")
    ;

  po::positional_options_description p;
  p.add("request", 1);

  po::variables_map vm;
  try
    {
      po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
                vm);
      po::notify(vm);
    }
  catch (const std::exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      return 1;
    }

  if (vm.count("help") != 0)
    {
      std::cerr << description << std::endl;
      return 0;
    }

  if (vm.count("sign-id") != 0)
    {
      hasSignId = true;
    }

  if (vm.count("subject-name") == 0)
    {
      std::cerr << "subject_name must be specified" << std::endl;
      return 1;
    }

  std::vector<CertificateSubjectDescription> subjectDescription;
  subjectDescription.push_back(CertificateSubjectDescription(oid::ATTRIBUTE_NAME, subjectName));

  tokenizer<escaped_list_separator<char> > subjectInfoItems
    (subjectInfo, escaped_list_separator<char>("\\", " \t", "'\""));

  tokenizer<escaped_list_separator<char> >::iterator it =
    subjectInfoItems.begin();

  while (it != subjectInfoItems.end())
    {
      std::string oid = *it;

      it++;
      if (it == subjectInfoItems.end())
        {
          std::cerr << "ERROR: unmatched info for oid [" << oid << "]" << std::endl;
          return 1;
        }

      std::string value = *it;

      subjectDescription.push_back(CertificateSubjectDescription(OID(oid), value));

      it++;
    }

  system_clock::TimePoint notBefore;
  system_clock::TimePoint notAfter;

  if (vm.count("not-before") == 0)
    {
      notBefore = system_clock::now();
    }
  else
    {
      notBefore = fromIsoString(notBeforeStr.substr(0, 8) + "T" +
                                notBeforeStr.substr(8, 6));
    }

  if (vm.count("not-after") == 0)
    {
      notAfter = notBefore + days(365);
    }
  else
    {
      notAfter = fromIsoString(notAfterStr.substr(0, 8) + "T" +
                               notAfterStr.substr(8, 6));

      if (notAfter < notBefore)
        {
          std::cerr << "not-before is later than not-after" << std::endl;
          return 1;
        }
    }

  if (vm.count("request") == 0)
    {
      std::cerr << "request file must be specified" << std::endl;
      return 1;
    }

  shared_ptr<IdentityCertificate> selfSignedCertificate
    = getIdentityCertificate(requestFile);

  if (!static_cast<bool>(selfSignedCertificate))
    {
      std::cerr << "ERROR: input error" << std::endl;
      return 1;
    }

  KeyChain keyChain;

  Name keyName = selfSignedCertificate->getPublicKeyName();
  Name signIdName;
  Name prefix(certPrefix);

  if (!hasSignId)
    signIdName = keyChain.getDefaultIdentity();
  else
    signIdName = Name(signId);

  shared_ptr<IdentityCertificate> certificate =
    keyChain.prepareUnsignedIdentityCertificate(keyName, selfSignedCertificate->getPublicKeyInfo(),
                                                signIdName, notBefore, notAfter,
                                                subjectDescription, prefix);

  if (!static_cast<bool>(certificate))
    {
      std::cerr << "ERROR: key name is not formated correctly or does not match certificate name."
                << std::endl;
      return 1;
    }

  keyChain.createIdentity(signIdName);
  Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(signIdName);
  keyChain.sign(*certificate, signingCertificateName);

  Block wire = certificate->wireEncode();

  try
    {
      using namespace CryptoPP;
      StringSource ss(wire.wire(), wire.size(), true,
                      new Base64Encoder(new FileSink(std::cout), true, 64));
    }
  catch (const CryptoPP::Exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      return 1;
    }

  return 0;
}
Exemple #17
0
int
ndnsec_key_gen(int argc, char** argv)
{
  using namespace ndn;
  namespace po = boost::program_options;

  std::string identityName;
  bool isDefault = true;
  char keyType = 'r';
  std::string outputFilename;

  po::options_description description("General Usage\n"
                                      "  ndnsec key-gen [-h] [-n] identity\n"
                                      "General options");
  description.add_options()
    ("help,h", "produce help message")
    ("identity,i", po::value<std::string>(&identityName),
     "identity name, for example, /ndn/edu/ucla/alice")
    ("not_default,n",
     "optional, if not specified, the target identity will be set as "
     "the default identity of the system")
    ("dsk,d", "generate Data-Signing-Key (DSK) instead of the default Key-Signing-Key (KSK)")
    ("type,t", po::value<char>(&keyType)->default_value('r'),
    "optional, key type, r for RSA key (default), e for ECDSA key")
    // ("size,s", po::value<int>(&keySize)->default_value(2048),
    // "optional, key size, 2048 (default)")
    ;

  po::positional_options_description p;
  p.add("identity", 1);

  po::variables_map vm;
  try {
    po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
              vm);
    po::notify(vm);
  }
  catch (const std::exception& e) {
    std::cerr << "ERROR: " << e.what() << std::endl;
    std::cerr << description << std::endl;
    return 1;
  }

  if (vm.count("help") != 0) {
    std::cerr << description << std::endl;
    return 0;
  }

  if (vm.count("identity") == 0) {
    std::cerr << "identity must be specified" << std::endl;
    std::cerr << description << std::endl;
    return 1;
  }

  if (vm.count("not_default") != 0)
    isDefault = false;

  bool isKsk = (vm.count("dsk") == 0);

  KeyChain keyChain;
  Name keyName;

  try {
    switch (keyType) {
    case 'r':
      keyName = keyChain.generateRsaKeyPair(Name(identityName), isKsk, RsaKeyParams().getKeySize());
      break;
    case 'e':
      keyName = keyChain.generateEcdsaKeyPair(Name(identityName), isKsk,
                                              EcdsaKeyParams().getKeySize());
      break;
    default:
      std::cerr << "Unrecongized key type" << "\n";
      std::cerr << description << std::endl;
      return 1;
    }

    if (0 == keyName.size()) {
      std::cerr << "Error: failed to generate key" << "\n";
      return 1;
    }

    keyChain.setDefaultKeyNameForIdentity(keyName);

    shared_ptr<security::v1::IdentityCertificate> identityCert = keyChain.selfSign(keyName);

    if (isDefault)
      keyChain.setDefaultIdentity(Name(identityName));

    io::save(*identityCert, std::cout);
  }
  catch (const std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
  }
  return 0;
}
int
ndnsec_get_default(int argc, char** argv)
{
  using namespace ndn;
  namespace po = boost::program_options;

  bool isGetDefaultId = true;
  bool isGetDefaultKey = false;
  bool isGetDefaultCert = false;
  bool isQuiet = false;
  std::string identityString;
  std::string keyName;

  po::options_description description("General Usage\n  ndnsec get-default [-h] [-k|c] [-i identity|-K key] [-q]\nGeneral options");
  description.add_options()
    ("help,h", "produce help message")
    ("default_key,k", "get default key")
    ("default_cert,c", "get default certificate")
    ("identity,i", po::value<std::string>(&identityString), "target identity")
    ("key,K", po::value<std::string>(&keyName), "target key")
    ("quiet,q", "don't output trailing newline")
    ;

  po::variables_map vm;
  try
    {
      po::store(po::parse_command_line(argc, argv, description), vm);
      po::notify(vm);
    }
  catch (const std::exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      std::cerr << description << std::endl;
      return 1;
    }

  if (vm.count("help") != 0)
    {
      std::cerr << description << std::endl;;
      return 0;
    }

  if (vm.count("default_cert") != 0)
    {
      isGetDefaultCert = true;
      isGetDefaultId = false;
    }
  else if (vm.count("default_key") != 0)
    {
      isGetDefaultKey = true;
      isGetDefaultId = false;
    }

  if (vm.count("quiet") != 0)
    {
      isQuiet = true;
    }

  KeyChain keyChain;

  if (vm.count("key") != 0)
    {
      Name keyNdnName(keyName);
      if (isGetDefaultCert)
        {
          std::cout << keyChain.getDefaultCertificateNameForKey(keyNdnName);
          if (!isQuiet) std::cout << std::endl;
          return 0;
        }
      return 1;
    }
  else if (vm.count("identity") != 0)
    {
      Name identity(identityString);

      if (isGetDefaultKey)
        {
          std::cout << keyChain.getDefaultKeyNameForIdentity(identity);
          if (!isQuiet)
            std::cout << std::endl;

          return 0;
        }
      if (isGetDefaultCert)
        {
          std::cout << keyChain.getDefaultCertificateNameForIdentity(identity);
          if (!isQuiet)
            std::cout << std::endl;

          return 0;
        }
      return 1;
    }
  else
    {
      Name identity = keyChain.getDefaultIdentity();
      if (isGetDefaultId)
        {
          std::cout << identity;
          if (!isQuiet) std::cout << std::endl;
          return 0;
        }
      if (isGetDefaultKey)
        {
          std::cout << keyChain.getDefaultKeyNameForIdentity(identity);
          if (!isQuiet) std::cout << std::endl;
          return 0;
        }
      if (isGetDefaultCert)
        {
          std::cout << keyChain.getDefaultCertificateNameForIdentity(identity);
          if (!isQuiet) std::cout << std::endl;
          return 0;
        }
      return 1;
    }
}
int main(int argc, char** argv)
{
  try {
    Interest interest;
    interest.wireDecode(TlvInterest, sizeof(TlvInterest));
    cout << "Interest:" << endl;
    dumpInterest(interest);

    // Set the name again to clear the cached encoding so we encode again.
    interest.setName(interest.getName());
    Blob encoding = interest.wireEncode();
    cout << endl << "Re-encoded interest " << encoding.toHex() << endl;

    Interest reDecodedInterest;
    reDecodedInterest.wireDecode(encoding);
    cout << "Re-decoded Interest:" << endl;
    dumpInterest(reDecodedInterest);

    Interest freshInterest(Name("/ndn/abc"));
    freshInterest.setMinSuffixComponents(4)
      .setMaxSuffixComponents(6)
      .setInterestLifetimeMilliseconds(30000)
      .setChildSelector(1)
      .setMustBeFresh(true);
    freshInterest.getKeyLocator().setType(ndn_KeyLocatorType_KEY_LOCATOR_DIGEST);
    uint8_t digest[] = {
      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
    freshInterest.getKeyLocator().setKeyData(Blob(digest, sizeof(digest)));
    freshInterest.getExclude().appendComponent(Name("abc")[0]).appendAny();

    ptr_lib::shared_ptr<MemoryIdentityStorage> identityStorage
      (new MemoryIdentityStorage());
    ptr_lib::shared_ptr<MemoryPrivateKeyStorage> privateKeyStorage
      (new MemoryPrivateKeyStorage());
    KeyChain keyChain
      (ptr_lib::make_shared<IdentityManager>(identityStorage, privateKeyStorage),
       ptr_lib::make_shared<SelfVerifyPolicyManager>(identityStorage.get()));

    // Initialize the storage.
    Name keyName("/testname/DSK-123");
    Name certificateName = keyName.getSubName(0, keyName.size() - 1).append
      ("KEY").append(keyName[-1]).append("ID-CERT").append("0");
    identityStorage->addKey
      (keyName, KEY_TYPE_RSA, Blob(DEFAULT_RSA_PUBLIC_KEY_DER,
       sizeof(DEFAULT_RSA_PUBLIC_KEY_DER)));
    privateKeyStorage->setKeyPairForKeyName
      (keyName, KEY_TYPE_RSA, DEFAULT_RSA_PUBLIC_KEY_DER,
       sizeof(DEFAULT_RSA_PUBLIC_KEY_DER), DEFAULT_RSA_PRIVATE_KEY_DER,
       sizeof(DEFAULT_RSA_PRIVATE_KEY_DER));

    // Make a Face just so that we can sign the interest.
    Face face("localhost");
    face.setCommandSigningInfo(keyChain, certificateName);
    face.makeCommandInterest(freshInterest);

    ptr_lib::shared_ptr<Interest> reDecodedFreshInterest(new Interest());
    reDecodedFreshInterest->wireDecode(freshInterest.wireEncode());
    cout << endl << "Re-decoded fresh Interest:" << endl;
    dumpInterest(*reDecodedFreshInterest);

    keyChain.verifyInterest
      (reDecodedFreshInterest, bind(&onVerified, "Freshly-signed Interest", _1),
       bind(&onVerifyFailed, "Freshly-signed Interest", _1));
  } catch (std::exception& e) {
    cout << "exception: " << e.what() << endl;
  }
  return 0;
}
BOOST_FIXTURE_TEST_CASE(CommandInterest, CommandInterestFixture)
{
  KeyChain keyChain;
  Name identity("/TestCommandInterest/Validation");
  identity.appendVersion();

  Name certName;
  BOOST_REQUIRE_NO_THROW(certName = keyChain.createIdentity(identity));

  CommandInterestGenerator generator;
  CommandInterestValidator validator;

  validator.addInterestRule("^<TestCommandInterest><Validation>",
                            *keyChain.getCertificate(certName));

  //Test a legitimate command
  shared_ptr<Interest> commandInterest1 =
    make_shared<Interest>("/TestCommandInterest/Validation/Command1");
  generator.generateWithIdentity(*commandInterest1, identity);
  validator.validate(*commandInterest1,
                     bind(&CommandInterestFixture::validated, this, _1),
                     bind(&CommandInterestFixture::validationFailed, this, _1, _2));

  BOOST_CHECK_EQUAL(m_validity, true);

  //Test an outdated command
  reset();
  shared_ptr<Interest> commandInterest2 =
    make_shared<Interest>("/TestCommandInterest/Validation/Command2");
  time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now());
  timestamp -= time::seconds(5);

  Name commandName = commandInterest2->getName();
  commandName
    .appendNumber(timestamp.count())
    .appendNumber(random::generateWord64());
  commandInterest2->setName(commandName);

  keyChain.signByIdentity(*commandInterest2, identity);
  validator.validate(*commandInterest2,
                     bind(&CommandInterestFixture::validated, this, _1),
                     bind(&CommandInterestFixture::validationFailed, this, _1, _2));

  BOOST_CHECK_EQUAL(m_validity, false);

  //Test an unauthorized command
  Name identity2("/TestCommandInterest/Validation2");
  Name certName2;
  BOOST_REQUIRE_NO_THROW(certName2 = keyChain.createIdentity(identity2));

  shared_ptr<Interest> commandInterest3 =
    make_shared<Interest>("/TestCommandInterest/Validation/Command3");
  generator.generateWithIdentity(*commandInterest3, identity2);
  validator.validate(*commandInterest3,
                     bind(&CommandInterestFixture::validated, this, _1),
                     bind(&CommandInterestFixture::validationFailed, this, _1, _2));

  BOOST_CHECK_EQUAL(m_validity, false);

  //Test another unauthorized command
  shared_ptr<Interest> commandInterest4 =
    make_shared<Interest>("/TestCommandInterest/Validation2/Command");
  generator.generateWithIdentity(*commandInterest4, identity);
  validator.validate(*commandInterest4,
                     bind(&CommandInterestFixture::validated, this, _1),
                     bind(&CommandInterestFixture::validationFailed, this, _1, _2));

  BOOST_CHECK_EQUAL(m_validity, false);

  BOOST_CHECK_NO_THROW(keyChain.deleteIdentity(identity));
  BOOST_CHECK_NO_THROW(keyChain.deleteIdentity(identity2));
}
Exemple #21
0
int
ndnsec_op_tool(int argc, char** argv)
{
  using namespace ndn;
  namespace po = boost::program_options;

  std::string command;

  po::options_description description("General options");
  description.add_options()
    ("help,h", "produce this help message")
    ("command", po::value<std::string>(&command), "command")
    ;

  po::positional_options_description p;
  p.add("command", 1);

  po::variables_map vm;
  try
    {
      po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
                vm);
      po::notify(vm);
    }
  catch (const std::exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      std::cerr << description << std::endl;
      return -1;
    }

  if (vm.count("help") != 0)
    {
      std::cerr << description << std::endl;
      return 0;
    }

  if (vm.count("command") == 0)
    {
      std::cerr << "command must be specified" << std::endl;
      std::cerr << description << std::endl;
      return 1;
    }

  if (command == "sign") // the content to be signed from stdin
    {
      KeyChain keyChain;

      Buffer dataToSign((istreambuf_iterator<char>(cin)), istreambuf_iterator<char>());

      Block value = keyChain.sign(dataToSign.buf(), dataToSign.size(),
                                  security::SigningInfo(security::SigningInfo::SIGNER_TYPE_CERT,
                                                        keyChain.getDefaultCertificateName()));

      if (value.value_size() == 0)
        {
          std::cerr << "Error signing with default key" << std::endl;
          return -1;
        }

      std::cout.write(reinterpret_cast<const char*>(value.wire()), value.size());
    }

  return 0;
}
int
ndnsec_cert_dump(int argc, char** argv)
{
  using namespace ndn;
  namespace po = boost::program_options;

  std::string name;
  bool isKeyName = false;
  bool isIdentityName = false;
  bool isCertName = true;
  // bool isFileName = false;
  bool isPretty = false;
  bool isStdOut = true;
  bool isRepoOut = false;
  std::string repoHost;
  std::string repoPort;
  // bool isDnsOut = false;

  po::options_description description("General Usage\n"
                                      "  ndnsec cert-dump [-h] [-p] [-d] [-r [-H repo-host] "
                                         "[-P repo-port] ] [-i|k|f] name\n"
                                      "General options");
  description.add_options()
    ("help,h",     "produce help message")
    ("pretty,p",   "display certificate in human readable format")
    ("identity,i", "treat the name parameter as identity name (e.g., /ndn/edu/ucla/alice")
    ("key,k",      "treat the name parameter as key name "
                   "(e.g., /ndn/edu/ucla/alice/ksk-123456789)")
    ("file,f",     "treat the name parameter as file name with base64 encoded certificate, "
                   "- for stdin")
    ("repo-output,r", "publish the certificate to the repo-ng")
    ("repo-host,H", po::value<std::string>(&repoHost)->default_value("localhost"),
                   "the repo host if repo-output is specified")
    ("repo-port,P", po::value<std::string>(&repoPort)->default_value("7376"),
                   "the repo port if repo-output is specified")
    // ("dns-output,d", "published the certificate to NDNS")
    ("name,n", po::value<std::string>(&name),
                   "unless overridden with --identity or --key parameter, the certificate name, "
                   "for example, /ndn/edu/ucla/KEY/cs/alice/ksk-1234567890"
                                "/ID-CERT/%FD%FF%FF%FF%FF%FF%FF%FF")
    ;

  po::positional_options_description p;
  p.add("name", 1);

  po::variables_map vm;
  try
    {
      po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
                vm);
      po::notify(vm);
    }
  catch (const std::exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      std::cerr << description << std::endl;
      return 1;
    }

  if (vm.count("help") != 0)
    {
      std::cerr << description << std::endl;
      return 0;
    }

  if (vm.count("name") == 0)
    {
      std::cerr << "identity_name must be specified" << std::endl;
      std::cerr << description << std::endl;
      return 1;
    }

  if (vm.count("key") != 0)
    {
      isCertName = false;
      isKeyName = true;
    }
  else if (vm.count("identity") != 0)
    {
      isCertName = false;
      isIdentityName = true;
    }
  else if (vm.count("file") != 0)
    {
      isCertName = false;
      // isFileName = true;
    }

  if (vm.count("pretty") != 0)
    isPretty = true;

  if (vm.count("repo-output") != 0)
    {
      isRepoOut = true;
      isStdOut = false;
    }
  else if (vm.count("dns-output") != 0)
    {
      // isDnsOut = true;
      isStdOut = false;
      std::cerr << "Error: DNS output is not supported yet!" << std::endl;
      return 1;
    }

  if (isPretty && !isStdOut)
    {
      std::cerr << "Error: pretty option can only be specified when other "
                << "output option is specified" << std::endl;
      return 1;
    }

  shared_ptr<IdentityCertificate> certificate;

  KeyChain keyChain;

  if (isIdentityName || isKeyName || isCertName)
    {
      if (isIdentityName)
        {
          Name certName = keyChain.getDefaultCertificateNameForIdentity(name);
          certificate = keyChain.getCertificate(certName);
        }
      else if (isKeyName)
        {
          Name certName = keyChain.getDefaultCertificateNameForKey(name);
          certificate = keyChain.getCertificate(certName);
        }
      else
        certificate = keyChain.getCertificate(name);

      if (!static_cast<bool>(certificate))
        {
          std::cerr << "No certificate found!" << std::endl;
          return 1;
        }
    }
  else
    {
      certificate = getIdentityCertificate(name);
      if (!static_cast<bool>(certificate))
        {
          std::cerr << "No certificate read!" << std::endl;
          return 1;
        }
    }

  if (isPretty)
    {
      std::cout << *certificate << std::endl;
    }
  else
    {
      if (isStdOut)
        {
          io::save(*certificate, std::cout);
          return 0;
        }
      if (isRepoOut)
        {
          using namespace boost::asio::ip;
          tcp::iostream request_stream;
          request_stream.expires_from_now(boost::posix_time::milliseconds(3000));
          request_stream.connect(repoHost, repoPort);
          if (!request_stream)
            {
              std::cerr << "fail to open the stream!" << std::endl;
              return 1;
            }
          request_stream.write(reinterpret_cast<const char*>(certificate->wireEncode().wire()),
                               certificate->wireEncode().size());

          return 0;
        }
    }
  return 0;
}
int
ndnsec_sign_req(int argc, char** argv)
{
  using namespace ndn;
  namespace po = boost::program_options;

  std::string name;
  bool isKeyName = false;

  po::options_description description("General Usage\n  ndnsec sign-req [-h] [-k] name\nGeneral options");
  description.add_options()
    ("help,h", "produce help message")
    ("key,k", "optional, if specified, name is keyName (e.g. /ndn/edu/ucla/alice/ksk-123456789), otherwise identity name")
    ("name,n", po::value<std::string>(&name), "name, for example, /ndn/edu/ucla/alice")
    ;

  po::positional_options_description p;
  p.add("name", 1);

  po::variables_map vm;
  try
    {
      po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
                vm);
      po::notify(vm);
    }
  catch (const std::exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      std::cerr << description << std::endl;
      return 1;
    }

  if (vm.count("help") != 0)
    {
      std::cerr << description << std::endl;
      return 0;
    }

  if (vm.count("name") == 0)
    {
      std::cerr << "ERROR: name must be specified" << std::endl;
      std::cerr << description << std::endl;
      return 1;
    }

  if (vm.count("key") != 0)
    isKeyName = true;

  shared_ptr<IdentityCertificate> selfSignCert;

  KeyChain keyChain;

  if (isKeyName)
    selfSignCert = keyChain.selfSign(name);
  else {
    Name keyName = keyChain.getDefaultKeyNameForIdentity(name);
    selfSignCert = keyChain.selfSign(keyName);
  }

  if (static_cast<bool>(selfSignCert)) {
    io::save(*selfSignCert, std::cout);
    return 0;
  }
  else {
    std::cerr << "ERROR: Public key does not exist" << std::endl;
    return 1;
  }
}
int
ndnsec_cert_gen(int argc, char** argv)
{
  using boost::tokenizer;
  using boost::escaped_list_separator;

  using namespace ndn;
  using namespace ndn::time;
  namespace po = boost::program_options;

  std::string notBeforeStr;
  std::string notAfterStr;
  std::string subjectName;
  std::string requestFile("-");
  std::string signId;
  std::string subjectInfo;
  bool hasSignId = false;
  bool isNack = false;

  po::options_description description("General Usage\n  ndnsec cert-gen [-h] [-S date] [-E date] [-N subject-name] [-I subject-info] [-s sign-id] request\nGeneral options");
  description.add_options()
    ("help,h", "produce help message")
    ("not-before,S", po::value<std::string>(&notBeforeStr), "certificate starting date, YYYYMMDDhhmmss")
    ("not-after,E", po::value<std::string>(&notAfterStr), "certificate ending date, YYYYMMDDhhmmss")
    ("subject-name,N", po::value<std::string>(&subjectName), "subject name")
    ("subject-info,I", po::value<std::string>(&subjectInfo), "subject info, pairs of OID and string description: \"2.5.4.10 'University of California, Los Angeles'\"")
    ("nack", "Generate revocation certificate (NACK)")
    ("sign-id,s", po::value<std::string>(&signId), "signing Identity, system default identity if not specified")
    ("request,r", po::value<std::string>(&requestFile), "request file name, - for stdin")
    ;

  po::positional_options_description p;
  p.add("request", 1);

  po::variables_map vm;
  try
    {
      po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
                vm);
      po::notify(vm);
    }
  catch (const std::exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      return 1;
    }

  if (vm.count("help") != 0)
    {
      std::cerr << description << std::endl;
      return 0;
    }

  if (vm.count("sign-id") != 0)
    {
      hasSignId = true;
    }

  if (vm.count("nack") != 0)
    {
      isNack = true;
    }

  std::vector<CertificateSubjectDescription> otherSubDescrypt;
  tokenizer<escaped_list_separator<char> > subjectInfoItems
    (subjectInfo, escaped_list_separator<char> ("\\", " \t", "'\""));

  tokenizer<escaped_list_separator<char> >::iterator it =
    subjectInfoItems.begin();

  while (it != subjectInfoItems.end())
    {
      std::string oid = *it;

      it++;
      if (it == subjectInfoItems.end())
        {
          std::cerr << "ERROR: unmatched info for oid [" << oid << "]" << std::endl;
          return 1;
        }

      std::string value = *it;

      otherSubDescrypt.push_back(CertificateSubjectDescription(oid, value));

      it++;
    }

  system_clock::TimePoint notBefore;
  system_clock::TimePoint notAfter;

  if (vm.count("not-before") == 0)
    {
      notBefore = system_clock::now();
    }
  else
    {
      notBefore = fromIsoString(notBeforeStr.substr(0, 8) + "T" +
                                notBeforeStr.substr(8, 6));
    }

  if (vm.count("not-after") == 0)
    {
      notAfter = notBefore + days(365);
    }
  else
    {
      notAfter = fromIsoString(notAfterStr.substr(0, 8) + "T" +
                               notAfterStr.substr(8, 6));

      if (notAfter < notBefore)
        {
          std::cerr << "not-before is later than not-after" << std::endl;
          return 1;
        }
    }

  if (vm.count("request") == 0)
    {
      std::cerr << "request file must be specified" << std::endl;
      return 1;
    }

  shared_ptr<IdentityCertificate> selfSignedCertificate
    = getIdentityCertificate(requestFile);

  if (!static_cast<bool>(selfSignedCertificate))
    {
      std::cerr << "ERROR: input error" << std::endl;
      return 1;
    }

  KeyChain keyChain;

  Name keyName = selfSignedCertificate->getPublicKeyName();
  Name signIdName;
  Name certName;

  if (!hasSignId)
    signIdName = keyChain.getDefaultIdentity();
  else
    signIdName = Name(signId);


  if (signIdName.isPrefixOf(keyName))
    {
      // if signee's namespace is a sub-namespace of signer, for example, signer's namespace is
      // /ndn/test, signee's namespace is /ndn/test/alice, the generated certificate name is
      // /ndn/test/KEY/alice/ksk-1234/ID-CERT/%01%02
      certName.append(signIdName)
        .append("KEY")
        .append(keyName.getSubName(signIdName.size()))
        .append("ID-CERT")
        .appendVersion();
    }
  else
    {
      // if signee's namespace is not a sub-namespace of signer, for example, signer's namespace is
      // /ndn/test, signee's namespace is /ndn/ucla/bob, the generated certificate name is
      // /ndn/ucla/bob/KEY/ksk-1234/ID-CERT/%01%02
      certName.append(keyName.getPrefix(-1))
        .append("KEY")
        .append(keyName.get(-1))
        .append("ID-CERT")
        .appendVersion();
    }

  Block wire;

  if (!isNack)
    {
      if (vm.count("subject-name") == 0)
        {
          std::cerr << "subject_name must be specified" << std::endl;
          return 1;
        }

      CertificateSubjectDescription subDescryptName("2.5.4.41", subjectName);
      IdentityCertificate certificate;
      certificate.setName(certName);
      certificate.setNotBefore(notBefore);
      certificate.setNotAfter(notAfter);
      certificate.setPublicKeyInfo(selfSignedCertificate->getPublicKeyInfo());
      certificate.addSubjectDescription(subDescryptName);
      for (size_t i = 0; i < otherSubDescrypt.size(); i++)
        certificate.addSubjectDescription(otherSubDescrypt[i]);
      certificate.encode();

      keyChain.createIdentity(signIdName);
      Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(signIdName);
      keyChain.sign(certificate, signingCertificateName);

      wire = certificate.wireEncode();
    }
  else
    {
      Data revocationCert;
      // revocationCert.setContent(void*, 0); // empty content
      revocationCert.setName(certName);

      keyChain.createIdentity(signIdName);
      Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(signIdName);
      keyChain.sign(revocationCert, signingCertificateName);

      wire = revocationCert.wireEncode();
    }

  try
    {
      using namespace CryptoPP;
      StringSource ss(wire.wire(), wire.size(), true,
                      new Base64Encoder(new FileSink(std::cout), true, 64));
    }
  catch (const CryptoPP::Exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      return 1;
    }

  return 0;
}
inline void
CommandInterestGenerator::generateWithIdentity(Interest& interest, const Name& identity)
{
  m_keyChain.sign(interest,
                  security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID, identity));
}
/**
 * Loop to encode a data packet nIterations times using C++.
 * @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 encoding Set this to the wire encoding.
 * @return The number of seconds for all iterations.
 */
static double
benchmarkEncodeDataSecondsCpp(int nIterations, bool useComplex, bool useCrypto, Blob& encoding)
{
  Name name;
  Blob content;
  if (useComplex) {
    // Use a large name and content.
    name = Name("/ndn/ucla.edu/apps/lwndn-test/numbers.txt/%FD%05%05%E8%0C%CE%1D/%00");

    ostringstream contentStream;
    int count = 1;
    contentStream << (count++);
    while (contentStream.str().length() < 1115)
      contentStream << " " << (count++);
    content = Blob((uint8_t*)contentStream.str().c_str(), contentStream.str().length());
  }
  else {
    // Use a small name and content.
    name = Name("/test");
    content = Blob((uint8_t*)"abc", 3);
  }
  Blob finalBlockId((uint8_t*)"\x00", 1);

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

  uint8_t signatureBitsArray[256];
  memset(signatureBitsArray, 0, sizeof(signatureBitsArray));
  Blob signatureBits(signatureBitsArray, sizeof(signatureBitsArray));

  double start = getNowSeconds();
  for (int i = 0; i < nIterations; ++i) {
    Data data(name);
    data.setContent(content);
    if (useComplex) {
      data.getMetaInfo().setFreshnessPeriod(1000);
      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;
      keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
      keyLocator.setKeyName(certificateName);
      Sha256WithRsaSignature* sha256Signature = (Sha256WithRsaSignature*)data.getSignature();
      sha256Signature->setKeyLocator(keyLocator);
      sha256Signature->setSignature(signatureBits);
    }

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

  return finish - start;
}
int
ndnsec_delete(int argc, char** argv)
{
  using namespace ndn;
  namespace po = boost::program_options;

  bool isDeleteKey = false;
  bool isDeleteCert = false;
  std::string name;

  po::options_description description("General Usage\n"
                                      "ndnsec delete [-h] [-k|c] name\n"
                                      "General options");
  description.add_options()
    ("help,h", "produce help message")
    ("delete-key,k", "(Optional) delete a key if specified.")
    ("delete-key2,K", "(Optional) delete a key if specified.")
    ("delete-cert,c", "(Optional) delete a certificate if specified.")
    ("delete-cert2,C", "(Optional) delete a certificate if specified.")
    ("name,n", po::value<std::string>(&name), "By default, it refers to an identity."
     "If -k is specified, it refers to a key."
     "If -c is specified, it refers to a certificate.");
    ;

  po::positional_options_description p;
  p.add("name", 1);

  po::variables_map vm;
  try {
    po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
              vm);
    po::notify(vm);
  }
  catch (const std::exception& e) {
    std::cerr << "ERROR: " << e.what() << std::endl;
    std::cerr << description << std::endl;
    return 2;
  }

  if (vm.count("help") != 0) {
    std::cerr << description << std::endl;;
    return 0;
  }

  if (vm.count("name") == 0) {
    std::cerr << "ERROR: name must be specified" << std::endl;
    std::cerr << description << std::endl;
    return 2;
  }

  if (vm.count("delete-cert") != 0 || vm.count("delete-cert2") != 0)
    isDeleteCert = true;

  else if (vm.count("delete-key") != 0 || vm.count("delete-key2") != 0)
    isDeleteKey = true;

  KeyChain keyChain;

  try {
    if (isDeleteCert) {
      if (!keyChain.doesCertificateExist(name)) {
        std::cerr << "ERROR: Certificate does not exist: " << name << std::endl;
        return 1;
      }

      keyChain.deleteCertificate(name);
      std::cerr << "OK: Delete certificate: " << name << std::endl;
    }
    else if (isDeleteKey) {
      if (!keyChain.doesPublicKeyExist(name) &&
          !keyChain.doesKeyExistInTpm(name, KEY_CLASS_PRIVATE)) {
        std::cerr << "ERROR: Key does not exist: " << name << std::endl;
        return 1;
      }

      keyChain.deleteKey(name);
      std::cerr << "OK: Delete key: " << name << std::endl;
    }
    else {
      if (!keyChain.doesIdentityExist(name)) {
        std::cerr << "ERROR: Identity does not exist: " << name << std::endl;
        return 1;
      }

      keyChain.deleteIdentity(name);
      std::cerr << "OK: Delete identity: " << name << std::endl;
    }
  }
  catch (const SecPublicInfo::Error& e) {
    std::cerr << "ERROR: Cannot delete the item: " << e.what() << std::endl;
    return 2;
  }
  catch (const SecTpm::Error& e) {
    std::cerr << "ERROR: Cannot delete the item: " << e.what() << std::endl;
    return 2;
  }
  catch (const KeyChain::Error& e) {
    std::cerr << "ERROR: " << e.what() << std::endl;
    return 2;
  }

  return 0;
}