tools: Add security tools; Add waf build options for tools.

Change-Id: I058510acc1a0361fed43d94c7a0b545416a9efb4
diff --git a/tools/ndnsec-certgen.cpp b/tools/ndnsec-certgen.cpp
new file mode 100644
index 0000000..8b3f21e
--- /dev/null
+++ b/tools/ndnsec-certgen.cpp
@@ -0,0 +1,282 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#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/regex.hpp>
+#include <cryptopp/base64.h>
+#include <cryptopp/files.h>
+
+#include <boost/tokenizer.hpp>
+using boost::tokenizer;
+using boost::escaped_list_separator;
+
+#include "security/key-chain.hpp"
+
+namespace ndn {
+typedef boost::posix_time::ptime Time;
+typedef boost::posix_time::time_duration TimeInterval;
+namespace time {
+const Time UNIX_EPOCH_TIME = Time (boost::gregorian::date (1970, boost::gregorian::Jan, 1));
+} // namespace time
+} // namespace ndn
+
+using namespace ndn;
+namespace po = boost::program_options;
+
+shared_ptr<IdentityCertificate>
+getSelfSignedCertificate(const std::string& fileName)
+{
+  std::istream* ifs;
+  if(fileName == "-")
+    ifs = &std::cin;
+  else
+    ifs = new std::ifstream(fileName.c_str());
+
+  std::string decoded;
+  CryptoPP::FileSource ss2(*ifs, true,
+                           new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
+
+  shared_ptr<IdentityCertificate> identityCertificate = make_shared<IdentityCertificate>();
+  identityCertificate->wireDecode(Block(make_shared<Buffer>(decoded.c_str(), decoded.size())));
+
+  return identityCertificate;
+}
+
+int main(int argc, char** argv)
+{
+  std::string notBeforeStr;
+  std::string notAfterStr;
+  std::string sName;
+  std::string reqFile;
+  std::string signId;
+  std::string subInfo;
+  bool isSelfSigned = false;
+  bool nack = false;
+
+  po::options_description desc("General Usage\n  ndn-certgen [-h] [-S date] [-E date] [-N subject-name] [-I subject-info] [-s sign-id] request\nGeneral options");
+  desc.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>(&sName), "subject name")
+    ("subject-info,I", po::value<std::string>(&subInfo), "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, self-signed if not specified")
+    ("request,r", po::value<std::string>(&reqFile), "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(desc).positional(p).run(), vm);
+      po::notify(vm);
+    }
+  catch (std::exception &e)
+    {
+      std::cerr << "ERROR: " << e.what() << std::endl;
+      return 1;
+    }
+
+  if (vm.count("help"))
+    {
+      std::cerr << desc << std::endl;
+      return 1;
+    }
+
+  if (0 == vm.count("sign-id"))
+    {     
+      isSelfSigned = true;
+    }
+
+  if (vm.count("nack"))
+    {
+      nack = true;
+    }
+
+  std::vector<CertificateSubjectDescription> otherSubDescrypt;
+  tokenizer<escaped_list_separator<char> > subInfoItems(subInfo, escaped_list_separator<char> ("\\", " \t", "'\""));
+
+  tokenizer<escaped_list_separator<char> >::iterator it = subInfoItems.begin();
+  try
+    {
+      while (it != subInfoItems.end())
+        {
+          std::string oid = *it;
+
+          it++;
+          if (it == subInfoItems.end ())
+            {
+              std::cerr << "ERROR: unmatched info for oid [" << oid << "]" << std::endl;
+              return 1;
+            }
+
+          std::string value = *it;
+
+          otherSubDescrypt.push_back (CertificateSubjectDescription(oid, value));
+
+          it++;
+        }
+    }
+  catch (std::exception &e)
+    {
+      std::cerr << "error in parsing subject info" << std::endl;
+      return 1;
+    }
+
+  Time notBefore;
+  Time notAfter;
+  try{
+    if (0 == vm.count("not-before"))
+      {
+        notBefore = boost::posix_time::second_clock::universal_time();
+      }
+    else
+      {
+        notBefore = boost::posix_time::from_iso_string(notBeforeStr.substr(0, 8) + "T" + notBeforeStr.substr(8, 6));
+      }
+
+
+    if (0 == vm.count("not-after"))
+      {
+        notAfter = notBefore + boost::posix_time::hours(24*365);
+      }
+    else
+      {
+        notAfter = boost::posix_time::from_iso_string(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;
+          }
+      }
+  }catch(std::exception & e){
+    std::cerr << "Error in converting validity timestamp!" << std::endl;
+    return 1;
+  }
+
+  if (0 == vm.count("request"))
+    {
+      std::cerr << "request file must be specified" << std::endl;
+      return 1;
+    }
+
+  shared_ptr<IdentityCertificate> selfSignedCertificate;
+  try
+    {
+      selfSignedCertificate = getSelfSignedCertificate(reqFile);
+    }
+  catch(...)
+    {
+      std::cerr << "ERROR: input error" << std::endl;
+      return 1;
+    }
+
+  Name keyName = selfSignedCertificate->getPublicKeyName();
+  Name signIdName;
+  Name certName;
+
+  if(isSelfSigned)
+    {
+      certName = keyName.getPrefix(keyName.size()-1);
+      certName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
+    }
+  else
+    {
+      signIdName = Name(signId);
+  
+      Name::const_iterator i = keyName.begin();
+      Name::const_iterator j = signIdName.begin();
+      int count = 0;
+      for(; i != keyName.end() && j != signIdName.end(); i++, j++, count++)
+        {
+          if(*i != *j)
+            break;
+        }
+      
+      if(j != signIdName.end() || i == keyName.end())
+        {
+          std::cerr << "wrong signing identity!" << std::endl;
+          return 1;
+        }
+
+      certName = keyName.getSubName(0, count);
+      certName.append("KEY").append(keyName.getSubName(count, keyName.size()-count));
+      certName.append("ID-CERT").appendVersion ();
+    }
+
+  Block wire;
+
+  if (!nack)
+    {
+      if (0 == vm.count("subject-name"))
+        {
+          std::cerr << "subject_name must be specified" << std::endl;
+          return 1;
+        }
+
+      try
+        {
+          CertificateSubjectDescription subDescryptName("2.5.4.41", sName);
+          IdentityCertificate certificate;
+          certificate.setName(certName);
+          certificate.setNotBefore((notBefore-ndn::time::UNIX_EPOCH_TIME).total_milliseconds());
+          certificate.setNotAfter((notAfter-ndn::time::UNIX_EPOCH_TIME).total_milliseconds());
+          certificate.setPublicKeyInfo(selfSignedCertificate->getPublicKeyInfo());
+          certificate.addSubjectDescription(subDescryptName);
+          for(int i = 0; i < otherSubDescrypt.size(); i++)
+            certificate.addSubjectDescription(otherSubDescrypt[i]);
+          certificate.encode();
+
+          KeyChain keyChain;
+
+          if(isSelfSigned)
+            keyChain.selfSign(certificate);
+          else
+            {
+              Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(Name(signId));
+              
+              keyChain.sign(certificate, signingCertificateName);
+            }
+          wire = certificate.wireEncode();
+        }
+      catch(std::exception &e)
+        {
+          std::cerr << "ERROR: " << e.what() << std::endl;
+          return 1;
+        }
+    }
+  else
+    {
+      Data revocationCert;
+      // revocationCert.setContent(void*, 0); // empty content
+      revocationCert.setName(certName);
+
+      KeyChain keyChain;
+      Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(Name(signId));
+
+      keyChain.sign (revocationCert, signingCertificateName);
+      wire = revocationCert.wireEncode();
+    }
+
+  CryptoPP::StringSource ss(reinterpret_cast<const unsigned char *>(wire.wire()), wire.size(),
+                            true,
+                            new CryptoPP::Base64Encoder(new CryptoPP::FileSink(std::cout), true, 64));
+
+  return 0;
+}
diff --git a/tools/ndnsec-dskgen.cpp b/tools/ndnsec-dskgen.cpp
new file mode 100644
index 0000000..61f1fbf
--- /dev/null
+++ b/tools/ndnsec-dskgen.cpp
@@ -0,0 +1,143 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <cryptopp/base64.h>
+
+#include "security/key-chain.hpp"
+#include "security/signature-sha256-with-rsa.hpp"
+
+using namespace ndn;
+namespace po = boost::program_options;
+
+
+int main(int argc, char** argv)
+{
+  std::string identityName;
+  char keyType = 'r';
+  int keySize = 2048;
+
+  // po::options_description desc("General Usage\n  ndn-keygen [-h] [-d] [-i] [-t type] [-s size] identity\nGeneral options");
+  po::options_description desc("General Usage\n  ndn-keygen [-h] identity\nGeneral options");
+  desc.add_options()
+    ("help,h", "produce help message")
+    ("identity_name,n", 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)")
+    // ("size,s", po::value<int>(&keySize)->default_value(2048), "optional, key size, 2048 (default)")
+    ;
+
+  po::positional_options_description p;
+  p.add("identity_name", 1);
+
+  po::variables_map vm;
+  po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
+  po::notify(vm);
+
+  if (vm.count("help"))
+    {
+      std::cerr << desc << std::endl;
+      return 1;
+    }
+
+  if (0 == vm.count("identity_name"))
+    {
+      std::cerr << "identity_name must be specified" << std::endl;
+      std::cerr << desc << std::endl;
+      return 1;
+    }
+
+  KeyChain keyChain;
+
+  Name defaultCertName = keyChain.getDefaultCertificateNameForIdentity(identityName);
+  bool isDefaultDsk = false;
+  if(defaultCertName.get(-3).toEscapedString().substr(0,4) == "dsk-")
+    isDefaultDsk = true;
+
+  Name signingCertName;
+  shared_ptr<IdentityCertificate> kskCert;
+  if(isDefaultDsk)
+    {
+      shared_ptr<IdentityCertificate> dskCert = keyChain.getCertificate(defaultCertName);
+      SignatureSha256WithRsa sha256sig(dskCert->getSignature());
+
+      Name keyLocatorName = sha256sig.getKeyLocator().getName(); // will throw exception if keylocator is absent or it is not a name
+
+      Name kskName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
+      Name kskCertName = keyChain.getDefaultCertificateNameForKey(kskName);
+      signingCertName = kskCertName;
+      kskCert = keyChain.getCertificate(kskCertName);
+    }
+  else
+    {
+      signingCertName = defaultCertName;
+      kskCert = keyChain.getCertificate(defaultCertName);
+    }
+
+  Name newKeyName;
+  // if (vm.count("type"))
+  if (true)
+    {
+      switch(keyType)
+      {
+      case 'r':
+        {
+          try
+            {
+              newKeyName = keyChain.generateRSAKeyPair(Name(identityName), false, keySize);
+
+              if(0 == newKeyName.size())
+                {
+		  std::cerr << "fail to generate key!" << std::endl;
+                  return 1;
+                }
+	      break;
+            }
+          catch(std::exception &e)
+            {
+              std::cerr << "ERROR: " << e.what() << std::endl;
+              return 1;
+            }
+        }
+      default:
+        std::cerr << "Unrecongized key type" << "\n";
+        std::cerr << desc << std::endl;
+        return 1;
+      }
+    }
+
+
+  Name certName = newKeyName.getPrefix(newKeyName.size()-1);
+  certName.append("KEY").append(newKeyName.get(-1)).append("ID-CERT").appendVersion ();
+
+  shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
+  certificate->setName(certName);
+  certificate->setNotBefore(kskCert->getNotBefore());
+  certificate->setNotAfter(kskCert->getNotAfter());
+
+  certificate->setPublicKeyInfo(*keyChain.getPublicKey(newKeyName));
+
+  const std::vector<CertificateSubjectDescription>& subList = kskCert->getSubjectDescriptionList();
+  std::vector<CertificateSubjectDescription>::const_iterator it = subList.begin();
+  for(; it != subList.end(); it++)
+      certificate->addSubjectDescription(*it);
+
+  certificate->encode();
+
+  keyChain.sign(*certificate, signingCertName);
+
+  keyChain.addCertificateAsIdentityDefault(*certificate);
+
+  return 0;
+}
diff --git a/tools/ndnsec-dump-certificate.cpp b/tools/ndnsec-dump-certificate.cpp
new file mode 100644
index 0000000..d3936ec
--- /dev/null
+++ b/tools/ndnsec-dump-certificate.cpp
@@ -0,0 +1,220 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#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/asio.hpp>
+
+#include <cryptopp/base64.h>
+#include <cryptopp/files.h>
+
+#include "security/key-chain.hpp"
+
+using namespace ndn;
+namespace po = boost::program_options;
+
+shared_ptr<IdentityCertificate>
+getIdentityCertificate(const std::string& fileName)
+{
+  std::istream* ifs;
+  if(fileName == "-")
+    ifs = &std::cin;
+  else
+    ifs = new std::ifstream(fileName.c_str());
+
+  std::string decoded;
+  CryptoPP::FileSource ss2(*ifs, true,
+                           new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
+
+  ptr_lib::shared_ptr<IdentityCertificate> identityCertificate = ptr_lib::make_shared<IdentityCertificate>();
+  identityCertificate->wireDecode(Block(decoded.c_str(), decoded.size()));
+
+  return identityCertificate;
+}
+
+int main(int argc, char** argv)	
+{
+  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 = "127.0.0.1";
+  std::string repoPort = "7376";
+  bool isDnsOut = false;
+
+  po::options_description desc("General Usage\n  ndn-dump-certificate [-h] [-p] [-d] [-r [-H repo-host] [-P repor-port] ] [-i|k|f] certName\nGeneral options");
+  desc.add_options()
+    ("help,h", "produce help message")
+    ("pretty,p", "optional, if specified, display certificate in human readable format")
+    ("identity,i", "optional, if specified, name is identity name (e.g. /ndn/edu/ucla/alice), otherwise certificate name")
+    ("key,k", "optional, if specified, name is key name (e.g. /ndn/edu/ucla/alice/KSK-123456789), otherwise certificate name")
+    ("file,f", "optional, if specified, name is file name, - for stdin")
+    ("repo-output,r", "optional, if specified, certificate is dumped (published) to repo")
+    ("repo-host,H", po::value<std::string>(&repoHost)->default_value("localhost"), "optional, the repo host if repo-output is specified")
+    ("repo-port,P", po::value<std::string>(&repoPort)->default_value("7376"), "optional, the repo port if repo-output is specified")
+    ("dns-output,d", "optional, if specified, certificate is dumped (published) to DNS")
+    ("name,n", po::value<std::string>(&name), "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;
+  po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
+  po::notify(vm);
+
+  if (vm.count("help")) 
+    {
+      std::cerr << desc << std::endl;
+      return 1;
+    }
+
+  if (0 == vm.count("name"))
+    {
+      std::cerr << "identity_name must be specified" << std::endl;
+      std::cerr << desc << std::endl;
+      return 1;
+    }
+  
+  if (vm.count("key"))
+    {
+      isCertName = false;
+      isKeyName = true;
+    }
+  else if (vm.count("identity"))
+    {
+      isCertName = false;
+      isIdentityName = true;
+    }
+  else if (vm.count("file"))
+    {
+      isCertName = false;
+      isFileName = true;
+    }    
+    
+  if (vm.count("pretty"))
+    isPretty = true;
+
+  if (vm.count("repo-output"))
+    {
+      isRepoOut = true;
+      isStdOut = false;
+    }
+  else if(vm.count("dns-output"))
+    {
+      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;
+    }
+
+  KeyChain keyChain;
+  ptr_lib::shared_ptr<IdentityCertificate> certificate;
+
+  try{
+    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(NULL == certificate)
+          {
+            std::cerr << "No certificate found!" << std::endl;
+            return 1;
+          }
+      }
+    else
+      {
+        certificate = getIdentityCertificate(name);
+        if(NULL == certificate)
+          {
+            std::cerr << "No certificate read!" << std::endl;
+            return 1;
+          }
+      }
+
+    if(isPretty)
+      {
+        std::cout << *certificate << std::endl;
+        // cout << "Certificate name: " << std::endl;
+        // cout << "  " << certificate->getName() << std::endl;
+        // cout << "Validity: " << std::endl;
+        // cout << "  NotBefore: " << boost::posix_time::to_simple_string(certificate->getNotBefore()) << std::endl;
+        // cout << "  NotAfter: " << boost::posix_time::to_simple_string(certificate->getNotAfter()) << std::endl;
+        // cout << "Subject Description: " << std::endl;
+        // const vector<CertificateSubjectDescription>& SubDescriptionList = certificate->getSubjectDescriptionList();
+        // vector<CertificateSubjectDescription>::const_iterator it = SubDescriptionList.begin();
+        // for(; it != SubDescriptionList.end(); it++)
+        //   cout << "  " << it->getOidStr() << ": " << it->getValue() << std::endl;
+        // cout << "Public key bits: " << std::endl;
+        // const Blob& keyBlob = certificate->getPublicKeygetKeyBlob();
+        // std::string encoded;
+        // CryptoPP::StringSource ss(reinterpret_cast<const unsigned char *>(keyBlob.buf()), keyBlob.size(), true,
+        //                           new CryptoPP::Base64Encoder(new CryptoPP::StringSink(encoded), true, 64));
+        // cout << encoded;        
+      }
+    else
+      {
+        if(isStdOut)
+          {
+            CryptoPP::StringSource ss(certificate->wireEncode().wire(), certificate->wireEncode().size(),
+                                      true,
+                                      new CryptoPP::Base64Encoder(new CryptoPP::FileSink(std::cout), true, 64));
+            return 0;
+          }
+        if(isRepoOut)
+          {
+            using namespace boost::asio::ip;
+            tcp::iostream request_stream;
+#if (BOOST_VERSION >= 104700)
+            request_stream.expires_from_now(boost::posix_time::milliseconds(3000));
+#endif
+            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;
+          }
+      }
+  }
+  catch(std::exception & e){
+    std::cerr << e.what() << std::endl;
+    return 1;
+  }
+  return 0;
+}
diff --git a/tools/ndnsec-get-default.cpp b/tools/ndnsec-get-default.cpp
new file mode 100644
index 0000000..d263d2b
--- /dev/null
+++ b/tools/ndnsec-get-default.cpp
@@ -0,0 +1,126 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#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 <cryptopp/base64.h>
+
+#include "security/key-chain.hpp"
+
+using namespace ndn;
+namespace po = boost::program_options;
+
+int main(int argc, char** argv)	
+{
+  bool getDefaultId = true;
+  bool getDefaultKey = false;
+  bool getDefaultCert = false;
+  bool quiet = false;
+  std::string idName;
+  std::string keyName;
+
+  po::options_description desc("General Usage\n  ndn-get-default [-h] [-K|C] [-i identity|-k key]\nGeneral options");
+  desc.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>(&idName), "target identity")
+    ("key,k", po::value<std::string>(&keyName), "target key")
+    ("quiet,q", "don't output trailing newline")
+    ;
+
+  po::variables_map vm;
+  po::store(po::parse_command_line(argc, argv, desc), vm);
+  po::notify(vm);
+
+  if (vm.count("help")) 
+    {
+      std::cerr << desc << std::endl;;
+      return 1;
+    }
+
+  if(vm.count("default_cert"))
+    {
+      getDefaultCert = true;
+      getDefaultId = false;
+    }
+  else if(vm.count("default_key"))
+    {
+      getDefaultKey = true;
+      getDefaultId = false;
+    }
+
+  if(vm.count("quiet"))
+    {
+      quiet = true;
+    }
+  
+  KeyChain keyChain;
+  bool ok = false;
+
+  if(vm.count("key"))
+    {
+      Name keyNdnName(keyName);
+      if(getDefaultCert)
+	{
+	  std::cout << keyChain.getDefaultCertificateNameForKey(keyNdnName);
+          if (!quiet) std::cout << std::endl;
+	  return 0;
+	}
+      return 1;
+    }
+  else if(vm.count("identity"))
+    {
+      Name idNdnName(idName);
+
+      if(getDefaultKey)
+	{
+	  std::cout << keyChain.getDefaultKeyNameForIdentity(idNdnName);
+          if (!quiet) std::cout << std::endl;
+	  return 0;
+	}
+      if(getDefaultCert)
+	{
+	  std::cout << keyChain.getDefaultCertificateNameForIdentity(idNdnName);
+          if (!quiet) std::cout << std::endl;
+	  return 0;
+	}
+      return 1;
+    }
+  else
+    {
+      Name idNdnName = keyChain.getDefaultIdentity();
+      if(getDefaultId)
+	{
+	  std::cout << idNdnName;
+          if (!quiet) std::cout << std::endl;
+	  return 0;
+	}
+      if(getDefaultKey)
+	{
+	  std::cout << keyChain.getDefaultKeyNameForIdentity(idNdnName);
+          if (!quiet) std::cout << std::endl;
+	  return 0;
+	}
+      if(getDefaultCert)
+	{
+	  std::cout << keyChain.getDefaultCertificateNameForIdentity(idNdnName);
+          if (!quiet) std::cout << std::endl;
+	  return 0;
+	}
+    }
+
+
+}
diff --git a/tools/ndnsec-install-cert.cpp b/tools/ndnsec-install-cert.cpp
new file mode 100644
index 0000000..4bcd4a2
--- /dev/null
+++ b/tools/ndnsec-install-cert.cpp
@@ -0,0 +1,261 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#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/asio.hpp>
+
+#include <cryptopp/base64.h>
+#include <cryptopp/files.h>
+
+#include "security/key-chain.hpp"
+
+using namespace std;
+using namespace ndn;
+namespace po = boost::program_options;
+
+ptr_lib::shared_ptr<IdentityCertificate>
+getCertificate(const string& fileName)
+{
+  istream* ifs;
+  if(fileName == string("-"))
+    ifs = &cin;
+  else
+    ifs = new ifstream(fileName.c_str());
+
+  string decoded;
+  CryptoPP::FileSource ss2(*ifs, true,
+                           new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
+
+  ptr_lib::shared_ptr<IdentityCertificate> identityCertificate = ptr_lib::make_shared<IdentityCertificate>();
+  identityCertificate->wireDecode(Block(decoded.c_str(), decoded.size()));
+
+  return identityCertificate;
+}
+
+struct HttpException : public std::exception
+{
+  HttpException(const std::string &reason)
+    : m_reason(reason)
+  {
+  }
+  ~HttpException() throw()
+  {
+  }
+
+  const char* what() const throw()
+  {
+    return m_reason.c_str();
+  }
+
+private:
+  std::string m_reason;
+};
+
+ptr_lib::shared_ptr<IdentityCertificate>
+getCertificateHttp(const std::string &host, const std::string &port, const std::string &path)
+{
+  using namespace boost::asio::ip;
+  tcp::iostream request_stream;
+#if (BOOST_VERSION >= 104700)
+  request_stream.expires_from_now(boost::posix_time::milliseconds(3000));
+#endif
+  request_stream.connect(host,port);
+  if(!request_stream)
+    {
+      throw HttpException("HTTP connection error");
+    }
+  request_stream << "GET " << path << " HTTP/1.0\r\n";
+  request_stream << "Host: " << host << "\r\n";
+  request_stream << "Accept: */*\r\n";
+  request_stream << "Cache-Control: no-cache\r\n";
+  request_stream << "Connection: close\r\n\r\n";
+  request_stream.flush();
+
+  std::string line1;
+  std::getline(request_stream,line1);
+  if (!request_stream)
+    {
+      throw HttpException("HTTP communication error");
+    }
+
+  std::stringstream response_stream(line1);
+  std::string http_version;
+  response_stream >> http_version;
+  unsigned int status_code;
+  response_stream >> status_code;
+  std::string status_message;
+
+  std::getline(response_stream,status_message);
+  if (!response_stream || http_version.substr(0,5)!="HTTP/")
+    {
+      throw HttpException("HTTP communication error");
+    }
+  if (status_code!=200)
+    {
+      throw HttpException("HTTP server error");
+    }
+  std::string header;
+  while (std::getline(request_stream, header) && header != "\r") ;
+
+
+  string decoded;
+  CryptoPP::FileSource ss2(request_stream, true,
+                           new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
+
+  ptr_lib::shared_ptr<IdentityCertificate> identityCertificate = ptr_lib::make_shared<IdentityCertificate>();
+  identityCertificate->wireDecode(Block(decoded.c_str(), decoded.size()));
+
+  return identityCertificate;
+}
+
+int main(int argc, char** argv)
+{
+  string certFileName;
+  bool systemDefault = true;
+  bool identityDefault = false;
+  bool keyDefault = false;
+  bool noDefault = false;
+  bool any = false;
+
+  po::options_description desc("General Usage\n  ndn-install-cert [-h] [-I|K|N] cert-file\nGeneral options");
+  desc.add_options()
+    ("help,h", "produce help message")
+    ("cert-file,f", po::value<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(desc).positional(p).run(), vm);
+      po::notify(vm);
+    }
+  catch (exception &e)
+    {
+      cerr << "ERROR: " << e.what() << endl;
+      return 1;
+    }
+
+  if (vm.count("help"))
+    {
+      cerr << desc << endl;
+      return 1;
+    }
+
+  if (0 == vm.count("cert-file"))
+    {
+      cerr << "cert_file must be specified" << endl;
+      cerr << desc << endl;
+      return 1;
+    }
+
+  if (vm.count("identity-default"))
+    {
+      identityDefault = true;
+      systemDefault = false;
+    }
+  else if (vm.count("key-default"))
+    {
+      keyDefault = true;
+      systemDefault = false;
+    }
+  else if (vm.count("no-default"))
+    {
+      noDefault = true;
+      systemDefault = false;
+    }
+
+  try
+    {
+      ptr_lib::shared_ptr<IdentityCertificate> cert;
+
+      if(certFileName.find("http://") == 0)
+        {
+          string host;
+          string port;
+          string path;
+
+          size_t pos = 7;
+          size_t posSlash = certFileName.find ("/", pos);
+
+          if (posSlash == string::npos)
+            throw HttpException("Request line is not correctly formatted");
+
+          size_t posPort = certFileName.find (":", pos);
+
+          if (posPort != 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 = getCertificate(certFileName);
+        }
+
+      KeyChain keyChain;
+
+      if(systemDefault)
+        {
+          keyChain.addCertificateAsIdentityDefault(*cert);
+          Name keyName = cert->getPublicKeyName();
+          Name identity = keyName.getSubName(0, keyName.size()-1);
+          keyChain.setDefaultIdentity(identity);
+        }
+      else if(identityDefault)
+        {
+          keyChain.addCertificateAsIdentityDefault(*cert);
+        }
+      else if(keyDefault)
+        {
+          keyChain.addCertificateAsKeyDefault(*cert);
+        }
+      else
+        {
+          keyChain.addCertificate(*cert);
+        }
+
+      cout << "OK: certificate with name [" << cert->getName().toUri() << "] has been successfully installed" << endl;
+
+      return 0;
+    }
+  catch(std::exception &e)
+    {
+      cerr << "ERROR: " << e.what() << endl;
+      return 1;
+    }
+  catch(...)
+    {
+      cerr << "ERROR: unknown error" << endl;
+      return 1;
+    }
+}
diff --git a/tools/ndnsec-keygen.cpp b/tools/ndnsec-keygen.cpp
new file mode 100644
index 0000000..48646d1
--- /dev/null
+++ b/tools/ndnsec-keygen.cpp
@@ -0,0 +1,121 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+
+#include <cryptopp/base64.h>
+#include <cryptopp/files.h>
+
+#include "security/key-chain.hpp"
+
+using namespace std;
+using namespace ndn;
+namespace po = boost::program_options;
+
+
+int main(int argc, char** argv)	
+{
+  string identityName;
+  bool dskFlag = false;
+  bool notDefault = false;
+  char keyType = 'r';
+  int keySize = 2048;
+  string outputFilename;
+
+  // po::options_description desc("General Usage\n  ndn-keygen [-h] [-d] [-i] [-t type] [-s size] identity\nGeneral options");
+  po::options_description desc("General Usage\n  ndn-keygen [-h] [-i] identity\nGeneral options");
+  desc.add_options()
+    ("help,h", "produce help message")
+    ("identity_name,n", po::value<string>(&identityName), "identity name, for example, /ndn/ucla.edu/alice")
+    // ("dsk,d", "optional, if specified, a Data-Signing-Key will be created, otherwise create a Key-Signing-Key")
+    ("not_default,i", "optional, if not specified, the target identity will be set as the default identity of the system")
+    // ("type,t", po::value<char>(&keyType)->default_value('r'), "optional, key type, r for RSA key (default)")
+    // ("size,s", po::value<int>(&keySize)->default_value(2048), "optional, key size, 2048 (default)")
+    ;
+
+  po::positional_options_description p;
+  p.add("identity_name", 1);
+  
+  po::variables_map vm;
+  po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
+  po::notify(vm);
+
+  if (vm.count("help")) 
+    {
+      cerr << desc << endl;
+      return 1;
+    }
+
+  if (0 == vm.count("identity_name"))
+    {
+      cerr << "identity_name must be specified" << endl;
+      cerr << desc << endl;
+      return 1;
+    }
+
+  // if (vm.count("dsk")) 
+  //   dskFlag =  true;
+  
+  if (vm.count("not_default"))
+    notDefault = true;
+
+  KeyChain keyChain;
+
+  // if (vm.count("type")) 
+  if (true)
+    {
+      switch(keyType)
+      {
+      case 'r':
+        {
+          try
+            {
+              Name keyName = keyChain.generateRSAKeyPair(Name(identityName), !dskFlag, keySize);            
+
+              if(0 == keyName.size())
+                {                  
+                  return 1;
+                }
+
+              keyChain.setDefaultKeyNameForIdentity(keyName);
+            
+              ptr_lib::shared_ptr<IdentityCertificate> idcert = keyChain.selfSign(keyName);
+
+              if(!notDefault)
+                {
+                  keyChain.setDefaultIdentity(Name(identityName));
+                }
+              
+              CryptoPP::StringSource ss(idcert->wireEncode().wire(), 
+                                        idcert->wireEncode().size(), 
+                                        true,
+                                        new CryptoPP::Base64Encoder(new CryptoPP::FileSink(cout), true, 64));
+              return 0;
+            }
+          catch(std::exception &e)
+            {
+              cerr << "ERROR: " << e.what() << endl;
+              return 1;
+            }
+        }
+      default:
+        cerr << "Unrecongized key type" << "\n";
+        cerr << desc << endl;
+        return 1;
+      }
+    }
+
+  return 0;
+}
diff --git a/tools/ndnsec-ls-identity.cpp b/tools/ndnsec-ls-identity.cpp
new file mode 100644
index 0000000..8570156
--- /dev/null
+++ b/tools/ndnsec-ls-identity.cpp
@@ -0,0 +1,185 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#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 <cryptopp/base64.h>
+
+#include "security/key-chain.hpp"
+
+using namespace std;
+using namespace ndn;
+namespace po = boost::program_options;
+
+int main(int argc, char** argv)	
+{
+  bool getId = true;
+  bool getKey = false;
+  bool getCert = false;
+
+  po::options_description desc("General Usage\n  ndn-ls-identity [-h] [-K|C]\nGeneral options");
+  desc.add_options()
+    ("help,h", "produce help message")
+    ("key,K", "granularity: key")
+    ("cert,C", "granularity: certificate")
+    ;
+
+  po::variables_map vm;
+  po::store(po::parse_command_line(argc, argv, desc), vm);
+  po::notify(vm);
+
+  if (vm.count("help")) 
+    {
+      cerr << desc << endl;;
+      return 1;
+    }
+
+  if(vm.count("cert"))
+    {
+      getCert = true;
+      getId = false;
+    }
+  else if(vm.count("key"))
+    {
+      getKey = true;
+      getId = false;
+    }
+
+  KeyChain keyChain;
+
+  if(getId)
+    {
+      vector<Name> defaultList;
+      keyChain.getAllIdentities(defaultList, true);
+      for(int i = 0; i < defaultList.size(); i++)
+	cout << "* " << defaultList[i] << endl;
+      vector<Name> otherList;
+      keyChain.getAllIdentities(otherList, false);
+      for(int i = 0; i < otherList.size(); i++)
+	cout << "  " << otherList[i] << endl;
+      return 0;
+    }
+  if(getKey)
+    {
+      vector<Name> defaultIdList;
+      keyChain.getAllIdentities(defaultIdList, true);
+      for(int i = 0; i < defaultIdList.size(); i++)
+        {
+          cout << "* " << defaultIdList[i] << endl;
+          vector<Name> defaultKeyList;
+          keyChain.getAllKeyNamesOfIdentity(defaultIdList[i], defaultKeyList, true);
+          for(int j = 0; j < defaultKeyList.size(); j++)
+            cout << "  +->* " << defaultKeyList[j] << endl;
+          vector<Name> otherKeyList;
+          keyChain.getAllKeyNamesOfIdentity(defaultIdList[i], otherKeyList, false);
+          for(int j = 0; j < otherKeyList.size(); j++)
+            cout << "  +->  " << otherKeyList[j] << endl;
+          cout << endl;
+        }
+      vector<Name> otherIdList;
+      keyChain.getAllIdentities(otherIdList, false);
+      for(int i = 0; i < otherIdList.size(); i++)
+        {
+          cout << "  " << otherIdList[i] << endl;
+          vector<Name> defaultKeyList;
+          keyChain.getAllKeyNamesOfIdentity(otherIdList[i], defaultKeyList, true);
+          for(int j = 0; j < defaultKeyList.size(); j++)
+            cout << "  +->* " << defaultKeyList[j] << endl;
+          vector<Name> otherKeyList;
+          keyChain.getAllKeyNamesOfIdentity(otherIdList[i], otherKeyList, false);
+          for(int j = 0; j < otherKeyList.size(); j++)
+            cout << "  +->  " << otherKeyList[j] << endl;
+          cout << endl;
+        }
+      return 0;
+    }
+  if(getCert)
+    {
+      vector<Name> defaultIdList;
+      keyChain.getAllIdentities(defaultIdList, true);
+      for(int i = 0; i < defaultIdList.size(); i++)
+        {
+          cout << "* " << defaultIdList[i] << endl;
+          vector<Name> defaultKeyList;
+          keyChain.getAllKeyNamesOfIdentity(defaultIdList[i], defaultKeyList, true);
+          for(int j = 0; j < defaultKeyList.size(); j++)
+            {
+              cout << "  +->* " << defaultKeyList[j] << endl;
+              vector<Name> defaultCertList;
+              keyChain.getAllCertificateNamesOfKey(defaultKeyList[j], defaultCertList, true);
+              for(int k = 0; k < defaultCertList.size(); k++)
+                  cout << "       +->* " << defaultCertList[k] << endl;
+              vector<Name> otherCertList;
+              keyChain.getAllCertificateNamesOfKey(defaultKeyList[j], otherCertList, false);
+              for(int k = 0; k < otherCertList.size(); k++)
+                  cout << "       +->  " << otherCertList[k] << endl;
+            }
+          vector<Name> otherKeyList;
+          keyChain.getAllKeyNamesOfIdentity(defaultIdList[i], otherKeyList, false);
+          for(int j = 0; j < otherKeyList.size(); j++)
+            {
+              cout << "  +->  " << otherKeyList[j] << endl;
+              vector<Name> defaultCertList;
+              keyChain.getAllCertificateNamesOfKey(otherKeyList[j], defaultCertList, true);
+              for(int k = 0; k < defaultCertList.size(); k++)
+                  cout << "       +->* " << defaultCertList[k] << endl;
+              vector<Name> otherCertList;
+              keyChain.getAllCertificateNamesOfKey(otherKeyList[j], otherCertList, false);
+              for(int k = 0; k < otherCertList.size(); k++)
+                  cout << "       +->  " << otherCertList[k] << endl;
+            }
+
+          cout << endl;
+        }
+      vector<Name> otherIdList;
+      keyChain.getAllIdentities(otherIdList, false);
+      for(int i = 0; i < otherIdList.size(); i++)
+        {
+          cout << "  " << otherIdList[i] << endl;
+          vector<Name> defaultKeyList;
+          keyChain.getAllKeyNamesOfIdentity(otherIdList[i], defaultKeyList, true);
+          for(int j = 0; j < defaultKeyList.size(); j++)
+            {
+              cout << "  +->* " << defaultKeyList[j] << endl;
+              vector<Name> defaultCertList;
+              keyChain.getAllCertificateNamesOfKey(defaultKeyList[j], defaultCertList, true);
+              for(int k = 0; k < defaultCertList.size(); k++)
+                  cout << "       +->* " << defaultCertList[k] << endl;
+              vector<Name> otherCertList;
+              keyChain.getAllCertificateNamesOfKey(defaultKeyList[j], otherCertList, false);
+              for(int k = 0; k < otherCertList.size(); k++)
+                  cout << "       +->  " << otherCertList[k] << endl;
+            }
+          vector<Name> otherKeyList;
+          keyChain.getAllKeyNamesOfIdentity(otherIdList[i], otherKeyList, false);
+          for(int j = 0; j < otherKeyList.size(); j++)
+            {
+              cout << "  +->  " << otherKeyList[j] << endl;
+              vector<Name> defaultCertList;
+              keyChain.getAllCertificateNamesOfKey(otherKeyList[j], defaultCertList, true);
+              for(int k = 0; k < defaultCertList.size(); k++)
+                  cout << "       +->* " << defaultCertList[k] << endl;
+              vector<Name> otherCertList;
+              keyChain.getAllCertificateNamesOfKey(otherKeyList[j], otherCertList, false);
+              for(int k = 0; k < otherCertList.size(); k++)
+                  cout << "       +->  " << otherCertList[k] << endl;
+            }
+
+          cout << endl;
+        }
+      return 0;
+    }
+  return 1;
+}
diff --git a/tools/ndnsec-operator-tool.cpp b/tools/ndnsec-operator-tool.cpp
new file mode 100644
index 0000000..942570e
--- /dev/null
+++ b/tools/ndnsec-operator-tool.cpp
@@ -0,0 +1,98 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#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/regex.hpp>
+#include <boost/exception/all.hpp>
+
+#include "security/key-chain.hpp"
+#include "security/signature-sha256-with-rsa.hpp"
+
+using namespace std;
+using namespace ndn;
+namespace po = boost::program_options;
+
+int main(int argc, char** argv)
+{
+  string command;
+  
+  po::options_description desc("General options");
+  desc.add_options()
+    ("help,h", "produce this help message")
+    ("command", po::value<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(desc).positional(p).run(), vm);
+      po::notify(vm);
+    }
+  catch(std::exception &e)
+    {
+      cerr << "ERROR: " << e.what() << endl;
+      return -1;
+    }
+    
+  if (vm.count("help"))
+    {
+      cout << desc << "\n";
+      return 1;
+    }
+  
+  if (0 == vm.count("command"))
+    {
+      cerr << "command must be specified" << endl;
+      cerr << desc << endl;
+      return 1;
+    }
+
+  if (command == "sign") // the content to be signed from stdin
+    {
+      KeyChain keyChain;
+
+      try
+        {
+          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)
+            {
+              cerr << "Error signing with default key" << endl;
+              return -1;
+            }
+
+          cout.write(reinterpret_cast<const char*>(signature.getValue().wire()), signature.getValue().size());
+        }
+      catch (boost::exception &e)
+        {
+          std::cerr << "ERROR: " << boost::diagnostic_information (e) << std::endl;
+          return -1;
+        }
+      catch(std::exception &e)
+        {
+          cerr << "ERROR: " << e.what() << endl;
+          return -1;
+        }
+    }
+
+  return 0;
+}
diff --git a/tools/ndnsec-set-default.cpp b/tools/ndnsec-set-default.cpp
new file mode 100644
index 0000000..873b15a
--- /dev/null
+++ b/tools/ndnsec-set-default.cpp
@@ -0,0 +1,85 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#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 <cryptopp/base64.h>
+
+#include "security/key-chain.hpp"
+
+using namespace ndn;
+namespace po = boost::program_options;
+
+int main(int argc, char** argv)	
+{
+  std::string certFileName;
+  bool setDefaultId = true;
+  bool setDefaultKey = false;
+  bool setDefaultCert = false;
+  std::string name;
+
+  po::options_description desc("General Usage\n  ndn-set-default [-h] [-K|C] name\nGeneral options");
+  desc.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;
+  po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
+
+  po::notify(vm);
+
+  if (vm.count("help")) 
+    {
+      std::cerr << desc << std::endl;
+      return 1;
+    }
+
+  KeyChain keyChain;
+
+  if (vm.count("default_key"))
+    {
+      setDefaultKey = true;
+      setDefaultId = false;
+    }
+  else if(vm.count("default_cert"))
+    {
+      setDefaultCert = true;
+      setDefaultId = false;
+    }
+
+  if (setDefaultId)
+    {
+      Name idName(name);
+      keyChain.setDefaultIdentity(idName);
+      return 0;
+    }
+  if (setDefaultKey)
+    {
+      Name keyName(name);
+      keyChain.setDefaultKeyNameForIdentity(keyName);
+      return 0;
+    }
+  
+  if (setDefaultCert)
+    {
+      keyChain.setDefaultCertificateNameForKey(name);
+      return 0;
+    }
+}
diff --git a/tools/ndnsec-sig-verify.cpp b/tools/ndnsec-sig-verify.cpp
new file mode 100644
index 0000000..a6b1b85
--- /dev/null
+++ b/tools/ndnsec-sig-verify.cpp
@@ -0,0 +1,117 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+
+#include <cryptopp/base64.h>
+#include <cryptopp/files.h>
+
+#include "security/key-chain.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>(boost::cref(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(ptr_lib::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
+  //     ptr_lib::shared_ptr<Blob> input = ptr_lib::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 main(int argc, char** argv)	
+{
+  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;
+    }
+}
diff --git a/tools/ndnsec-sign-req.cpp b/tools/ndnsec-sign-req.cpp
new file mode 100644
index 0000000..6aef0b8
--- /dev/null
+++ b/tools/ndnsec-sign-req.cpp
@@ -0,0 +1,93 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <cryptopp/base64.h>
+#include <cryptopp/files.h>
+
+#include "security/key-chain.hpp"
+
+using namespace ndn;
+namespace po = boost::program_options;
+
+
+int main(int argc, char** argv)	
+{
+  std::string name;
+  bool isKeyName = false;
+
+  po::options_description desc("General Usage\n  ndn-sign-req [-h] [-k] name\nGeneral options");
+  desc.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(desc).positional(p).run(), vm);
+    po::notify(vm);
+  }
+  catch(const std::exception &e) {
+    std::cerr << "ERROR: " << e.what() << std::endl;
+    std::cerr << desc << std::endl;
+    return 1;
+  }
+
+  if (vm.count("help")) 
+    {
+      std::cerr << desc << std::endl;
+      return 1;
+    }
+
+  if (0 == vm.count("name"))
+    {
+      std::cerr << "identity_name must be specified" << std::endl;
+      std::cerr << desc << std::endl;
+      return 1;
+    }
+  
+  if (vm.count("key"))
+    isKeyName = true;
+    
+  KeyChain keyChain;
+
+  try{
+    if(isKeyName)
+      {
+        shared_ptr<IdentityCertificate> selfSignCert = keyChain.selfSign(name);
+
+        CryptoPP::StringSource ss(selfSignCert->wireEncode().wire(), selfSignCert->wireEncode().size(), true,
+                              new CryptoPP::Base64Encoder(new CryptoPP::FileSink(std::cout), true, 64));
+      }
+    else
+      {
+        Name keyName = keyChain.getDefaultKeyNameForIdentity(name);
+        ptr_lib::shared_ptr<IdentityCertificate> selfSignCert = keyChain.selfSign(keyName);
+
+        CryptoPP::StringSource ss(selfSignCert->wireEncode().wire(), selfSignCert->wireEncode().size(), true,
+                              new CryptoPP::Base64Encoder(new CryptoPP::FileSink(std::cout), true, 64));
+      }
+  }
+  catch(std::exception & e)
+    {
+      std::cerr << "ERROR: " << e.what() << std::endl;
+      return 1;
+    }
+  return 0;
+}
diff --git a/wscript b/wscript
index daa09ee..682df49 100644
--- a/wscript
+++ b/wscript
@@ -21,6 +21,8 @@
                    help='''Use C++11 features, even if available in the compiler''')
     opt.add_option('--without-system-boost', action='store_false', default=True, dest='use_system_boost',
                    help='''Use system's boost libraries''')
+    opt.add_option('--without-tools', action='store_false', default=True, dest='with_tools',
+                   help='''Do not build tools''')
 
 
 def configure(conf):
@@ -33,6 +35,9 @@
     if conf.options.with_tests:
         conf.env['WITH_TESTS'] = True
 
+    if conf.options.with_tools:
+        conf.env['WITH_TOOLS'] = True
+
     conf.check_openssl()
 
     if conf.options.debug:
@@ -86,7 +91,7 @@
         conf.define('HAVE_CXX11', 1)
     else:
         if conf.options.use_system_boost:
-            USED_BOOST_LIBS = 'system filesystem date_time iostreams regex'
+            USED_BOOST_LIBS = 'system filesystem date_time iostreams regex program_options'
             if conf.env['WITH_TESTS']:
                 USED_BOOST_LIBS += " unit_test_framework"
 
@@ -162,7 +167,10 @@
     if bld.env['WITH_TESTS']:
         bld.recurse('tests')
 
-    bld.recurse("tools examples")
+    if bld.env['WITH_TOOLS']:
+        bld.recurse("tools examples")
+    else:
+        bld.recurse("examples")
       
     headers = bld.path.ant_glob(['src/**/*.hpp'])
     bld.install_files("%s/ndn-cpp-dev" % bld.env['INCLUDEDIR'], headers, relative_trick=True, cwd=bld.path.find_node('src'))