diff --git a/src/daemon/db-mgr.cpp b/src/daemon/db-mgr.cpp
index 35af5de..53d3822 100644
--- a/src/daemon/db-mgr.cpp
+++ b/src/daemon/db-mgr.cpp
@@ -174,6 +174,31 @@
   return zone.getId() != 0;
 }
 
+std::vector<Zone>
+DbMgr::listZones()
+{
+  sqlite3_stmt* stmt;
+  const char* sql = "SELECT id, name, ttl FROM zones";
+  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
+  if (rc != SQLITE_OK) {
+    throw PrepareError(sql);
+  }
+
+  std::vector<Zone> vec;
+
+  while (sqlite3_step(stmt) == SQLITE_ROW) {
+    vec.emplace_back();
+    Zone& zone = vec.back();
+    zone.setId(sqlite3_column_int64(stmt, 0));
+    zone.setTtl(time::seconds(sqlite3_column_int(stmt, 2)));
+    zone.setName(Name(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 1)),
+                            sqlite3_column_bytes(stmt, 1))));
+  }
+  sqlite3_finalize(stmt);
+
+  return vec;
+}
+
 void
 DbMgr::remove(Zone& zone)
 {
diff --git a/src/daemon/db-mgr.hpp b/src/daemon/db-mgr.hpp
index ca83691..336b330 100644
--- a/src/daemon/db-mgr.hpp
+++ b/src/daemon/db-mgr.hpp
@@ -113,6 +113,12 @@
   find(Zone& zone);
 
   /**
+   * @brief get all zones in the database
+   */
+  std::vector<Zone>
+  listZones();
+
+  /**
    * @brief remove the zone
    * @pre m_zone.getId() > 0
    * @post m_zone.getId() == 0
diff --git a/src/mgmt/management-tool.cpp b/src/mgmt/management-tool.cpp
new file mode 100644
index 0000000..619d1c0
--- /dev/null
+++ b/src/mgmt/management-tool.cpp
@@ -0,0 +1,642 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "management-tool.hpp"
+#include "logger.hpp"
+#include "ndns-label.hpp"
+#include "ndns-tlv.hpp"
+
+#include <string>
+#include <iomanip>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/util/regex.hpp>
+#include <ndn-cxx/encoding/oid.hpp>
+#include <ndn-cxx/security/cryptopp.hpp>
+
+namespace ndn {
+namespace ndns {
+
+NDNS_LOG_INIT("ManagementTool");
+
+ManagementTool::ManagementTool(const std::string& dbFile)
+  : m_dbMgr(dbFile)
+{
+}
+
+void
+ManagementTool::createZone(const Name &zoneName,
+                           const Name& parentZoneName,
+                           const time::seconds& cacheTtl,
+                           const time::seconds& certTtl,
+                           const Name& kskCertName,
+                           const Name& dskCertName)
+{
+  bool isRoot = zoneName == ROOT_ZONE;
+
+  //check preconditions
+  Zone zone(zoneName, cacheTtl);
+  if (m_dbMgr.find(zone)) {
+    throw Error(zoneName.toUri() + " is already presented in the NDNS db");
+  }
+
+  if (!isRoot && parentZoneName.equals(zoneName)) {
+    throw Error("Parent zone name can not be the zone itself");
+  }
+
+  if (!isRoot && !parentZoneName.isPrefixOf(zoneName)) {
+    throw Error(parentZoneName.toUri() + " is not a prefix of " + zoneName.toUri());
+  }
+
+  if (kskCertName != DEFAULT_CERT) {
+    if (!matchCertificate(kskCertName, zoneName)) {
+      throw Error("Cannot verify KSK certificate");
+    }
+  }
+
+  if (dskCertName != DEFAULT_CERT) {
+    if (!matchCertificate(dskCertName, zoneName)) {
+      throw Error("Cannot verify DSK certificate");
+    }
+  }
+
+  if (kskCertName == DEFAULT_CERT && isRoot) {
+    throw Error("Cannot generate KSK for root zone");
+  }
+
+  //first generate KSK and DSK to the keyChain system, and add DSK as default
+  NDNS_LOG_INFO("Start generating KSK and DSK and their corresponding certificates");
+  time::system_clock::TimePoint notBefore = time::system_clock::now();
+  time::system_clock::TimePoint notAfter = notBefore + certTtl;
+  shared_ptr<IdentityCertificate> kskCert;
+
+  if (kskCertName == DEFAULT_CERT) {
+    //create KSK's certificate
+    Name kskName = m_keyChain.generateRsaKeyPair(zoneName, true);
+    std::vector<CertificateSubjectDescription> kskDesc;
+    kskCert = m_keyChain.prepareUnsignedIdentityCertificate(kskName, zoneName, notBefore, notAfter,
+                                                            kskDesc);
+    //prepare the correct name for the ksk certificate
+    Name newScertName = parentZoneName;
+    newScertName.append(label::NDNS_CERT_QUERY);
+    newScertName.append(zoneName.getSubName(parentZoneName.size()));
+    //remove the zone prefix and KEY
+    newScertName.append(kskCert->getName().getSubName(zoneName.size()+1));
+    kskCert->setName(newScertName);
+
+    m_keyChain.selfSign(*kskCert);
+    m_keyChain.addCertificate(*kskCert);
+    NDNS_LOG_INFO("Generated KSK: " << kskCert->getName().toUri());
+  }
+  else {
+    kskCert = m_keyChain.getCertificate(kskCertName);
+  }
+
+  Name dskName;
+  shared_ptr<IdentityCertificate> dskCert;
+  if (dskCertName == DEFAULT_CERT) {
+    dskName = m_keyChain.generateRsaKeyPairAsDefault(zoneName, false);
+    //create DSK's certificate
+    std::vector<CertificateSubjectDescription> dskDesc;
+    dskCert = m_keyChain.prepareUnsignedIdentityCertificate(dskName, zoneName, notBefore, notAfter,
+                                                            dskDesc);
+    m_keyChain.sign(*dskCert, kskCert->getName());
+    m_keyChain.addCertificateAsKeyDefault(*dskCert);
+    NDNS_LOG_INFO("Generated DSK: " << dskCert->getName().toUri());
+  }
+  else {
+    dskCert = m_keyChain.getCertificate(dskCertName);
+    dskName = dskCert->getPublicKeyName();
+    m_keyChain.setDefaultKeyNameForIdentity(dskName);
+    m_keyChain.setDefaultCertificateNameForKey(dskCert->getName());
+  }
+
+  //second add zone to the database
+  NDNS_LOG_INFO("Start adding new zone to data base");
+  addZone(zone);
+
+  //third create ID-cert
+  NDNS_LOG_INFO("Start creating DSK's ID-CERT");
+  addIdCert(zone, dskCert, cacheTtl);
+}
+
+void
+ManagementTool::deleteZone(const Name& zoneName)
+{
+  //check pre-conditions
+  Zone zone(zoneName);
+  if (!m_dbMgr.find(zone)) {
+    throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+  }
+
+  //first remove all rrsets of this zone from local ndns database
+  std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
+  for (Rrset& rrset : rrsets) {
+    m_dbMgr.remove(rrset);
+  }
+
+  //second remove zone from local ndns database
+  removeZone(zone);
+
+  //third remove identity
+  m_keyChain.deleteIdentity(zoneName);
+}
+
+void
+ManagementTool::exportCertificate(const Name& certName, const std::string& outFile)
+{
+  //search for the certificate, start from KeyChain then local NDNS database
+  shared_ptr<IdentityCertificate> cert;
+  if (m_keyChain.doesCertificateExist(certName)) {
+    cert = m_keyChain.getCertificate(certName);
+  }
+  else {
+    shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
+    if (regex->match(certName) != true) {
+      throw Error("Certificate name is illegal");
+    }
+    Name zoneName = regex->expand("\\1");
+    Name label = regex->expand("\\2");
+
+    Zone zone(zoneName);
+    Rrset rrset(&zone);
+    rrset.setLabel(label);
+    rrset.setType(label::CERT_RR_TYPE);
+    if (m_dbMgr.find(rrset)) {
+      Data data(rrset.getData());
+      cert = make_shared<IdentityCertificate>(data);
+    }
+    else {
+      throw Error("Cannot find the cert: " + certName.toUri());
+    }
+  }
+
+  if (outFile == DEFAULT_IO) {
+    ndn::io::save(*cert, std::cout);
+  }
+  else {
+    ndn::io::save(*cert, outFile);
+    NDNS_LOG_INFO("save cert to file: " << outFile);
+  }
+}
+
+void
+ManagementTool::addRrSet(const Name& zoneName,
+                         const Name& label,
+                         const name::Component& type,
+                         NdnsType ndnsType,
+                         const uint64_t version,
+                         const std::vector<std::string>& contents,
+                         const Name& inputDskCertName,
+                         const time::seconds& ttl)
+{
+  // check pre-condition
+  Zone zone(zoneName);
+  if (!m_dbMgr.find(zone)) {
+    throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+  }
+
+  if (ndnsType == NDNS_UNKNOWN) {
+    throw Error("The ndns type is unknown");
+  }
+
+  if (type == label::CERT_RR_TYPE) {
+    throw Error("It cannot handle ID-CERT rrset type");
+  }
+
+  // check strange rr type and ndns type combination
+  if (type == label::NS_RR_TYPE && ndnsType == NDNS_RAW) {
+    throw Error("NS cannot be of the type NDNS_RAW");
+  }
+
+  if (type == label::TXT_RR_TYPE && ndnsType != NDNS_RESP) {
+    throw Error("TXT cannot be of the type NDNS_RAW or NDNS_AUTH");
+  }
+
+  if (ndnsType == NDNS_RAW && contents.size() != 1) {
+    throw Error("NDNS_RAW must contain a single content element");
+  }
+
+  Name dskName;
+  Name dskCertName = inputDskCertName;
+  if (dskCertName == DEFAULT_CERT) {
+    dskName = m_keyChain.getDefaultKeyNameForIdentity(zoneName);
+    dskCertName = m_keyChain.getDefaultCertificateNameForKey(dskName);
+  }
+  else {
+    if (!matchCertificate(dskCertName, zoneName)) {
+      throw Error("Cannot verify certificate");
+    }
+  }
+
+  // set rrset
+  Rrset rrset(&zone);
+  rrset.setLabel(label);
+  rrset.setType(type);
+  if (ttl == DEFAULT_RR_TTL)
+    rrset.setTtl(zone.getTtl());
+  else
+    rrset.setTtl(ttl);
+
+  // set response
+  Response re;
+  re.setZone(zoneName);
+  re.setQueryType(label::NDNS_ITERATIVE_QUERY);
+  re.setRrLabel(label);
+  re.setRrType(type);
+  re.setNdnsType(ndnsType);
+
+  //set content according to ndns type
+  if (ndnsType == NDNS_RAW) {
+    Block tmp = ndn::dataBlock(ndn::tlv::Content, contents[0].c_str(), contents[0].length());
+    re.setAppContent(tmp);
+  }
+  else if (ndnsType != NDNS_AUTH) {
+    if (contents.empty()) {
+      re.addRr("");
+    }
+    else {
+      for (const auto& item : contents) {
+        re.addRr(item);
+      }
+    }
+  }
+
+  shared_ptr<Data> data = re.toData();
+  if (version != VERSION_USE_UNIX_TIMESTAMP) {
+    name::Component tmp = name::Component::fromVersion(version);
+    re.setVersion(tmp);
+  }
+  m_keyChain.sign(*data, dskCertName);
+
+  rrset.setVersion(re.getVersion());
+  rrset.setData(data->wireEncode());
+
+  if (m_dbMgr.find(rrset)) {
+    throw Error("Rrset with label=" + label.toUri() + " is already in local NDNS databse");
+  }
+  NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
+                << type);
+  m_dbMgr.insert(rrset);
+}
+
+void
+ManagementTool::addRrSet(const Name& zoneName,
+                         const std::string& inFile,
+                         const time::seconds& ttl,
+                         const Name& inputDskCertName)
+{
+  //check precondition
+  Zone zone(zoneName);
+  if (!m_dbMgr.find(zone)) {
+    throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+  }
+
+  Name dskName;
+  Name dskCertName = inputDskCertName;
+  if (dskCertName == DEFAULT_CERT) {
+    dskName = m_keyChain.getDefaultKeyNameForIdentity(zoneName);
+    dskCertName = m_keyChain.getDefaultCertificateNameForKey(dskName);
+  }
+  else {
+    if (!matchCertificate(dskCertName, zoneName)) {
+      throw Error("Cannot verify certificate");
+    }
+  }
+
+  if (inFile != DEFAULT_IO) {
+    boost::filesystem::path dir = boost::filesystem::path(inFile);
+    if (!boost::filesystem::exists(dir) || boost::filesystem::is_directory(dir)) {
+      throw Error("Data: " + inFile + " does not exist");
+    }
+  }
+
+  //first load the data
+  shared_ptr<Data> data;
+  if (inFile == DEFAULT_IO)
+    data = ndn::io::load<ndn::Data>(std::cin);
+  else
+    data = ndn::io::load<ndn::Data>(inFile);
+
+  //determine whether the data is a self-signed certificate
+  shared_ptr<Regex> regex1 = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
+  if (regex1->match(data->getName())) {
+    IdentityCertificate scert(*data);
+    Name keyName = scert.getPublicKeyName();
+    Name keyLocator = scert.getSignature().getKeyLocator().getName();
+
+    //if it is, extract the content and name from the data, and resign it using the dsk.
+    shared_ptr<Regex> regex2 = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT>");
+    BOOST_VERIFY(regex2->match(keyLocator) == true);
+    if (keyName == regex2->expand("\\1\\2")) {
+      shared_ptr<Data> pre = data;
+      Name name = pre->getName();
+      //check whether the name is legal or not. if not converting it to a legal name
+      if (zoneName != regex1->expand("\\1")) {
+        Name comp1 = regex1->expand("\\1").getSubName(zoneName.size());
+        Name comp2 = regex1->expand("\\2");
+        name = zoneName;
+        name.append("KEY");
+        name.append(comp1);
+        name.append(comp2);
+        name.append("ID-CERT");
+        name.append(pre->getName().get(-1));
+      }
+
+      data = make_shared<Data>();
+      data->setName(name);
+      data->setContent(pre->getContent());
+
+      m_keyChain.sign(*data, dskCertName);
+    }
+  }
+
+  // create response for the input data
+  Response re;
+  Name hint;
+  re.fromData(hint, zoneName, *data);
+  Name label = re.getRrLabel();
+  name::Component type = re.getRrType();
+
+  Rrset rrset(&zone);
+  rrset.setLabel(label);
+  rrset.setType(type);
+  if (ttl == DEFAULT_RR_TTL)
+    rrset.setTtl(zone.getTtl());
+  else
+    rrset.setTtl(ttl);
+  rrset.setVersion(re.getVersion());
+  rrset.setData(data->wireEncode());
+
+  if (m_dbMgr.find(rrset)) {
+    throw Error("Rrset with label=" + label.toUri() + " is already in local NDNS databse");
+  }
+  NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
+                << type);
+  m_dbMgr.insert(rrset);
+}
+
+void
+ManagementTool::listZone(const Name& zoneName, std::ostream& os, const bool printRaw) {
+  Zone zone(zoneName);
+  if (!m_dbMgr.find(zone)) {
+    os << "No record is found" << std::endl;
+    return;
+  }
+
+  //first output the zone name
+  os << "; Zone " << zoneName.toUri() << std::endl << std::endl;
+
+  //second output all rrsets
+  std::vector<Rrset> rrsets = m_dbMgr.findRrsets(zone);
+
+  //set width for different columns
+  size_t labelWidth = 0;
+  size_t ttlWidth = 0;
+  size_t typeWidth = 0;
+  for (Rrset& rrset : rrsets) {
+    Data data(rrset.getData());
+    Response re;
+    Name hint;
+    re.fromData(hint, zoneName, data);
+
+    if (rrset.getLabel().toUri().size() > labelWidth)
+      labelWidth = rrset.getLabel().toUri().size();
+
+    std::stringstream seconds;
+    seconds << rrset.getTtl().count();
+    if (seconds.str().size() > ttlWidth)
+      ttlWidth = seconds.str().size();
+
+    if (rrset.getType().toUri().size() > typeWidth)
+      typeWidth = rrset.getType().toUri().size();
+  }
+
+  //output
+  for (Rrset& rrset : rrsets) {
+    Data data(rrset.getData());
+    Response re;
+    Name hint;
+    re.fromData(hint, zoneName, data);
+    int iteration = re.getNdnsType() == NDNS_RAW || re.getNdnsType() == NDNS_AUTH ?
+                      1 : re.getRrs().size();
+    const std::vector<Block> &rrs = re.getRrs();
+
+    if (re.getNdnsType() != NDNS_RAW && re.getNdnsType() != NDNS_AUTH) {
+      os << "; rrset=" << rrset.getLabel().toUri()
+         << " type=" << rrset.getType().toUri()
+         << " version=" << rrset.getVersion().toUri()
+         << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri()
+         << std::endl;
+    }
+
+    for (int i = 0; i < iteration; i++) {
+      os.setf(os.left);
+      os.width(labelWidth + 2);
+      os << rrset.getLabel().toUri();
+
+      os.width(ttlWidth + 2);
+      os << rrset.getTtl().count();
+
+      os.width(typeWidth + 2);
+      os << rrset.getType().toUri();
+
+      if (re.getNdnsType() != NDNS_RAW && re.getNdnsType() != NDNS_AUTH) {
+        using namespace CryptoPP;
+        if (rrset.getType() == label::TXT_RR_TYPE) {
+          os.write(reinterpret_cast<const char*>(rrs[i].value()), rrs[i].value_size());
+          os << std::endl;
+        }
+        else if (rrset.getType() == label::NS_RR_TYPE) {
+          //TODO output the NS data once we have it
+          os << std::endl;
+        }
+        else {
+          StringSource ss(rrs[i].wire(), rrs[i].size(), true,
+                          new Base64Encoder(new FileSink(os), true, 64));
+        }
+      }
+    }
+
+    if (re.getNdnsType() == NDNS_RAW || re.getNdnsType() == NDNS_AUTH) {
+      os.width();
+      os << "; content-type=" << re.getNdnsType()
+         << " version=" << rrset.getVersion().toUri()
+         << " signed-by=" << data.getSignature().getKeyLocator().getName().toUri();
+      os << std::endl;
+
+      if (printRaw && re.getNdnsType() == NDNS_RAW) {
+        using namespace CryptoPP;
+        std::stringstream sstream;
+        StringSource ss(re.getAppContent().wire(), re.getAppContent().size(), true,
+                        new Base64Encoder(new FileSink(sstream), true, 64));
+
+        std::string content = sstream.str();
+        std::string delimiter = "\n";
+        size_t pos = 0;
+        std::string token;
+        while ((pos = content.find(delimiter)) != std::string::npos) {
+            token = content.substr(0, pos);
+            os << "; " << token << std::endl;
+            content.erase(0, pos + delimiter.length());
+        }
+
+        os << std::endl;
+      }
+    }
+    else {
+      os << std::endl;
+    }
+  }
+}
+
+void
+ManagementTool::listAllZones(std::ostream& os) {
+  std::vector<Zone> zones = m_dbMgr.listZones();
+
+  size_t nameWidth = 0;
+  for (const Zone& zone : zones) {
+    if (zone.getName().toUri().size() > nameWidth)
+      nameWidth = zone.getName().toUri().size();
+  }
+
+  for (const Zone& zone : zones) {
+    os.setf(os.left);
+    os.width(nameWidth + 2);
+    os << zone.getName().toUri();
+
+    os << "; default-ttl=" << zone.getTtl().count();
+    os << " default-key=" << m_keyChain.getDefaultKeyNameForIdentity(zone.getName());
+    os << " default-certificate="
+       << m_keyChain.getDefaultCertificateNameForIdentity(zone.getName());
+    os << std::endl;
+  }
+}
+
+void
+ManagementTool::removeRrSet(const Name& zoneName, const Name& label, const name::Component& type)
+{
+  Zone zone(zoneName);
+  Rrset rrset(&zone);
+  rrset.setLabel(label);
+  rrset.setType(type);
+
+  if (!m_dbMgr.find(rrset)) {
+    return;
+  }
+  NDNS_LOG_INFO("Remove rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
+                << type);
+  m_dbMgr.remove(rrset);
+}
+
+void
+ManagementTool::getRrSet(const Name& zoneName,
+                         const Name& label,
+                         const name::Component& type,
+                         std::ostream& os)
+{
+  Zone zone(zoneName);
+  Rrset rrset(&zone);
+  rrset.setLabel(label);
+  rrset.setType(type);
+
+  if (!m_dbMgr.find(rrset)) {
+    os << "No record is found" << std::endl;
+    return;
+  }
+
+  using namespace CryptoPP;
+  StringSource ss(rrset.getData().wire(), rrset.getData().size(), true,
+                  new Base64Encoder(new FileSink(os), true, 64));
+}
+
+void
+ManagementTool::addIdCert(Zone& zone, shared_ptr<IdentityCertificate> cert,
+                          const time::seconds& ttl)
+{
+  Rrset rrset(&zone);
+  size_t size = zone.getName().size();
+  Name label = cert->getName().getSubName(size + 1, cert->getName().size() - size - 3);
+  rrset.setLabel(label);
+  rrset.setType(label::CERT_RR_TYPE);
+  rrset.setTtl(ttl);
+  rrset.setVersion(cert->getName().get(-1));
+  rrset.setData(cert->wireEncode());
+
+  if (m_dbMgr.find(rrset)) {
+    throw Error("ID-CERT with label=" + label.toUri() +
+                " is already presented in local NDNS databse");
+  }
+  NDNS_LOG_INFO("Add rrset with zone-id: " << zone.getId() << " label: " << label << " type: "
+                << label::CERT_RR_TYPE);
+  m_dbMgr.insert(rrset);
+}
+
+void
+ManagementTool::addZone(Zone& zone)
+{
+  if (m_dbMgr.find(zone)) {
+    throw Error("Zone with Name=" + zone.getName().toUri() +
+                " is already presented in local NDNS databse");
+  }
+  NDNS_LOG_INFO("Add zone with Name: " << zone.getName().toUri());
+  m_dbMgr.insert(zone);
+}
+
+void
+ManagementTool::removeZone(Zone& zone)
+{
+  if (!m_dbMgr.find(zone)) {
+    return;
+  }
+  NDNS_LOG_INFO("Remove zone with Name: " << zone.getName().toUri());
+  m_dbMgr.remove(zone);
+}
+
+bool
+ManagementTool::matchCertificate(const Name& certName, const Name& identity)
+{
+  if (!m_keyChain.doesCertificateExist(certName)) {
+    NDNS_LOG_WARN(certName.toUri() << " is not presented in KeyChain");
+    return false;
+  }
+
+  //check its public key information
+  shared_ptr<IdentityCertificate> cert = m_keyChain.getCertificate(certName);
+  Name keyName = cert->getPublicKeyName();
+
+  if (!identity.isPrefixOf(keyName) || identity.size()!=keyName.size()-1) {
+    NDNS_LOG_WARN(keyName.toUri() << " is not a key of " << identity.toUri());
+    return false;
+  }
+
+  if (!m_keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE)) {
+    NDNS_LOG_WARN("Private key: " << keyName.toUri() << " is not presented in KeyChain");
+    return false;
+  }
+
+  return true;
+}
+
+} // namespace ndns
+} // namespace ndn
diff --git a/src/mgmt/management-tool.hpp b/src/mgmt/management-tool.hpp
new file mode 100644
index 0000000..f962b11
--- /dev/null
+++ b/src/mgmt/management-tool.hpp
@@ -0,0 +1,233 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NDNS_MGMT_MANAGEMENT_TOOL_HPP
+#define NDNS_MGMT_MANAGEMENT_TOOL_HPP
+
+#include "config.hpp"
+#include "ndns-enum.hpp"
+#include "./daemon/zone.hpp"
+#include "./daemon/db-mgr.hpp"
+#include "./daemon/rrset.hpp"
+#include "./clients/response.hpp"
+
+#include <stdexcept>
+#include <ndn-cxx/common.hpp>
+#include <ndn-cxx/security/identity-certificate.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+
+namespace ndn {
+namespace ndns {
+
+static const Name DEFAULT_CERT;
+static const Name ROOT_ZONE;
+static const time::seconds DEFAULT_CACHE_TTL = time::seconds(3600);
+static const time::seconds DEFAULT_CERT_TTL = time::days(365);
+static const std::vector<std::string> DEFAULT_CONTENTS;
+static const std::string DEFAULT_IO = "-";
+static const time::seconds DEFAULT_RR_TTL = time::seconds(0);
+static constexpr uint64_t VERSION_USE_UNIX_TIMESTAMP = std::numeric_limits<uint64_t>::max();
+
+/**
+ * @brief provides management tools to the NDNS system, such as zone creation, zone delegation, DSK
+ * generation and root zone creation.
+ */
+class ManagementTool : noncopyable
+{
+public:
+  /** @brief Represents an error might be thrown during runtime
+   */
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what) : std::runtime_error(what)
+    {
+    }
+  };
+
+  /** @param certDir Path to the directory to store certificates
+   *  @param dbFile Path to the local database
+   */
+  explicit
+  ManagementTool(const std::string& dbFile);
+
+  /** @brief Create a Zone according to a given name.
+   *
+   *  Specifically, It will generate a KSK and a DSK (and their certificates) to the following
+   *  places:
+   *  1) Local NDNS database: a new zone is added.
+   *  2) Local NDNS database: an ID-CERT of the DSK is added.
+   *  3) KeyChain: an identity named with zone name is added.
+   *  4) KeyChain: a KSK and its self-signed certificate is added. The ownership of the KSK is the
+   *  parent zone.
+   *  5) KeyChain: a DSK and its KSK signed certificate is added.
+   *
+   *  -SS.cert (self-signed)
+   *  -SKS.cert (self's Key signed)
+   *  -PKS.cert (parent's Key Signed)
+   *
+   *  @attention
+   *  1) to create root zone, supply zoneName and parentZoneName both with ROOT_ZONE
+   *
+   *  @param zoneName zone's name
+   *  @param parentZoneName parent zone's name
+   *  @param ttl ttl for the created zone
+   *  @param kskCertName if given, a zone will be created with this ksk certificate and its key
+   *  @param kskCertName if given, a zone will be created with this dsk certificate and its key
+   */
+  void
+  createZone(const Name& zoneName,
+             const Name& parentZoneName,
+             const time::seconds& cacheTtl = DEFAULT_CACHE_TTL,
+             const time::seconds& certTtl = DEFAULT_CERT_TTL,
+             const Name& kskCertName = DEFAULT_CERT,
+             const Name& dskCertName = DEFAULT_CERT);
+
+  /** @brief Delete a Zone according to a given name.
+   *
+   *  Specifically, It will do the following things:
+   *  1) KeyChain System: delete the Identity with zone name and all its keys/certificates
+   *  2) Local NDNS database: delete the zone record
+   *  3) Local NDNS database: delete the ID-CERT of the zone's DSK
+   */
+  void
+  deleteZone(const Name& zoneName);
+
+  /** @brief Export the certificate to file system
+   *
+   *  @param certName the name of the certificate to be exported
+   *  @param output the path to output to-be exported file, including the file name
+   */
+  void
+  exportCertificate(const Name& certName, const std::string& outFile = DEFAULT_IO);
+
+  /** @brief add rrset to the NDNS local database
+   *
+   *  This one is only capable of adding NS type including NDNS_RESP and NDNS_AUTH and user defined
+   *  type with string content.
+   *  Other complicated situations can be handled by the other addRrSet() overload function.
+   *
+   *  @param zoneName the name of the zone to hold the rrset
+   *  @param label the rrset label
+   *  @param type the rrset type
+   *  @param ndnsType the ndnsType of the response, for user-defined type, just set it NDNS_RAW
+   *  @param version the version of the response and rrset, default is Unix Timestamp
+   *  @param content the content of the response
+   *  @param dskName the DSK to signed the response, default is the zone's DSK
+   *  @param ttl the ttl of the rrset
+    */
+  void
+  addRrSet(const Name& zoneName,
+           const Name& label,
+           const name::Component& type,
+           NdnsType ndnsType,
+           const uint64_t version = VERSION_USE_UNIX_TIMESTAMP,
+           const std::vector<std::string>& contents = DEFAULT_CONTENTS,
+           const Name& dskCertName = DEFAULT_CERT,
+           const time::seconds& ttl = DEFAULT_RR_TTL);
+
+  /** @brief add rrset to the NDNS local database
+   *
+   *  This overload is capable of adding any data to the rrset as long as the supplied data is
+   *  valid.
+   *  A special case is to add the ID-CERT of KSK to the parent zone. At this case, the SS cert
+   *  should be supplied, and therefore it will use the parent zone's DSK to resign the certificate.
+   *  For other cases, the data will be added directly without any modification.
+   *
+   *  @param zoneName the name of the zone to hold the rrset
+   *  @param dataPath the path to the supplied data
+   *  @param ttl the ttl of the rrset
+   *  @param dskName the DSK to signed the special case, default is the zone's DSK
+    */
+  void
+  addRrSet(const Name& zoneName,
+           const std::string& inFile = DEFAULT_IO,
+           const time::seconds& ttl = DEFAULT_RR_TTL,
+           const Name& dskCertName = DEFAULT_CERT);
+
+  /** @brief remove rrset from the NDNS local database
+   *
+   *  @param zonName the name of the zone holding the rrset
+   *  @param label rrset's label
+   *  @param type rrset's type
+    */
+  void
+  removeRrSet(const Name& zoneName, const Name& label, const name::Component& type);
+
+  /** @brief output the raw data of the selected rrset
+   *
+   *  @param zonName the name of the zone holding the rrset
+   *  @param label rrset's label
+   *  @param type rrset's type
+   *  @param os the ostream to print information to
+   *  @param isPP indicate pretty print
+    */
+  void
+  getRrSet(const Name& zoneName,
+           const Name& label,
+           const name::Component& type,
+           std::ostream& os);
+
+  /** @brief generates an output like DNS zone file. Reference:
+   *  http://en.wikipedia.org/wiki/Zone_file
+   *
+   *  @param zoneName the name of the zone to investigate
+   *  @param os the ostream to print information to
+   *  @param printRaw set to print content of ndns-raw rrset
+    */
+  void
+  listZone(const Name& zoneName, std::ostream& os, const bool printRaw = false);
+
+  /** @brief lists all existing zones within this name server.
+   *
+   *  @param os the ostream to print information to
+    */
+  void
+  listAllZones(std::ostream& os);
+
+private:
+  /** @brief add ID-CERT to the NDNS local database
+    */
+  void
+  addIdCert(Zone& zone, shared_ptr<IdentityCertificate> cert, const time::seconds& ttl);
+
+  /** @brief add zone to the NDNS local database
+    */
+  void
+  addZone(Zone& zone);
+
+  /** @brief remove zone from the NDNS local database
+    */
+  void
+  removeZone(Zone& zone);
+
+  /** @brief determine whether a certificate matches with both the identity and key type
+   */
+  bool
+  matchCertificate(const Name& certName, const Name& identity);
+
+private:
+  KeyChain m_keyChain;
+  DbMgr m_dbMgr;
+};
+
+} // namespace ndns
+} // namespace ndn
+#endif // NDNS_MGMT_MANAGEMENT_TOOL_HPP
