tools: ndnsec code reorganization

Change-Id: I94bc0e4904e90370724e8e7ccc56221e64b2ac24
diff --git a/tools/ndnsec/cert-dump.hpp b/tools/ndnsec/cert-dump.hpp
new file mode 100644
index 0000000..fd1313a
--- /dev/null
+++ b/tools/ndnsec/cert-dump.hpp
@@ -0,0 +1,206 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_CERT_DUMP_HPP
+#define NDN_TOOLS_NDNSEC_CERT_DUMP_HPP
+
+#include "util.hpp"
+
+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;
+}
+
+#endif // NDN_TOOLS_NDNSEC_CERT_DUMP_HPP
diff --git a/tools/ndnsec/cert-gen.hpp b/tools/ndnsec/cert-gen.hpp
new file mode 100644
index 0000000..64e7469
--- /dev/null
+++ b/tools/ndnsec/cert-gen.hpp
@@ -0,0 +1,235 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_CERT_GEN_HPP
+#define NDN_TOOLS_NDNSEC_CERT_GEN_HPP
+
+#include "util.hpp"
+
+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;
+
+  KeyChain keyChain;
+
+  std::string notBeforeStr;
+  std::string notAfterStr;
+  std::string subjectName;
+  std::string requestFile("-");
+  Name signId;
+  std::string subjectInfo;
+  std::vector<std::string> signedInfo;
+  Name certPrefix = KeyChain::DEFAULT_PREFIX; // to avoid displaying the default value
+
+  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 (default: now)")
+    ("not-after,E",    po::value<std::string>(&notAfterStr),
+                       "certificate ending date, YYYYMMDDhhmmss (default: now + 365 days)")
+    ("subject-name,N", po::value<std::string>(&subjectName),
+                       "subject name")
+    ("subject-info,I", po::value<std::string>(&subjectInfo),
+                       "(deprecated, uses 'signed-info') subject info, pairs of OID and string "
+                       " description: \"2.5.4.10 'University of California, Los Angeles'\"")
+    ("signed-info",    po::value<std::vector<std::string> >(&signedInfo),
+                       "a pair of OID and string (must be separated by a single space), e.g., "
+                       "\"2.5.4.10 University of California, Los Angeles\". "
+                       "May be repeated multiple times")
+    ("sign-id,s",      po::value<Name>(&signId)->default_value(keyChain.getDefaultIdentity()),
+                       "signing identity")
+    ("cert-prefix,p",  po::value<Name>(&certPrefix),
+                       "cert prefix, which is the part of certificate name before "
+                       "KEY component")
+    ("request,r",      po::value<std::string>(&requestFile)->default_value("-"),
+                       "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::cout << description << std::endl;
+      return 0;
+    }
+
+  if (vm.count("subject-name") == 0)
+    {
+      std::cerr << "ERROR: subject name must be specified" << std::endl
+                << std::endl
+                << description << std::endl;
+      return 1;
+    }
+
+  std::vector<CertificateSubjectDescription> subjectDescription;
+  subjectDescription.push_back(CertificateSubjectDescription(oid::ATTRIBUTE_NAME, subjectName));
+
+  // 'subjectInfo' is deprecated and the following block will be removed eventually
+  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++;
+    }
+
+  // new 'signedInfo' processing
+  for (std::vector<std::string>::const_iterator info = signedInfo.begin();
+       info != signedInfo.end(); ++info) {
+    size_t pos = info->find(" ");
+    if (pos == std::string::npos) {
+      std::cerr << "ERROR: incorrectly formatted signed info block [" << *info << "]" << std::endl;
+      return 1;
+    }
+    OID oid(info->substr(0, pos));
+    std::string value = info->substr(pos + 1);
+
+    subjectDescription.push_back(CertificateSubjectDescription(oid, value));
+  }
+
+  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 << "ERROR: not-before cannot be later than not-after" << std::endl
+                    << std::endl
+                    << description << std::endl;
+          return 1;
+        }
+    }
+
+  if (vm.count("request") == 0)
+    {
+      std::cerr << "ERROR: request file must be specified" << std::endl
+                << std::endl
+                << description << std::endl;
+      return 1;
+    }
+
+  shared_ptr<IdentityCertificate> selfSignedCertificate
+    = getIdentityCertificate(requestFile);
+
+  if (!static_cast<bool>(selfSignedCertificate))
+    {
+      std::cerr << "ERROR: input error" << std::endl;
+      return 1;
+    }
+
+  Name keyName = selfSignedCertificate->getPublicKeyName();
+
+  shared_ptr<IdentityCertificate> certificate =
+    keyChain.prepareUnsignedIdentityCertificate(keyName, selfSignedCertificate->getPublicKeyInfo(),
+                                                signId, notBefore, notAfter,
+                                                subjectDescription, certPrefix);
+
+  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(signId);
+  Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(signId);
+  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;
+}
+
+#endif // NDN_TOOLS_NDNSEC_CERT_GEN_HPP
diff --git a/tools/ndnsec/cert-install.hpp b/tools/ndnsec/cert-install.hpp
new file mode 100644
index 0000000..94a73a7
--- /dev/null
+++ b/tools/ndnsec/cert-install.hpp
@@ -0,0 +1,235 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_CERT_INSTALL_HPP
+#define NDN_TOOLS_NDNSEC_CERT_INSTALL_HPP
+
+#include "util.hpp"
+
+
+class HttpException : public std::runtime_error
+{
+public:
+  explicit
+  HttpException(const std::string& what)
+    : std::runtime_error(what)
+  {
+  }
+};
+
+ndn::shared_ptr<ndn::IdentityCertificate>
+getCertificateHttp(const std::string& host, const std::string& port, const std::string& path)
+{
+  using namespace boost::asio::ip;
+  tcp::iostream requestStream;
+
+  requestStream.expires_from_now(boost::posix_time::milliseconds(3000));
+
+  requestStream.connect(host, port);
+  if (!static_cast<bool>(requestStream))
+    {
+      throw HttpException("HTTP connection error");
+    }
+  requestStream << "GET " << path << " HTTP/1.0\r\n";
+  requestStream << "Host: " << host << "\r\n";
+  requestStream << "Accept: */*\r\n";
+  requestStream << "Cache-Control: no-cache\r\n";
+  requestStream << "Connection: close\r\n\r\n";
+  requestStream.flush();
+
+  std::string statusLine;
+  std::getline(requestStream, statusLine);
+  if (!static_cast<bool>(requestStream))
+    {
+      throw HttpException("HTTP communication error");
+    }
+
+  std::stringstream responseStream(statusLine);
+  std::string httpVersion;
+  responseStream >> httpVersion;
+  unsigned int statusCode;
+  responseStream >> statusCode;
+  std::string statusMessage;
+
+  std::getline(responseStream, statusMessage);
+  if (!static_cast<bool>(requestStream) || httpVersion.substr(0, 5) != "HTTP/")
+    {
+      throw HttpException("HTTP communication error");
+    }
+  if (statusCode != 200)
+    {
+      throw HttpException("HTTP server error");
+    }
+  std::string header;
+  while (std::getline(requestStream, header) && header != "\r")
+    ;
+
+  ndn::OBufferStream os;
+  {
+    using namespace CryptoPP;
+    FileSource ss2(requestStream, true, new Base64Decoder(new FileSink(os)));
+  }
+
+  ndn::shared_ptr<ndn::IdentityCertificate> identityCertificate =
+    ndn::make_shared<ndn::IdentityCertificate>();
+  identityCertificate->wireDecode(ndn::Block(os.buf()));
+
+  return identityCertificate;
+}
+
+int
+ndnsec_cert_install(int argc, char** argv)
+{
+  using namespace ndn;
+  namespace po = boost::program_options;
+
+  std::string certFileName;
+  bool isSystemDefault = true;
+  bool isIdentityDefault = false;
+  bool isKeyDefault = false;
+
+  po::options_description description("General Usage\n  ndnsec cert-install [-h] [-I|K|N] cert-file\nGeneral options");
+  description.add_options()
+    ("help,h", "produce help message")
+    ("cert-file,f", po::value<std::string>(&certFileName), "file name of the ceritificate, - for stdin. "
+                                                      "If starts with http://, will try to fetch "
+                                                      "the certificate using HTTP GET request")
+    ("identity-default,I", "optional, if specified, the certificate will be set as the default certificate of the identity")
+    ("key-default,K", "optional, if specified, the certificate will be set as the default certificate of the key")
+    ("no-default,N", "optional, if specified, the certificate will be simply installed")
+    ;
+  po::positional_options_description p;
+  p.add("cert-file", 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("cert-file") == 0)
+    {
+      std::cerr << "cert_file must be specified" << std::endl;
+      std::cerr << description << std::endl;
+      return 1;
+    }
+
+  if (vm.count("identity-default") != 0)
+    {
+      isIdentityDefault = true;
+      isSystemDefault = false;
+    }
+  else if (vm.count("key-default") != 0)
+    {
+      isKeyDefault = true;
+      isSystemDefault = false;
+    }
+  else if (vm.count("no-default") != 0)
+    {
+      // noDefault = true;
+      isSystemDefault = false;
+    }
+
+  shared_ptr<IdentityCertificate> cert;
+
+  if (certFileName.find("http://") == 0)
+    {
+      std::string host;
+      std::string port;
+      std::string path;
+
+      size_t pos = 7; // offset of "http://"
+      size_t posSlash = certFileName.find("/", pos);
+
+      if (posSlash == std::string::npos)
+        throw HttpException("Request line is not correctly formatted");
+
+      size_t posPort = certFileName.find(":", pos);
+
+      if (posPort != std::string::npos && posPort < posSlash) // port is specified
+        {
+          port = certFileName.substr(posPort + 1, posSlash - posPort - 1);
+          host = certFileName.substr(pos, posPort - pos);
+        }
+      else
+        {
+          port = "80";
+          host = certFileName.substr(pos, posSlash - pos);
+        }
+
+      path = certFileName.substr(posSlash, certFileName.size () - posSlash);
+
+      cert = getCertificateHttp(host, port, path);
+    }
+  else
+    {
+      cert = getIdentityCertificate(certFileName);
+    }
+
+  if (!static_cast<bool>(cert))
+    return 1;
+
+  KeyChain keyChain;
+
+  if (isSystemDefault)
+    {
+      keyChain.addCertificateAsIdentityDefault(*cert);
+      Name keyName = cert->getPublicKeyName();
+      Name identity = keyName.getSubName(0, keyName.size()-1);
+      keyChain.setDefaultIdentity(identity);
+    }
+  else if (isIdentityDefault)
+    {
+      keyChain.addCertificateAsIdentityDefault(*cert);
+    }
+  else if (isKeyDefault)
+    {
+      keyChain.addCertificateAsKeyDefault(*cert);
+    }
+  else
+    {
+      keyChain.addCertificate(*cert);
+    }
+
+  std::cerr << "OK: certificate with name ["
+            << cert->getName().toUri()
+            << "] has been successfully installed"
+            << std::endl;
+
+  return 0;
+}
+
+#endif // NDN_TOOLS_NDNSEC_CERT_INSTALL_HPP
diff --git a/tools/ndnsec/cert-revoke.hpp b/tools/ndnsec/cert-revoke.hpp
new file mode 100644
index 0000000..7056ca6
--- /dev/null
+++ b/tools/ndnsec/cert-revoke.hpp
@@ -0,0 +1,191 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_CERT_REVOKE_HPP
+#define NDN_TOOLS_NDNSEC_CERT_REVOKE_HPP
+
+#include "util.hpp"
+
+int
+ndnsec_cert_revoke(int argc, char** argv)
+{
+  using namespace ndn;
+  namespace po = boost::program_options;
+
+  KeyChain keyChain;
+
+  std::string requestFile("-");
+  Name signId = keyChain.getDefaultIdentity();
+  bool hasSignId = false;
+  Name certPrefix = KeyChain::DEFAULT_PREFIX;
+
+  po::options_description description("General Usage\n  ndnsec cert-revoke [-h] request\n"
+                                      "General options");
+  description.add_options()
+    ("help,h", "produce help message")
+    ("sign-id,s",     po::value<Name>(&signId),
+                      "signing identity (default: use the same as in the revoked certificate)")
+    ("cert-prefix,p", po::value<Name>(&certPrefix),
+                      "cert prefix, which is the part of certificate name before "
+                      "KEY component (default: use the same as in the revoked certificate)")
+    ("request,r",     po::value<std::string>(&requestFile)->default_value("-"),
+                      "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;
+    }
+
+  hasSignId = (vm.count("sign-id") != 0);
+
+  if (vm.count("request") == 0)
+    {
+      std::cerr << "request file must be specified" << std::endl;
+      return 1;
+    }
+
+  shared_ptr<IdentityCertificate> revokedCertificate
+    = getIdentityCertificate(requestFile);
+
+  if (!static_cast<bool>(revokedCertificate))
+    {
+      std::cerr << "ERROR: input error" << std::endl;
+      return 1;
+    }
+
+  Block wire;
+
+  try
+    {
+      Name keyName;
+
+      if (hasSignId) {
+        keyName = keyChain.getDefaultKeyNameForIdentity(signId);
+      }
+      else {
+        const Signature& signature = revokedCertificate->getSignature();
+        if (!signature.hasKeyLocator() ||
+            signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name)
+          {
+            std::cerr << "ERROR: Invalid certificate to revoke" << std::endl;
+            return 1;
+          }
+
+        keyName = IdentityCertificate::certificateNameToPublicKeyName(
+                    signature.getKeyLocator().getName());
+      }
+
+      Name certName;
+      if (certPrefix == KeyChain::DEFAULT_PREFIX) {
+        certName = revokedCertificate->getName().getPrefix(-1);
+      }
+      else {
+        Name revokedKeyName = revokedCertificate->getPublicKeyName();
+
+        if (certPrefix.isPrefixOf(revokedKeyName) && certPrefix != revokedKeyName) {
+          certName.append(certPrefix)
+            .append("KEY")
+            .append(revokedKeyName.getSubName(certPrefix.size()))
+            .append("ID-CERT");
+        }
+        else {
+          std::cerr << "ERROR: certificate prefix does not match the revoked certificate"
+                    << std::endl;
+          return 1;
+        }
+      }
+      certName
+        .appendVersion()
+        .append("REVOKED");
+
+      Data revocationCert;
+      revocationCert.setName(certName);
+
+      if (keyChain.doesPublicKeyExist(keyName))
+        {
+          Name signingCertificateName = keyChain.getDefaultCertificateNameForKey(keyName);
+          keyChain.sign(revocationCert, signingCertificateName);
+        }
+      else
+        {
+          std::cerr << "ERROR: Cannot find the signing key!" << std::endl;
+          return 1;
+        }
+
+      wire = revocationCert.wireEncode();
+    }
+  catch (Signature::Error& e)
+    {
+      std::cerr << "ERROR: No valid signature!" << std::endl;
+      return 1;
+    }
+  catch (KeyLocator::Error& e)
+    {
+      std::cerr << "ERROR: No valid KeyLocator!" << std::endl;
+      return 1;
+    }
+  catch (IdentityCertificate::Error& e)
+    {
+      std::cerr << "ERROR: Cannot determine the signing key!" << std::endl;
+      return 1;
+    }
+  catch (SecPublicInfo::Error& e)
+    {
+      std::cerr << "ERROR: Incomplete or corrupted PIB (" << e.what() << ")" << std::endl;
+      return 1;
+    }
+
+  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;
+}
+
+#endif // NDN_TOOLS_NDNSEC_CERT_REVOKE_HPP
diff --git a/tools/ndnsec/delete.hpp b/tools/ndnsec/delete.hpp
new file mode 100644
index 0000000..629440f
--- /dev/null
+++ b/tools/ndnsec/delete.hpp
@@ -0,0 +1,111 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_DELETE_HPP
+#define NDN_TOOLS_NDNSEC_DELETE_HPP
+
+#include "util.hpp"
+
+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;
+}
+
+#endif // NDN_TOOLS_NDNSEC_DELETE_HPP
diff --git a/tools/ndnsec/dsk-gen.hpp b/tools/ndnsec/dsk-gen.hpp
new file mode 100644
index 0000000..c07afab
--- /dev/null
+++ b/tools/ndnsec/dsk-gen.hpp
@@ -0,0 +1,184 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_DSK_GEN_HPP
+#define NDN_TOOLS_NDNSEC_DSK_GEN_HPP
+
+#include "util.hpp"
+
+int
+ndnsec_dsk_gen(int argc, char** argv)
+{
+  using namespace ndn;
+  namespace po = boost::program_options;
+
+  std::string identityName;
+  char keyType = 'r';
+
+  po::options_description description("General Usage\n"
+                                      "  ndnsec dsk-gen [-h] [-t keyType] identity\n"
+                                      "General options");
+  description.add_options()
+    ("help,h", "produce help message")
+    ("identity,i", po::value<std::string>(&identityName),
+     "identity name, for example, /ndn/ucla.edu/alice")
+    ("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;
+  }
+
+  shared_ptr<IdentityCertificate> kskCert;
+  Name signingCertName;
+
+  KeyChain keyChain;
+
+  try {
+    Name defaultCertName = keyChain.getDefaultCertificateNameForIdentity(identityName);
+    bool isDefaultDsk = false;
+    std::string keyUsageTag = defaultCertName.get(-3).toUri().substr(0,4);
+    if (keyUsageTag == "ksk-")
+      isDefaultDsk = false;
+    else if (keyUsageTag == "dsk-")
+      isDefaultDsk = true;
+    else {
+      std::cerr << "ERROR: Unknown key usage tag: " << keyUsageTag << std::endl;
+      return 1;
+    }
+
+    if (isDefaultDsk) {
+      shared_ptr<IdentityCertificate> dskCert = keyChain.getCertificate(defaultCertName);
+
+      if (static_cast<bool>(dskCert)) {
+        SignatureSha256WithRsa sha256sig(dskCert->getSignature());
+
+        Name keyLocatorName = sha256sig.getKeyLocator().getName();
+
+        Name kskName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
+        Name kskCertName = keyChain.getDefaultCertificateNameForKey(kskName);
+        signingCertName = kskCertName;
+        kskCert = keyChain.getCertificate(kskCertName);
+      }
+      else {
+        std::cerr << "ERROR: The default certificate is missing." << std::endl;
+        return 1;
+      }
+    }
+    else {
+      signingCertName = defaultCertName;
+      kskCert = keyChain.getCertificate(defaultCertName);
+    }
+
+    if (!static_cast<bool>(kskCert)) {
+      std::cerr << "ERROR: KSK certificate is missing." << std::endl;
+      return 1;
+    }
+
+    Name newKeyName;
+    switch (keyType) {
+    case 'r':
+      {
+        RsaKeyParams params;
+        newKeyName = keyChain.generateRsaKeyPair(Name(identityName), false, params.getKeySize());
+        if (0 == newKeyName.size()) {
+          std::cerr << "ERROR: Fail to generate RSA key!" << std::endl;
+          return 1;
+        }
+        break;
+      }
+    case 'e':
+      {
+        EcdsaKeyParams params;
+        newKeyName = keyChain.generateEcdsaKeyPair(Name(identityName), false, params.getKeySize());
+        if (0 == newKeyName.size()) {
+          std::cerr << "ERROR: Fail to generate ECDSA key!" << std::endl;
+          return 1;
+        }
+        break;
+      }
+    default:
+      std::cerr << "ERROR: Unrecongized key type" << "\n";
+      std::cerr << description << std::endl;
+      return 1;
+    }
+
+    Name certName = newKeyName.getPrefix(-1);
+    certName.append("KEY")
+      .append(newKeyName.get(-1))
+      .append("ID-CERT")
+      .appendVersion();
+
+    shared_ptr<IdentityCertificate> certificate =
+      keyChain.prepareUnsignedIdentityCertificate(newKeyName,
+                                                  Name(identityName),
+                                                  kskCert->getNotBefore(),
+                                                  kskCert->getNotAfter(),
+                                                  kskCert->getSubjectDescriptionList());
+
+    if (static_cast<bool>(certificate))
+      certificate->encode();
+    else {
+      std::cerr << "ERROR: Cannot format the certificate of the requested dsk." << "\n";
+      return 1;
+    }
+
+    keyChain.sign(*certificate, signingCertName);
+
+    keyChain.addCertificateAsIdentityDefault(*certificate);
+
+    std::cerr << "OK: dsk certificate with name [" << certificate->getName() <<
+      "] has been successfully installed\n";
+    return 0;
+  }
+  catch (std::runtime_error& e) {
+    std::cerr << "ERROR: other runtime errors: " << e.what() << "\n";
+    return 1;
+  }
+}
+
+#endif // NDN_TOOLS_NDNSEC_DSK_GEN_HPP
diff --git a/tools/ndnsec/export.hpp b/tools/ndnsec/export.hpp
new file mode 100644
index 0000000..aab60ae
--- /dev/null
+++ b/tools/ndnsec/export.hpp
@@ -0,0 +1,135 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_EXPORT_HPP
+#define NDN_TOOLS_NDNSEC_EXPORT_HPP
+
+#include "util.hpp"
+
+int
+ndnsec_export(int argc, char** argv)
+{
+  using namespace ndn;
+  namespace po = boost::program_options;
+
+  std::string identityStr;
+  std::string output;
+  std::string exportPassword;
+  bool isPrivateExport = false;
+
+  po::options_description description("General Usage\n  ndnsec export [-h] [-o output] [-p] identity \nGeneral options");
+  description.add_options()
+    ("help,h", "Produce help message")
+    ("output,o", po::value<std::string>(&output), "(Optional) output file, stdout if not specified")
+    ("private,p", "export info contains private key")
+    ("identity,i", po::value<std::string>(&identityStr), "Identity to export")
+    ;
+
+  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 << "ERROR: identity must be specified" << std::endl;
+      std::cerr << description << std::endl;
+      return 1;
+    }
+
+  if (vm.count("private") != 0)
+    isPrivateExport = true;
+
+  if (vm.count("output") == 0)
+    output = "-";
+
+  Name identity(identityStr);
+  if (!isPrivateExport)
+    {
+      KeyChain keyChain;
+      shared_ptr<IdentityCertificate> cert
+        = keyChain.getCertificate(keyChain.getDefaultCertificateNameForIdentity(identity));
+
+      if (output == "-")
+        io::save(*cert, std::cout);
+      else
+        io::save(*cert, output);
+
+      return 0;
+    }
+  else
+    {
+      Block wire;
+      try
+        {
+          KeyChain keyChain;
+
+          int count = 3;
+          while (!getPassword(exportPassword, "Passphrase for the private key: "))
+            {
+              count--;
+              if (count <= 0)
+                {
+                  std::cerr << "ERROR: invalid password" << std::endl;
+                  memset(const_cast<char*>(exportPassword.c_str()), 0, exportPassword.size());
+                  return 1;
+                }
+            }
+          shared_ptr<SecuredBag> securedBag = keyChain.exportIdentity(identity, exportPassword);
+          memset(const_cast<char*>(exportPassword.c_str()), 0, exportPassword.size());
+
+          if (output == "-")
+            io::save(*securedBag, std::cout);
+          else
+            io::save(*securedBag, output);
+
+          return 0;
+        }
+      catch (const std::runtime_error& e)
+        {
+          std::cerr << "ERROR: " << e.what() << std::endl;
+          memset(const_cast<char*>(exportPassword.c_str()), 0, exportPassword.size());
+          return 1;
+        }
+    }
+}
+
+#endif // NDN_TOOLS_NDNSEC_EXPORT_HPP
diff --git a/tools/ndnsec/get-default.hpp b/tools/ndnsec/get-default.hpp
new file mode 100644
index 0000000..9af33cb
--- /dev/null
+++ b/tools/ndnsec/get-default.hpp
@@ -0,0 +1,148 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_GET_DEFAULT_HPP
+#define NDN_TOOLS_NDNSEC_GET_DEFAULT_HPP
+
+#include "util.hpp"
+
+
+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;
+    }
+}
+
+#endif // NDN_TOOLS_NDNSEC_GET_DEFAULT_HPP
diff --git a/tools/ndnsec/import.hpp b/tools/ndnsec/import.hpp
new file mode 100644
index 0000000..f8bfedf
--- /dev/null
+++ b/tools/ndnsec/import.hpp
@@ -0,0 +1,115 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_IMPORT_HPP
+#define NDN_TOOLS_NDNSEC_IMPORT_HPP
+
+#include "util.hpp"
+
+int
+ndnsec_import(int argc, char** argv)
+{
+  using namespace ndn;
+  namespace po = boost::program_options;
+
+  std::string input("-");
+  std::string importPassword;
+  bool isPrivateImport = false;
+
+  po::options_description description("General Usage\n  ndnsec import [-h] [-p] input \nGeneral options");
+  description.add_options()
+    ("help,h", "produce help message")
+    ("private,p", "import info contains private key")
+    ("input,i", po::value<std::string>(&input), "input source, stdin if -")
+    ;
+
+  po::positional_options_description p;
+  p.add("input", 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("private") != 0)
+    isPrivateImport = true;
+
+  if (!isPrivateImport)
+    {
+      std::cerr << "You are trying to import certificate!\n"
+                << "Please use ndnsec cert-install!" << std::endl;
+      return 1;
+    }
+  else
+    {
+      try
+        {
+          KeyChain keyChain;
+
+          shared_ptr<SecuredBag> securedBag;
+          if (input == "-")
+            securedBag = io::load<SecuredBag>(std::cin);
+          else
+            securedBag = io::load<SecuredBag>(input);
+
+          int count = 3;
+          while (!getPassword(importPassword, "Passphrase for the private key: "))
+            {
+              count--;
+              if (count <= 0)
+                {
+                  std::cerr << "ERROR: Fail to get password" << std::endl;
+                  memset(const_cast<char*>(importPassword.c_str()), 0, importPassword.size());
+                  return 1;
+                }
+            }
+          keyChain.importIdentity(*securedBag, importPassword);
+          memset(const_cast<char*>(importPassword.c_str()), 0, importPassword.size());
+        }
+      catch (const std::runtime_error& e)
+        {
+          std::cerr << "ERROR: " << e.what() << std::endl;
+          memset(const_cast<char*>(importPassword.c_str()), 0, importPassword.size());
+          return 1;
+        }
+
+      return 0;
+    }
+}
+
+#endif // NDN_TOOLS_NDNSEC_IMPORT_HPP
diff --git a/tools/ndnsec/key-gen.hpp b/tools/ndnsec/key-gen.hpp
new file mode 100644
index 0000000..1633855
--- /dev/null
+++ b/tools/ndnsec/key-gen.hpp
@@ -0,0 +1,126 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_KEY_GEN_HPP
+#define NDN_TOOLS_NDNSEC_KEY_GEN_HPP
+
+#include "util.hpp"
+
+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<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;
+}
+
+#endif // NDN_TOOLS_NDNSEC_KEY_GEN_HPP
diff --git a/tools/ndnsec/list.hpp b/tools/ndnsec/list.hpp
new file mode 100644
index 0000000..f40ab5e
--- /dev/null
+++ b/tools/ndnsec/list.hpp
@@ -0,0 +1,174 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_LIST_HPP
+#define NDN_TOOLS_NDNSEC_LIST_HPP
+
+#include "util.hpp"
+
+void
+printCertificate(ndn::KeyChain& keyChain,
+                 const ndn::Name& certName,
+                 bool isDefault,
+                 int verboseLevel)
+{
+  if (isDefault)
+    std::cout << "       +->* ";
+  else
+    std::cout << "       +->  ";
+
+  std::cout << certName << std::endl;
+
+  if (verboseLevel >= 3) {
+    ndn::shared_ptr<ndn::IdentityCertificate> certificate = keyChain.getCertificate(certName);
+    if (static_cast<bool>(certificate))
+      certificate->printCertificate(std::cout, "            ");
+  }
+}
+
+void
+printKey(ndn::KeyChain& keyChain,
+         const ndn::Name& keyName,
+         bool isDefault,
+         int verboseLevel)
+{
+  if (isDefault)
+    std::cout << "  +->* ";
+  else
+    std::cout << "  +->  ";
+
+  std::cout << keyName << std::endl;
+
+  if (verboseLevel >= 2) {
+    std::vector<ndn::Name> defaultCertificates;
+    keyChain.getAllCertificateNamesOfKey(keyName, defaultCertificates, true);
+
+    for (const auto& certName : defaultCertificates)
+      printCertificate(keyChain, certName, true, verboseLevel);
+
+    std::vector<ndn::Name> otherCertificates;
+    keyChain.getAllCertificateNamesOfKey(keyName, otherCertificates, false);
+    for (const auto& certName : otherCertificates)
+      printCertificate(keyChain, certName, false, verboseLevel);
+  }
+}
+
+void
+printIdentity(ndn::KeyChain& keyChain,
+              const ndn::Name& identity,
+              bool isDefault,
+              int verboseLevel)
+{
+  if (isDefault)
+    std::cout << "* ";
+  else
+    std::cout << "  ";
+
+  std::cout << identity << std::endl;
+
+  if (verboseLevel >= 1) {
+    std::vector<ndn::Name> defaultKeys;
+    keyChain.getAllKeyNamesOfIdentity(identity, defaultKeys, true);
+    for (const auto& keyName : defaultKeys)
+      printKey(keyChain, keyName, true, verboseLevel);
+
+    std::vector<ndn::Name> otherKeys;
+    keyChain.getAllKeyNamesOfIdentity(identity, otherKeys, false);
+    for (const auto& keyName : otherKeys) {
+      printKey(keyChain, keyName, false, verboseLevel);
+    }
+
+    std::cout << std::endl;
+  }
+}
+
+int
+ndnsec_list(int argc, char** argv)
+{
+  using namespace ndn;
+  namespace po = boost::program_options;
+
+  int verboseLevel = 0; // 0 print identity only
+                        // 1 print key name
+                        // 2 print cert name
+                        // 3 print cert content
+
+  po::options_description options("General Usage\n  ndnsec list [-h] [-k|c]\nGeneral options");
+  options.add_options()
+    ("help,h",    "produce help message")
+    ("key,k",     "granularity: key")
+    ("cert,c",    "granularity: certificate")
+    ("verbose,v", accumulator<int>(&verboseLevel),
+                  "verbose mode: -v is equivalent to -k, -vv is equivalent to -c")
+    ;
+
+  po::options_description oldOptions;
+  oldOptions.add_options()
+    ("key2,K",         "granularity: key")
+    ("cert2,C",        "granularity: certificate");
+
+  po::options_description allOptions;
+  allOptions.add(options).add(oldOptions);
+
+  po::variables_map vm;
+  try {
+    po::store(po::parse_command_line(argc, argv, allOptions), vm);
+    po::notify(vm);
+  }
+  catch (const std::exception& e) {
+    std::cerr << "ERROR: " << e.what() << std::endl;
+    std::cerr << options << std::endl;
+    return 1;
+  }
+
+  if (vm.count("help") != 0) {
+    std::cerr << options << std::endl;;
+    return 0;
+  }
+
+  int tmpVerboseLevel = 0;
+  if (vm.count("cert") != 0 || vm.count("cert2") != 0)
+    tmpVerboseLevel = 2;
+  else if(vm.count("key") != 0 || vm.count("key2") != 0)
+    tmpVerboseLevel = 1;
+
+  verboseLevel = std::max(verboseLevel, tmpVerboseLevel);
+
+  KeyChain keyChain;
+
+  std::vector<Name> defaultIdentities;
+  keyChain.getAllIdentities(defaultIdentities, true);
+  for (const auto& identity : defaultIdentities) {
+    printIdentity(keyChain, identity, true, verboseLevel);
+  }
+
+  std::vector<Name> otherIdentities;
+  keyChain.getAllIdentities(otherIdentities, false);
+  for (const auto& identity : otherIdentities) {
+    printIdentity(keyChain, identity, false, verboseLevel);
+  }
+
+  return 0;
+}
+
+#endif // NDN_TOOLS_NDNSEC_LIST_HPP
diff --git a/tools/ndnsec/main.cpp b/tools/ndnsec/main.cpp
new file mode 100644
index 0000000..ae81752
--- /dev/null
+++ b/tools/ndnsec/main.cpp
@@ -0,0 +1,114 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#include "version.hpp"
+
+#include "util.hpp"
+#include "list.hpp"
+#include "get-default.hpp"
+#include "set-default.hpp"
+#include "key-gen.hpp"
+#include "dsk-gen.hpp"
+#include "sign-req.hpp"
+#include "cert-gen.hpp"
+#include "cert-revoke.hpp"
+#include "cert-dump.hpp"
+#include "cert-install.hpp"
+#include "export.hpp"
+#include "import.hpp"
+#include "delete.hpp"
+#include "sig-verify.hpp"
+#include "set-acl.hpp"
+#include "unlock-tpm.hpp"
+#include "op-tool.hpp"
+
+using namespace ndn;
+
+std::string ndnsec_helper("\
+  help         Show all commands.\n\
+  version      Show version and exit.\n\
+  list         Display information in PublicInfo.\n\
+  get-default  Get default setting info.\n\
+  set-default  Configure default setting.\n\
+  key-gen      Generate a Key-Signing-Key for an identity.\n\
+  dsk-gen      Generate a Data-Signing-Key for an identity.\n\
+  sign-req     Generate a certificate signing request.\n\
+  cert-gen     Generate an identity certificate.\n\
+  cert-revoke  Revoke an identity certificate.\n\
+  cert-dump    Dump a certificate from PublicInfo.\n\
+  cert-install Install a certificate into PublicInfo.\n\
+  delete       Delete identity/key/certificate.\n\
+  export       Export an identity package.\n\
+  import       Import an identity package.\n\
+  sig-verify   Verify the signature of a Data packet.\n\
+  set-acl      Configure ACL of a private key.\n\
+  unlock-tpm   Unlock Tpm.\n\
+  op-tool      Operator tool.\n\
+");
+
+int
+main(int argc, char** argv)
+{
+  if (argc < 2)
+    {
+      std::cerr << ndnsec_helper << std::endl;
+      return 1;
+    }
+
+  std::string command(argv[1]);
+
+  try
+    {
+      if (command == "help")              { std::cout << ndnsec_helper << std::endl; }
+      else if (command == "version")      { std::cout << NDN_CXX_VERSION_BUILD_STRING
+                                                      << std::endl; }
+      else if (command == "list")         { return ndnsec_list(argc - 1, argv + 1); }
+      else if (command == "get-default")  { return ndnsec_get_default(argc - 1, argv + 1); }
+      else if (command == "set-default")  { return ndnsec_set_default(argc - 1, argv + 1); }
+      else if (command == "key-gen")      { return ndnsec_key_gen(argc - 1, argv + 1); }
+      else if (command == "dsk-gen")      { return ndnsec_dsk_gen(argc - 1, argv + 1); }
+      else if (command == "sign-req")     { return ndnsec_sign_req(argc - 1, argv + 1); }
+      else if (command == "cert-gen")     { return ndnsec_cert_gen(argc - 1, argv + 1); }
+      else if (command == "cert-revoke")  { return ndnsec_cert_revoke(argc - 1, argv + 1); }
+      else if (command == "cert-dump")    { return ndnsec_cert_dump(argc - 1, argv + 1); }
+      else if (command == "cert-install") { return ndnsec_cert_install(argc - 1, argv + 1); }
+      else if (command == "delete")       { return ndnsec_delete(argc - 1, argv + 1); }
+      else if (command == "export")       { return ndnsec_export(argc - 1, argv + 1); }
+      else if (command == "import")       { return ndnsec_import(argc - 1, argv + 1); }
+      else if (command == "sig-verify")   { return ndnsec_sig_verify(argc - 1, argv + 1); }
+      else if (command == "set-acl")      { return ndnsec_set_acl(argc - 1, argv + 1); }
+      else if (command == "unlock-tpm")   { return ndnsec_unlock_tpm(argc - 1, argv + 1); }
+      else if (command == "op-tool")      { return ndnsec_op_tool(argc - 1, argv + 1); }
+      else {
+        std::cerr << ndnsec_helper << std::endl;
+        return 1;
+      }
+    }
+  catch (const std::runtime_error& e)
+    {
+      std::cerr << "ERROR: " << e.what() << std::endl;
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/tools/ndnsec/op-tool.hpp b/tools/ndnsec/op-tool.hpp
new file mode 100644
index 0000000..d04d886
--- /dev/null
+++ b/tools/ndnsec/op-tool.hpp
@@ -0,0 +1,97 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_OP_TOOL_HPP
+#define NDN_TOOLS_NDNSEC_OP_TOOL_HPP
+
+#include "util.hpp"
+
+using namespace std;
+
+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>());
+
+      Signature signature = keyChain.sign(dataToSign.buf(), dataToSign.size(),
+                                          keyChain.getDefaultCertificateName());
+
+      if (signature.getValue().value_size() == 0)
+        {
+          std::cerr << "Error signing with default key" << std::endl;
+          return -1;
+        }
+
+      std::cout.write(reinterpret_cast<const char*>(signature.getValue().wire()),
+                      signature.getValue().size());
+    }
+
+  return 0;
+}
+
+#endif // NDN_TOOLS_NDNSEC_OP_TOOL_HPP
diff --git a/tools/ndnsec/set-acl.hpp b/tools/ndnsec/set-acl.hpp
new file mode 100644
index 0000000..d373223
--- /dev/null
+++ b/tools/ndnsec/set-acl.hpp
@@ -0,0 +1,88 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_SET_ACL_HPP
+#define NDN_TOOLS_NDNSEC_SET_ACL_HPP
+
+#include "util.hpp"
+
+int
+ndnsec_set_acl(int argc, char** argv)
+{
+  using namespace ndn;
+  namespace po = boost::program_options;
+
+  std::string keyName;
+  std::string appPath;
+
+  po::options_description description("General Usage\n  ndnsec set-acl [-h] keyName appPath \nGeneral options");
+  description.add_options()
+    ("help,h", "produce help message")
+    ("keyName,k", po::value<std::string>(&keyName), "Key name.")
+    ("appPath,p", po::value<std::string>(&appPath), "Application path.")
+    ;
+
+  po::positional_options_description p;
+  p.add("keyName", 1);
+  p.add("appPath", 1);
+
+  po::variables_map vm;
+  try
+    {
+      po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(),
+                vm);
+      po::notify(vm);
+    }
+  catch (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("keyName") == 0)
+    {
+      std::cerr << "ERROR: keyName is required!" << std::endl;
+      std::cerr << description << std::endl;
+      return 1;
+    }
+
+  if (vm.count("appPath") == 0)
+    {
+      std::cerr << "ERROR: appPath is required!" << std::endl;
+      std::cerr << description << std::endl;
+      return 1;
+    }
+
+  KeyChain keyChain;
+  keyChain.addAppToAcl(keyName, KEY_CLASS_PRIVATE, appPath, ACL_TYPE_PRIVATE);
+
+  return 0;
+}
+
+#endif // NDN_TOOLS_NDNSEC_SET_ACL_HPP
diff --git a/tools/ndnsec/set-default.hpp b/tools/ndnsec/set-default.hpp
new file mode 100644
index 0000000..765471d
--- /dev/null
+++ b/tools/ndnsec/set-default.hpp
@@ -0,0 +1,110 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_SET_DEFAULT_HPP
+#define NDN_TOOLS_NDNSEC_SET_DEFAULT_HPP
+
+int
+ndnsec_set_default(int argc, char** argv)
+{
+  using namespace ndn;
+  namespace po = boost::program_options;
+
+  std::string certFileName;
+  bool isSetDefaultId = true;
+  bool isSetDefaultKey = false;
+  bool isSetDefaultCert = false;
+  std::string name;
+
+  po::options_description description("General Usage\n  ndnsec set-default [-h] [-k|c] name\nGeneral options");
+  description.add_options()
+    ("help,h", "produce help message")
+    ("default_key,k", "set default key of the identity")
+    ("default_cert,c", "set default certificate of the key")
+    ("name,n", po::value<std::string>(&name), "the name to set")
+    ;
+
+  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 is required!" << std::endl;
+      std::cerr << description << std::endl;
+      return 1;
+    }
+
+  KeyChain keyChain;
+
+  if (vm.count("default_key") != 0)
+    {
+      isSetDefaultKey = true;
+      isSetDefaultId = false;
+    }
+  else if (vm.count("default_cert") != 0)
+    {
+      isSetDefaultCert = true;
+      isSetDefaultId = false;
+    }
+
+  if (isSetDefaultId)
+    {
+      Name idName(name);
+      keyChain.setDefaultIdentity(idName);
+      return 0;
+    }
+  if (isSetDefaultKey)
+    {
+      Name keyName(name);
+      keyChain.setDefaultKeyNameForIdentity(keyName);
+      return 0;
+    }
+
+  if (isSetDefaultCert)
+    {
+      keyChain.setDefaultCertificateNameForKey(name);
+      return 0;
+    }
+
+  return 1;
+}
+#endif // NDN_TOOLS_NDNSEC_SET_DEFAULT_HPP
diff --git a/tools/ndnsec/sig-verify.hpp b/tools/ndnsec/sig-verify.hpp
new file mode 100644
index 0000000..e49387a
--- /dev/null
+++ b/tools/ndnsec/sig-verify.hpp
@@ -0,0 +1,128 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_SIG_VERIFY_HPP
+#define NDN_TOOLS_NDNSEC_SIG_VERIFY_HPP
+
+#include "util.hpp"
+
+// using namespace ndn;
+// namespace po = boost::program_options;
+
+// shared_ptr<IdentityCertificate>
+// getCertificate(const std::string& certString)
+// {
+//   std::string decoded;
+//   CryptoPP::StringSource ss2(reinterpret_cast<const unsigned char *>(certString.c_str()), certString.size(), true,
+//                              new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
+
+//   Data data;
+//   data.wireDecode(Block(make_shared<Buffer>(decoded.begin(), decoded.end())));
+
+//   shared_ptr<IdentityCertificate> identityCertificate = make_shared<IdentityCertificate>(data);
+
+//   return identityCertificate;
+// }
+
+// bool
+// verifySignature(shared_ptr<IdentityCertificate> certificate, bool isDataPacket)
+// {
+//   throw std::runtime_error("Not supported yet");
+//   // if(isDataPacket)
+//   //   {
+//   //     std::string decoded;
+//   //     CryptoPP::FileSource ss2(cin, true,
+//   //                              new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
+
+//   //     Data data;
+//   //     data.wireDecode(make_shared<Buffer>(decoded.c_str(), decoded.size()));
+//   //     return PolicyManager::verifySignature(data, certificate->getPublicKeyInfo());
+//   //   }
+//   // else
+//   //   {
+//   //     // The first two bytes indicates the boundary of the of the signed data and signature.
+//   //     // for example, if the size of the signed data is 300, then the boundary should be 300, so the first two bytes should be: 0x01 0x2C
+//   //     shared_ptr<Blob> input = shared_ptr<Blob>(new Blob ((istreambuf_iterator<char>(cin)), istreambuf_iterator<char>()));
+//   //     size_t size = input->at(0);
+//   //     size = ((size << 8) + input->at(1));
+
+//   //     Blob signedBlob(input->buf()+2, size);
+//   //     Blob signature(input->buf()+2+size, input->size()-2-size);
+
+//   //     return PolicyManager::verifySignature(signedBlob, signature, certificate->getPublicKeyInfo());
+//   //   }
+// }
+
+int
+ndnsec_sig_verify(int argc, char** argv)
+{
+  std::cerr << "Not supported yet" << std::endl;
+  return 1;
+  // bool isDataPacket = false;
+  // std::string certString;
+
+  // po::options_description desc("General Usage\n  ndn-sig-verify [-h] [-d] certificate\nGeneral options");
+  // desc.add_options()
+  //   ("help,h", "produce help message")
+  //   ("data,d", "if specified, input from stdin will be treated as a Data packet, otherwise binary data")
+  //   ("certificate,c", po::value<std::string>(&certString), "the certificate bits")
+  //   ;
+
+  // po::positional_options_description p;
+  // p.add("certificate", 1);
+
+  // po::variables_map vm;
+  // try
+  //   {
+  //     po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
+  //     po::notify(vm);
+  //   }
+  // catch( const std::exception& e)
+  //   {
+  //     std::cerr << e.what() << std::endl;
+  //     std::cerr << desc << std::endl;
+  //     return 1;
+  //   }
+
+  // if (vm.count("help") || vm.count("certificate")==0)
+  //   {
+  //     std::cerr << desc << std::endl;
+  //     return 1;
+  //   }
+  // if (vm.count("data"))
+  //   isDataPacket = true;
+
+  // try
+  //   {
+  //     shared_ptr<IdentityCertificate> certificate = getCertificate(certString);
+  //     bool res = verifySignature(certificate, isDataPacket);
+  //     return (res ? 0 : 1);
+  //   }
+  // catch(const std::exception &e)
+  //   {
+  //     std::cerr << "ERROR: " << e.what() << std::endl;
+  //     return 1;
+  //   }
+}
+
+#endif // NDN_TOOLS_NDNSEC_SIG_VERIFY_HPP
diff --git a/tools/ndnsec/sign-req.hpp b/tools/ndnsec/sign-req.hpp
new file mode 100644
index 0000000..e0db0f3
--- /dev/null
+++ b/tools/ndnsec/sign-req.hpp
@@ -0,0 +1,99 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_SIGN_REQ_HPP
+#define NDN_TOOLS_NDNSEC_SIGN_REQ_HPP
+
+#include "util.hpp"
+
+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;
+  }
+}
+
+#endif // NDN_TOOLS_NDNSEC_SIGN_REQ_HPP
diff --git a/tools/ndnsec/unlock-tpm.hpp b/tools/ndnsec/unlock-tpm.hpp
new file mode 100644
index 0000000..7d2043b
--- /dev/null
+++ b/tools/ndnsec/unlock-tpm.hpp
@@ -0,0 +1,83 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_UNLOCK_TPM_HPP
+#define NDN_TOOLS_NDNSEC_UNLOCK_TPM_HPP
+
+#include "util.hpp"
+
+int
+ndnsec_unlock_tpm(int argc, char** argv)
+{
+  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;
+    }
+}
+
+#endif // NDN_TOOLS_NDNSEC_UNLOCK_TPM_HPP
diff --git a/tools/ndnsec/util.hpp b/tools/ndnsec/util.hpp
new file mode 100644
index 0000000..56cbaa6
--- /dev/null
+++ b/tools/ndnsec/util.hpp
@@ -0,0 +1,225 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_TOOLS_NDNSEC_UTIL_HPP
+#define NDN_TOOLS_NDNSEC_UTIL_HPP
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cstring>
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/asio.hpp>
+#include <boost/exception/all.hpp>
+
+
+#include "security/cryptopp.hpp"
+
+#include "security/key-chain.hpp"
+#include "util/io.hpp"
+
+bool
+getPassword(std::string& password, const std::string& prompt)
+{
+  bool isReady = false;
+
+  char* pw0 = 0;
+
+  pw0 = getpass(prompt.c_str());
+  if (!pw0)
+    return false;
+  std::string password1 = pw0;
+  memset(pw0, 0, strlen(pw0));
+
+  pw0 = getpass("Confirm:");
+  if (!pw0)
+    {
+      char* pw1 = const_cast<char*>(password1.c_str());
+      memset(pw1, 0, password1.size());
+      return false;
+    }
+
+  if (!password1.compare(pw0))
+    {
+      isReady = true;
+      password.swap(password1);
+    }
+
+  char* pw1 = const_cast<char*>(password1.c_str());
+  memset(pw1, 0, password1.size());
+  memset(pw0, 0, strlen(pw0));
+
+  if (password.empty())
+    return false;
+
+  return isReady;
+}
+
+ndn::shared_ptr<ndn::IdentityCertificate>
+getIdentityCertificate(const std::string& fileName)
+{
+
+  if (fileName == "-")
+    return ndn::io::load<ndn::IdentityCertificate>(std::cin);
+  else
+    return ndn::io::load<ndn::IdentityCertificate>(fileName);
+}
+
+
+/**
+ * @brief An accumulating option value to handle multiple incrementing options.
+ *
+ * Based on https://gitorious.org/bwy/bwy/source/8753148c324ddfacb1f3cdc315650586bd7b75a4:use/accumulator.hpp
+ * @sa http://benjaminwolsey.de/node/103
+ */
+template<typename T>
+class AccumulatorType : public boost::program_options::value_semantic
+{
+public:
+  explicit
+  AccumulatorType(T* store)
+    : m_store(store)
+    , m_interval(1)
+    , m_default(0)
+  {
+  }
+
+  virtual
+  ~AccumulatorType()
+  {
+  }
+
+  /// @brief Set the default value for this option.
+  AccumulatorType*
+  setDefaultValue(const T& t)
+  {
+    m_default = t;
+    return this;
+  }
+
+  /**
+   * @brief Set the interval for this option.
+   *
+   * Unlike for program_options::value, this specifies a value
+   * to be applied on each occurrence of the option.
+   */
+  AccumulatorType*
+  setInterval(const T& t) {
+    m_interval = t;
+    return this;
+  }
+
+  virtual std::string
+  name() const
+  {
+    return std::string();
+  }
+
+  // There are no tokens for an AccumulatorType
+  virtual unsigned
+  min_tokens() const
+  {
+    return 0;
+  }
+
+  virtual unsigned
+  max_tokens() const
+  {
+    return 0;
+  }
+
+  // Accumulating from different sources is silly.
+  virtual bool
+  is_composing() const
+  {
+    return false;
+  }
+
+  // Requiring one or more appearances is unlikely.
+  virtual bool
+  is_required() const
+  {
+    return false;
+  }
+
+  /**
+   * @brief Parse options
+   *
+   * Every appearance of the option simply increments the value
+   * There should never be any tokens.
+   */
+  virtual void
+  parse(boost::any& value_store,
+        const std::vector<std::string>& new_tokens,
+        bool utf8) const
+  {
+    if (value_store.empty())
+      value_store = T();
+    boost::any_cast<T&>(value_store) += m_interval;
+  }
+
+  /**
+   * @brief If the option doesn't appear, this is the default value.
+   */
+  virtual bool
+  apply_default(boost::any& value_store) const
+  {
+    value_store = m_default;
+    return true;
+  }
+
+  /**
+   * @brief Notify the user function with the value of the value store.
+   */
+  virtual void
+  notify(const boost::any& value_store) const
+  {
+    const T* val = boost::any_cast<T>(&value_store);
+    if (m_store)
+      *m_store = *val;
+  }
+
+private:
+    T* m_store;
+    T m_interval;
+    T m_default;
+};
+
+template<typename T>
+AccumulatorType<T>* accumulator()
+{
+  return new AccumulatorType<T>(0);
+}
+
+template<typename T>
+AccumulatorType<T>* accumulator(T* store)
+{
+  return new AccumulatorType<T>(store);
+}
+
+#endif // NDN_TOOLS_NDNSEC_UTIL_HPP