Update validation related codes to security v2

Change-Id: I5467b87092820666c04f22623f0f1665ce9a1194
diff --git a/src/clients/iterative-query-controller.cpp b/src/clients/iterative-query-controller.cpp
index 5a143a5..54bbb9a 100644
--- a/src/clients/iterative-query-controller.cpp
+++ b/src/clients/iterative-query-controller.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -17,8 +17,8 @@
  * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "validator.hpp"
 #include "iterative-query-controller.hpp"
+#include "validator.hpp"
 #include "logger.hpp"
 #include <iostream>
 
@@ -32,7 +32,7 @@
                                                    const QuerySucceedCallback& onSucceed,
                                                    const QueryFailCallback& onFail,
                                                    Face& face,
-                                                   Validator* validator)
+                                                   security::v2::Validator* validator)
   : QueryController(dstLabel, rrType, interestLifetime, onSucceed, onFail, face)
   , m_validator(validator)
   , m_step(QUERY_STEP_QUERY_NS)
@@ -68,20 +68,20 @@
   NDNS_LOG_TRACE("[* -> *] get a " << contentType
                  << " Response: " << data.getName());
   if (m_validator == nullptr) {
-    this->onDataValidated(make_shared<Data>(data), contentType);
+    this->onDataValidated(data, contentType);
   }
   else {
     m_validator->validate(data,
                           bind(&IterativeQueryController::onDataValidated, this, _1, contentType),
-                          [this] (const shared_ptr<const Data>& data, const std::string& str) {
-                            NDNS_LOG_WARN("data: " << data->getName() << " fails verification");
+                          [this] (const Data& data, const security::v2::ValidationError& err) {
+                            NDNS_LOG_WARN("data: " << data.getName() << " fails verification");
                             this->abort();
                           }
                           );
   }
 }
 void
-IterativeQueryController::onDataValidated(const shared_ptr<const Data>& data, NdnsContentType contentType)
+IterativeQueryController::onDataValidated(const Data& data, NdnsContentType contentType)
 {
   switch (m_step) {
   case QUERY_STEP_QUERY_NS:
@@ -89,11 +89,12 @@
       m_step = QUERY_STEP_QUERY_RR;
     }
     else if (contentType == NDNS_LINK) {
-      Link link(data->wireEncode());
-      if (link.getDelegations().empty()) {
+      Link link(data.wireEncode());
+      if (link.getDelegationList().empty()) {
         m_lastLink = Block();
-      } else {
-        m_lastLink = data->wireEncode();
+      }
+      else {
+        m_lastLink = data.wireEncode();
       }
 
       // for NS query, if already received, just return, instead of more queries until NACK
@@ -113,7 +114,8 @@
       std::ostringstream oss;
       oss << *this;
       NDNS_LOG_WARN("get unexpected Response: NDNS_BLOB for QUERY_NS: " << oss.str());
-    } else {
+    }
+    else {
       std::ostringstream oss;
       oss << *this;
       NDNS_LOG_WARN("get unexpected Response for QUERY_NS: " << oss.str());
@@ -142,9 +144,9 @@
     this->express(this->makeLatestInterest()); // express new Expres
   else if (m_step == QUERY_STEP_ANSWER_STUB) {
     NDNS_LOG_TRACE("query ends: " << *this);
-    Response re = this->parseFinalResponse(*data);
+    Response re = this->parseFinalResponse(data);
     if (m_onSucceed != nullptr)
-      m_onSucceed(*data, re);
+      m_onSucceed(data, re);
     else
       NDNS_LOG_TRACE("succeed callback is nullptr");
   }
@@ -202,7 +204,7 @@
 
   // addLink
   if (m_lastLink.hasWire()) {
-    query.setLink(m_lastLink);
+    query.setDelegationListFromLink(Link(m_lastLink));
   }
 
   switch (m_step) {
@@ -226,7 +228,8 @@
     std::ostringstream oss;
     oss << *this;
     NDNS_LOG_WARN("unexpected state: " << oss.str());
-    throw std::runtime_error("call makeLatestInterest() unexpected: " + oss.str());
+    BOOST_THROW_EXCEPTION(std::runtime_error("call makeLatestInterest() unexpected: "
+                                             + oss.str()));
   }
 
   Interest interest = query.toInterest();
diff --git a/src/clients/iterative-query-controller.hpp b/src/clients/iterative-query-controller.hpp
index 7f975da..8a15d98 100644
--- a/src/clients/iterative-query-controller.hpp
+++ b/src/clients/iterative-query-controller.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -61,7 +61,7 @@
   IterativeQueryController(const Name& dstLabel, const name::Component& rrType,
                            const time::milliseconds& interestLifetime,
                            const QuerySucceedCallback& onSucceed, const QueryFailCallback& onFail,
-                           Face& face, Validator* validator = nullptr);
+                           Face& face, security::v2::Validator* validator = nullptr);
 
   virtual void
   start();
@@ -78,7 +78,7 @@
   onData(const ndn::Interest& interest, const Data& data);
 
   void
-  onDataValidated(const shared_ptr<const Data>& data, NdnsContentType contentType);
+  onDataValidated(const Data& data, NdnsContentType contentType);
 
   /**
    * @brief change the Controller state according to timeout. For current,
@@ -92,7 +92,7 @@
 
   /**
    * @brief get the Interest according to current Controller state.
-   * Only be valid on State QueryNS & QueryRR, or throw exception
+   * Only be valid on State QueryNS and QueryRR, or throw exception
    */
   const Interest
   makeLatestInterest();
@@ -129,7 +129,7 @@
   }
 
 protected:
-  Validator* m_validator;
+  security::v2::Validator* m_validator;
   /**
    * @brief current query step
    */
@@ -160,4 +160,4 @@
 } // namespace ndns
 } // namespace ndn
 
-#endif // NDNS_CLIENTS_ITERATIVE_QUERY_HPP
+#endif // NDNS_CLIENTS_ITERATIVE_QUERY_CONTROLLER_HPP
diff --git a/src/clients/query.cpp b/src/clients/query.cpp
index 9853672..8a133bb 100644
--- a/src/clients/query.cpp
+++ b/src/clients/query.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -47,10 +47,11 @@
 
   m_zone = zone;
 
-  if (interest.hasLink()) {
-    m_link = interest.getLink().wireEncode();
-  } else {
-    m_link = Block();
+  if (!interest.getForwardingHint().empty()) {
+    m_delegationList = interest.getForwardingHint();
+  }
+  else {
+    m_delegationList = DelegationList();
   }
 
 
@@ -74,13 +75,19 @@
   Interest interest;
   interest.setName(name);
   interest.setInterestLifetime(m_interestLifetime);
-  if (m_link.hasWire()) {
-    interest.setLink(m_link);
+  if (!m_delegationList.empty()) {
+    interest.setForwardingHint(m_delegationList);
   }
 
   return interest;
 }
 
+void
+Query::setDelegationListFromLink(const Link& link)
+{
+  m_delegationList = link.getDelegationList();
+}
+
 std::ostream&
 operator<<(std::ostream& os, const Query& query)
 {
diff --git a/src/clients/query.hpp b/src/clients/query.hpp
index d96d58c..f933eeb 100644
--- a/src/clients/query.hpp
+++ b/src/clients/query.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -59,6 +59,9 @@
   bool
   fromInterest(const Name& zone, const Interest& interest);
 
+  void
+  setDelegationListFromLink(const Link& link);
+
   bool
   operator==(const Query& other) const
   {
@@ -170,18 +173,18 @@
    * @brief set link object
    */
   void
-  setLink(const Block& link)
+  setDelegationList(const DelegationList& delegations)
   {
-    m_link = link;
+    m_delegationList = delegations;
   }
 
   /**
    * @brief get Link object
    */
-  const Block&
-  getLink() const
+  const DelegationList&
+  getDelegationList() const
   {
-    return m_link;
+    return m_delegationList;
   }
 
 private:
@@ -190,7 +193,7 @@
   Name m_rrLabel;
   name::Component m_rrType;
   time::milliseconds m_interestLifetime;
-  Block m_link;
+  DelegationList m_delegationList;
 };
 
 std::ostream&
diff --git a/src/clients/response.cpp b/src/clients/response.cpp
index b1c3865..a23bc3c 100644
--- a/src/clients/response.cpp
+++ b/src/clients/response.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -39,7 +39,7 @@
 {
 }
 
-template<bool T>
+template<encoding::Tag T>
 inline size_t
 Response::wireEncode(EncodingImpl<T>& block) const
 {
@@ -180,8 +180,10 @@
 {
   if (block.type() != ndn::tlv::Content) {
     m_appContent = Block(ndn::tlv::Content, block);
-  } else
+  }
+  else {
     m_appContent = block;
+  }
 
   m_appContent.encode(); // this is a must
 }
diff --git a/src/clients/response.hpp b/src/clients/response.hpp
index 9f2138f..a33e42a 100644
--- a/src/clients/response.hpp
+++ b/src/clients/response.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -108,9 +108,9 @@
   /**
    * @brief encode app-level data
    */
-  template<bool T>
+  template<encoding::Tag T>
   size_t
-  wireEncode(EncodingImpl<T> & block) const;
+  wireEncode(EncodingImpl<T>& block) const;
 
 public:
   ///////////////////////////////////////////////
diff --git a/src/common.hpp b/src/common.hpp
index d813913..50b278a 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -17,8 +17,8 @@
  * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef COMMON_HPP
-#define COMMON_HPP
+#ifndef NDNS_COMMON_HPP
+#define NDNS_COMMON_HPP
 
 #ifdef NDNS_HAVE_TESTS
 #define NDNS_VIRTUAL_WITH_TESTS virtual
@@ -32,8 +32,4 @@
 #define NDNS_PROTECTED_WITH_TESTS_ELSE_PRIVATE private
 #endif
 
-
-
-
-
-#endif // COMMON_HPP
+#endif // NDNS_COMMON_HPP
diff --git a/src/daemon/db-mgr.cpp b/src/daemon/db-mgr.cpp
index 8f5fcb3..b925f2d 100644
--- a/src/daemon/db-mgr.cpp
+++ b/src/daemon/db-mgr.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -29,25 +29,32 @@
 
 NDNS_LOG_INIT("DbMgr")
 
-static const std::string NDNS_SCHEMA = "\
-CREATE TABLE IF NOT EXISTS zones (      \n\
-  id    INTEGER NOT NULL PRIMARY KEY,   \n\
-  name  blob NOT NULL UNIQUE,           \n\
-  ttl   integer(10) NOT NULL);          \n\
-                                        \n\
-CREATE TABLE IF NOT EXISTS rrsets (     \n\
-  id      INTEGER NOT NULL PRIMARY KEY, \n\
-  zone_id integer(10) NOT NULL,         \n\
-  label   blob NOT NULL,                \n\
-  type    blob NOT NULL,                \n\
-  version blob NOT NULL,                \n\
-  ttl     integer(10) NOT NULL,         \n\
-  data    blob NOT NULL,                                                \n\
-  FOREIGN KEY(zone_id) REFERENCES zones(id) ON UPDATE Cascade ON DELETE Cascade); \n\
-                                                                        \n\
-CREATE UNIQUE INDEX rrsets_zone_id_label_type_version                   \n\
-  ON rrsets (zone_id, label, type, version);                            \n\
-";
+static const std::string NDNS_SCHEMA = R"VALUE(
+CREATE TABLE IF NOT EXISTS zones (
+  id    INTEGER NOT NULL PRIMARY KEY,
+  name  blob NOT NULL UNIQUE,
+  ttl   integer(10) NOT NULL);
+
+CREATE TABLE IF NOT EXISTS zone_info (
+  zone_id  INTEGER NOT NULL,
+  key      VARCHAR(10) NOT NULL,
+  value    blob NOT NULL,
+  PRIMARY KEY (zone_id, key),
+  FOREIGN KEY(zone_id) REFERENCES zones(id) ON UPDATE Cascade ON DELETE Cascade);
+
+CREATE TABLE IF NOT EXISTS rrsets (
+  id      INTEGER NOT NULL PRIMARY KEY,
+  zone_id integer(10) NOT NULL,
+  label   blob NOT NULL,
+  type    blob NOT NULL,
+  version blob NOT NULL,
+  ttl     integer(10) NOT NULL,
+  data    blob NOT NULL,
+  FOREIGN KEY(zone_id) REFERENCES zones(id) ON UPDATE Cascade ON DELETE Cascade);
+
+CREATE UNIQUE INDEX rrsets_zone_id_label_type_version
+  ON rrsets (zone_id, label, type, version);
+)VALUE";
 
 DbMgr::DbMgr(const std::string& dbFile/* = DEFAULT_CONFIG_PATH "/" "ndns.db"*/)
   : m_dbFile(dbFile)
@@ -83,7 +90,7 @@
 
   if (res != SQLITE_OK) {
     NDNS_LOG_FATAL("Cannot open the db file: " << m_dbFile);
-    throw ConnectError("Cannot open the db file: " + m_dbFile);
+    BOOST_THROW_EXCEPTION(ConnectError("Cannot open the db file: " + m_dbFile));
   }
   // ignore any errors from DB creation (command will fail for the existing database, which is ok)
   sqlite3_exec(m_conn, NDNS_SCHEMA.c_str(), 0, 0, 0);
@@ -112,7 +119,7 @@
 
   int rc = sqlite3_exec(m_conn, sql, 0, 0, 0); // sqlite3_step cannot execute multiple SQL statement
   if (rc != SQLITE_OK) {
-    throw ExecuteError(sql);
+    BOOST_THROW_EXCEPTION(ExecuteError(sql));
   }
 
   NDNS_LOG_INFO("clear all the data in the database: " << m_dbFile);
@@ -132,7 +139,7 @@
   const char* sql = "INSERT INTO zones (name, ttl) VALUES (?, ?)";
   int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
   if (rc != SQLITE_OK) {
-    throw PrepareError(sql);
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
   }
 
   const Block& zoneName = zone.getName().wireEncode();
@@ -142,13 +149,80 @@
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE) {
     sqlite3_finalize(stmt);
-    throw ExecuteError(sql);
+    BOOST_THROW_EXCEPTION(ExecuteError(sql));
   }
 
   zone.setId(sqlite3_last_insert_rowid(m_conn));
   sqlite3_finalize(stmt);
 }
 
+void
+DbMgr::setZoneInfo(Zone& zone,
+                   const std::string& key,
+                   const Block& value)
+{
+  if (zone.getId() == 0) {
+    BOOST_THROW_EXCEPTION(Error("zone has not been initialized"));
+  }
+
+  if (key.length() > 10) {
+    BOOST_THROW_EXCEPTION(Error("key length should not exceed 10"));
+  }
+
+  sqlite3_stmt* stmt;
+  const char* sql = "INSERT OR REPLACE INTO zone_info (zone_id, key, value) VALUES (?, ?, ?)";
+  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
+  if (rc != SQLITE_OK) {
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
+  }
+
+  sqlite3_bind_int(stmt,  1, zone.getId());
+  sqlite3_bind_text(stmt, 2, key.c_str(),  key.length(), SQLITE_STATIC);
+  sqlite3_bind_blob(stmt, 3, value.wire(), value.size(), SQLITE_STATIC);
+
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_DONE) {
+    sqlite3_finalize(stmt);
+    BOOST_THROW_EXCEPTION(ExecuteError(sql));
+  }
+
+  sqlite3_finalize(stmt);
+}
+
+std::map<std::string, Block>
+DbMgr::getZoneInfo(Zone& zone)
+{
+  using std::string;
+  std::map<string, Block> rtn;
+
+  if (zone.getId() == 0) {
+    find(zone);
+  }
+
+  if (zone.getId() == 0) {
+    BOOST_THROW_EXCEPTION(Error("zone has not been initialized"));
+  }
+
+  sqlite3_stmt* stmt;
+  const char* sql = "SELECT key, value FROM zone_info WHERE zone_id=?";
+  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
+  if (rc != SQLITE_OK) {
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
+  }
+
+  sqlite3_bind_int(stmt, 1, zone.getId());
+
+  while (sqlite3_step(stmt) == SQLITE_ROW) {
+    const char* key = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
+    rtn[string(key)] = Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 1)),
+                             sqlite3_column_bytes(stmt, 1));
+  }
+
+  sqlite3_finalize(stmt);
+  return rtn;
+}
+
+
 bool
 DbMgr::find(Zone& zone)
 {
@@ -156,7 +230,7 @@
   const char* sql = "SELECT id, ttl FROM zones WHERE name=?";
   int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
   if (rc != SQLITE_OK) {
-    throw PrepareError(sql);
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
   }
 
   const Block& zoneName = zone.getName().wireEncode();
@@ -165,7 +239,8 @@
   if (sqlite3_step(stmt) == SQLITE_ROW) {
     zone.setId(sqlite3_column_int64(stmt, 0));
     zone.setTtl(time::seconds(sqlite3_column_int(stmt, 1)));
-  } else {
+  }
+  else {
     zone.setId(0);
   }
 
@@ -181,7 +256,7 @@
   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);
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
   }
 
   std::vector<Zone> vec;
@@ -209,7 +284,7 @@
   const char* sql = "DELETE FROM zones where id=?";
   int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
   if (rc != SQLITE_OK) {
-    throw PrepareError(sql);
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
   }
 
   sqlite3_bind_int64(stmt, 1, zone.getId());
@@ -217,7 +292,7 @@
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE) {
     sqlite3_finalize(stmt);
-    throw ExecuteError(sql);
+    BOOST_THROW_EXCEPTION(ExecuteError(sql));
   }
 
   sqlite3_finalize(stmt);
@@ -237,7 +312,7 @@
     return;
 
   if (rrset.getZone() == 0) {
-    throw RrsetError("Rrset has not been assigned to a zone");
+    BOOST_THROW_EXCEPTION(RrsetError("Rrset has not been assigned to a zone"));
   }
 
   if (rrset.getZone()->getId() == 0) {
@@ -251,7 +326,7 @@
   sqlite3_stmt* stmt;
   int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
   if (rc != SQLITE_OK) {
-    throw PrepareError(sql);
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
   }
 
   sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());
@@ -266,7 +341,7 @@
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE) {
     sqlite3_finalize(stmt);
-    throw ExecuteError(sql);
+    BOOST_THROW_EXCEPTION(ExecuteError(sql));
   }
 
   rrset.setId(sqlite3_last_insert_rowid(m_conn));
@@ -277,7 +352,7 @@
 DbMgr::find(Rrset& rrset)
 {
   if (rrset.getZone() == 0) {
-    throw RrsetError("Rrset has not been assigned to a zone");
+    BOOST_THROW_EXCEPTION(RrsetError("Rrset has not been assigned to a zone"));
   }
 
   if (rrset.getZone()->getId() == 0) {
@@ -294,7 +369,7 @@
   int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
 
   if (rc != SQLITE_OK) {
-    throw PrepareError(sql);
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
   }
 
   sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());
@@ -310,7 +385,8 @@
                            sqlite3_column_bytes(stmt, 2)));
     rrset.setData(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
                         sqlite3_column_bytes(stmt, 3)));
-  } else {
+  }
+  else {
     rrset.setId(0);
   }
   sqlite3_finalize(stmt);
@@ -325,7 +401,7 @@
     find(zone);
 
   if (zone.getId() == 0)
-    throw RrsetError("Attempting to find all the rrsets with a zone does not in the database");
+    BOOST_THROW_EXCEPTION(RrsetError("Attempting to find all the rrsets with a zone does not in the database"));
 
   std::vector<Rrset> vec;
   sqlite3_stmt* stmt;
@@ -334,7 +410,7 @@
 
   int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
   if (rc != SQLITE_OK) {
-    throw PrepareError(sql);
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
   }
   sqlite3_bind_int64(stmt, 1, zone.getId());
 
@@ -363,14 +439,14 @@
 DbMgr::remove(Rrset& rrset)
 {
   if (rrset.getId() == 0)
-    throw RrsetError("Attempting to remove Rrset that has no assigned id");
+    BOOST_THROW_EXCEPTION(RrsetError("Attempting to remove Rrset that has no assigned id"));
 
   sqlite3_stmt* stmt;
   const char* sql = "DELETE FROM rrsets WHERE id=?";
   int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
 
   if (rc != SQLITE_OK) {
-    throw PrepareError(sql);
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
   }
 
   sqlite3_bind_int64(stmt, 1, rrset.getId());
@@ -378,7 +454,7 @@
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE) {
     sqlite3_finalize(stmt);
-    throw ExecuteError(sql);
+    BOOST_THROW_EXCEPTION(ExecuteError(sql));
   }
 
   sqlite3_finalize(stmt);
@@ -390,11 +466,11 @@
 DbMgr::update(Rrset& rrset)
 {
   if (rrset.getId() == 0) {
-    throw RrsetError("Attempting to replace Rrset that has no assigned id");
+    BOOST_THROW_EXCEPTION(RrsetError("Attempting to replace Rrset that has no assigned id"));
   }
 
   if (rrset.getZone() == 0) {
-    throw RrsetError("Rrset has not been assigned to a zone");
+    BOOST_THROW_EXCEPTION(RrsetError("Rrset has not been assigned to a zone"));
   }
 
   sqlite3_stmt* stmt;
@@ -402,7 +478,7 @@
   int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
 
   if (rc != SQLITE_OK) {
-    throw PrepareError(sql);
+    BOOST_THROW_EXCEPTION(PrepareError(sql));
   }
 
   sqlite3_bind_int64(stmt, 1, rrset.getTtl().count());
diff --git a/src/daemon/db-mgr.hpp b/src/daemon/db-mgr.hpp
index 5c4e179..9e79223 100644
--- a/src/daemon/db-mgr.hpp
+++ b/src/daemon/db-mgr.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -33,7 +33,7 @@
 #define DEFINE_ERROR(ErrorName, Base)           \
 class ErrorName : public Base                   \
 {                                               \
- public:                                        \
+public:                                         \
   explicit                                      \
   ErrorName(const std::string& what)            \
     : Base(what)                                \
@@ -105,6 +105,20 @@
   insert(Zone& zone);
 
   /**
+   * @brief set zoneInfo by key-value
+   */
+  void
+  setZoneInfo(Zone& zone,
+              const std::string& key,
+              const Block& value);
+
+  /**
+   * @brief get zoneInfo
+   */
+  std::map<std::string, Block>
+  getZoneInfo(Zone& zone);
+
+  /**
    * @brief lookup the zone by name, fill the m_id and m_ttl
    * @post whatever the previous id is
    * @return true if the record exist
diff --git a/src/daemon/name-server.cpp b/src/daemon/name-server.cpp
index 70288ec..11ad3a8 100644
--- a/src/daemon/name-server.cpp
+++ b/src/daemon/name-server.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -20,6 +20,7 @@
 #include "name-server.hpp"
 #include "logger.hpp"
 #include <ndn-cxx/encoding/encoding-buffer.hpp>
+#include <ndn-cxx/security/signing-helpers.hpp>
 
 namespace ndn {
 namespace ndns {
@@ -28,44 +29,32 @@
 const time::milliseconds NAME_SERVER_DEFAULT_CONTENT_FRESHNESS(4000);
 
 NameServer::NameServer(const Name& zoneName, const Name& certName, Face& face, DbMgr& dbMgr,
-                       KeyChain& keyChain, Validator& validator)
+                       KeyChain& keyChain, security::v2::Validator& validator)
   : m_zone(zoneName)
   , m_dbMgr(dbMgr)
   , m_ndnsPrefix(zoneName)
-  , m_keyPrefix(zoneName)
   , m_certName(certName)
   , m_contentFreshness(NAME_SERVER_DEFAULT_CONTENT_FRESHNESS)
   , m_face(face)
   , m_keyChain(keyChain)
   , m_validator(validator)
 {
-  if (!m_keyChain.doesCertificateExist(m_certName)) {
-    NDNS_LOG_FATAL("Certificate: " << m_certName << " does not exist");
-    throw Error("certificate does not exist in the KeyChain: " + m_certName.toUri());
-  }
-
   m_dbMgr.find(m_zone);
 
   if (m_zone.getId() == 0) {
     NDNS_LOG_FATAL("m_zone does not exist: " << zoneName);
-    throw Error("Zone " + zoneName.toUri() + " does not exist in the database");
+    BOOST_THROW_EXCEPTION(Error("Zone " + zoneName.toUri() + " does not exist in the database"));
   }
 
   m_ndnsPrefix.append(ndns::label::NDNS_ITERATIVE_QUERY);
-  m_keyPrefix.append(ndns::label::NDNS_CERT_QUERY);
 
   m_face.setInterestFilter(m_ndnsPrefix,
                            bind(&NameServer::onInterest, this, _1, _2),
                            bind(&NameServer::onRegisterFailed, this, _1, _2)
                            );
 
-  m_face.setInterestFilter(m_keyPrefix,
-                           bind(&NameServer::onInterest, this, _1, _2),
-                           bind(&NameServer::onRegisterFailed, this, _1, _2)
-                           );
-
   NDNS_LOG_INFO("Zone: " << m_zone.getName() << " binds "
-                << "Prefix: " << m_ndnsPrefix << " and " << m_keyPrefix
+                << "Prefix: " << m_ndnsPrefix
                 << " with Certificate: " << m_certName
                 );
 }
@@ -109,7 +98,7 @@
     answer->setFreshnessPeriod(this->getContentFreshness());
     answer->setContentType(NDNS_NACK);
 
-    m_keyChain.sign(*answer, m_certName);
+    m_keyChain.sign(*answer, signingByCertificate(m_certName));
     NDNS_LOG_TRACE("answer query with NDNS-NACK: " << answer->getName());
     m_face.put(*answer);
   }
@@ -127,13 +116,13 @@
       const Block& block = it->blockFromValue();
       data = make_shared<Data>(block);
     }
-    catch (std::exception& e) {
+    catch (const std::exception& e) {
       NDNS_LOG_WARN("exception when getting update info: " << e.what());
       return;
     }
     m_validator.validate(*data,
                          bind(&NameServer::doUpdate, this, interest.shared_from_this(), data),
-                         [this] (const shared_ptr<const Data>& data, const std::string& msg) {
+                         [this] (const Data& data, const security::v2::ValidationError& msg) {
                            NDNS_LOG_WARN("Ignoring update that did not pass the verification. "
                                          << "Check the root certificate")
                          });
@@ -144,8 +133,8 @@
 NameServer::onRegisterFailed(const ndn::Name& prefix, const std::string& reason)
 {
   NDNS_LOG_FATAL("fail to register prefix=" << prefix << ". Due to: " << reason);
-  throw Error("zone " + m_zone.getName().toUri() + " register prefix: " +
-              prefix.toUri() + " fails. due to: " + reason);
+  BOOST_THROW_EXCEPTION(Error("zone " + m_zone.getName().toUri() + " register prefix: " +
+                              prefix.toUri() + " fails. due to: " + reason));
 }
 
 void
@@ -157,7 +146,7 @@
     if (!label::matchName(*data, m_zone.getName(), re))
       return;
   }
-  catch (std::exception& e) {
+  catch (const std::exception& e) {
     NDNS_LOG_INFO("Error while name/certificate matching: " << e.what());
   }
 
@@ -204,7 +193,7 @@
       NDNS_LOG_TRACE("insert new record and answer update with UPDATE_OK");
     }
   }
-  catch (std::exception& e) {
+  catch (const std::exception& e) {
     blk.push_back(makeNonNegativeIntegerBlock(ndn::ndns::tlv::UpdateReturnCode, UPDATE_FAILURE));
     blk.encode(); // must
     answer->setContent(blk);
@@ -212,7 +201,7 @@
                   << ". Update may need sudo privilege to write DbFile");
     NDNS_LOG_TRACE("exception happens and answer update with UPDATE_FAILURE");
   }
-  m_keyChain.sign(*answer, m_certName);
+  m_keyChain.sign(*answer, signingByCertificate(m_certName));
   m_face.put(*answer);
 }
 
diff --git a/src/daemon/name-server.hpp b/src/daemon/name-server.hpp
index aa75ade..d62cf79 100644
--- a/src/daemon/name-server.hpp
+++ b/src/daemon/name-server.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -53,11 +53,11 @@
 public:
   explicit
   NameServer(const Name& zoneName, const Name& certName, Face& face, DbMgr& dbMgr,
-             KeyChain& keyChain, Validator& validator);
+             KeyChain& keyChain, security::v2::Validator& validator);
 
 NDNS_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   void
-  onInterest(const Name& prefix, const Interest &interest);
+  onInterest(const Name& prefix, const Interest& interest);
 
   /**
    * @brief handle NDNS query message
@@ -84,18 +84,6 @@
     return m_ndnsPrefix;
   }
 
-  const Name&
-  getKeyPrefix() const
-  {
-    return m_keyPrefix;
-  }
-
-  void
-  setKeyPrefix(const Name& keyPrefix)
-  {
-    m_keyPrefix = keyPrefix;
-  }
-
   const Zone&
   getZone() const
   {
@@ -123,14 +111,13 @@
   DbMgr& m_dbMgr;
 
   Name m_ndnsPrefix;
-  Name m_keyPrefix;
   Name m_certName;
 
   time::milliseconds m_contentFreshness;
 
   Face& m_face;
   KeyChain& m_keyChain;
-  Validator& m_validator;
+  security::v2::Validator& m_validator;
 };
 
 } // namespace ndns
diff --git a/src/daemon/rrset-factory.cpp b/src/daemon/rrset-factory.cpp
index 9757abc..da7ffde 100644
--- a/src/daemon/rrset-factory.cpp
+++ b/src/daemon/rrset-factory.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2014-2017, Regents of the University of California.
  *
  * This file is part of NDNS (Named Data Networking Domain Name Service).
@@ -19,6 +19,9 @@
 
 #include "rrset-factory.hpp"
 #include "mgmt/management-tool.hpp"
+#include "util/cert-helper.hpp"
+
+#include <ndn-cxx/security/signing-helpers.hpp>
 
 #include <boost/algorithm/string/join.hpp>
 
@@ -37,9 +40,10 @@
   , m_dskCertName(inputDskCertName)
   , m_checked(false)
 {
+  Name identityName = Name(zoneName).append(label::NDNS_CERT_QUERY);
   if (m_dskCertName == DEFAULT_CERT) {
-    m_dskName = m_keyChain.getDefaultKeyNameForIdentity(zoneName);
-    m_dskCertName = m_keyChain.getDefaultCertificateNameForKey(m_dskName);
+    m_dskName = CertHelper::getDefaultKeyNameOfIdentity(m_keyChain, identityName);
+    m_dskCertName = CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, identityName);
   }
 }
 
@@ -47,8 +51,9 @@
 RrsetFactory::checkZoneKey()
 {
   onlyCheckZone();
+  Name zoneIdentityName = Name(m_zone.getName()).append(label::NDNS_CERT_QUERY);
   if (m_dskCertName != DEFAULT_CERT &&
-      !matchCertificate(m_dskCertName, m_zone.getName())) {
+      !matchCertificate(m_dskCertName, zoneIdentityName)) {
     BOOST_THROW_EXCEPTION(Error("Cannot verify certificate"));
   }
 }
@@ -84,7 +89,8 @@
   name::Component qType;
   if (type == label::CERT_RR_TYPE) {
     qType = label::NDNS_CERT_QUERY;
-  } else {
+  }
+  else {
     qType = label::NDNS_ITERATIVE_QUERY;
   }
 
@@ -96,7 +102,8 @@
 
   if (version != VERSION_USE_UNIX_TIMESTAMP) {
     name.append(name::Component::fromVersion(version));
-  } else {
+  }
+  else {
     name.appendVersion();
   }
 
@@ -108,26 +115,12 @@
 bool
 RrsetFactory::matchCertificate(const Name& certName, const Name& identity)
 {
-  if (!m_keyChain.doesCertificateExist(certName)) {
-    NDNS_LOG_WARN(certName.toUri() << " is not presented in KeyChain");
+  try {
+    CertHelper::getCertificate(m_keyChain, identity, certName);
+    return true;
+  } catch (ndn::security::Pib::Error) {
     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, KeyClass::PRIVATE)) {
-    NDNS_LOG_WARN("Private key: " << keyName.toUri() << " is not present in KeyChain");
-    return false;
-  }
-
-  return true;
 }
 
 Rrset
@@ -135,7 +128,7 @@
                               const name::Component& type,
                               const uint64_t version,
                               time::seconds ttl,
-                              const ndn::Link::DelegationSet& delegations)
+                              const ndn::DelegationList& delegations)
 {
   if (!m_checked) {
     BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
@@ -149,9 +142,7 @@
   Rrset& rrset = rrsetAndName.first;
 
   Link link(name);
-  for (const auto& i : delegations) {
-    link.addDelegation(i.first, i.second);
-  }
+  link.setDelegationList(delegations);
 
   setContentType(link, NDNS_LINK, ttl);
   sign(link);
@@ -200,7 +191,7 @@
                                 const name::Component& type,
                                 const uint64_t version,
                                 time::seconds ttl,
-                                const IdentityCertificate& cert)
+                                const ndn::security::v2::Certificate& cert)
 {
   if (!m_checked) {
     BOOST_THROW_EXCEPTION(Error("You have to call checkZoneKey before call generate functions"));
@@ -252,7 +243,7 @@
 void
 RrsetFactory::sign(Data& data)
 {
-  m_keyChain.sign(data, m_dskCertName);
+  m_keyChain.sign(data, signingByCertificate(m_dskCertName));
 }
 
 void
diff --git a/src/daemon/rrset-factory.hpp b/src/daemon/rrset-factory.hpp
index e6c5455..89f5b98 100644
--- a/src/daemon/rrset-factory.hpp
+++ b/src/daemon/rrset-factory.hpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2014-2017, Regents of the University of California.
  *
  * This file is part of NDNS (Named Data Networking Domain Name Service).
@@ -64,7 +64,7 @@
                   const name::Component& type,
                   const uint64_t version,
                   time::seconds ttl,
-                  const ndn::Link::DelegationSet& delegations);
+                  const ndn::DelegationList& delegations);
 
   Rrset
   generateTxtRrset(const Name& label,
@@ -84,7 +84,7 @@
                     const name::Component& type,
                     const uint64_t version,
                     time::seconds ttl,
-                    const IdentityCertificate& cert);
+                    const ndn::security::v2::Certificate& cert);
 
   static std::vector<std::string>
   wireDecodeTxt(const Block& wire);
diff --git a/src/mgmt/management-tool.cpp b/src/mgmt/management-tool.cpp
index e74c601..6610a13 100644
--- a/src/mgmt/management-tool.cpp
+++ b/src/mgmt/management-tool.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2014-2017, Regents of the University of California.
  *
  * This file is part of NDNS (Named Data Networking Domain Name Service).
@@ -21,6 +21,7 @@
 #include "logger.hpp"
 #include "ndns-label.hpp"
 #include "ndns-tlv.hpp"
+#include "util/cert-helper.hpp"
 
 #include <string>
 #include <iomanip>
@@ -32,103 +33,141 @@
 
 #include <ndn-cxx/util/regex.hpp>
 #include <ndn-cxx/util/indented-stream.hpp>
-#include <ndn-cxx/encoding/oid.hpp>
-#include <ndn-cxx/security/v1/cryptopp.hpp>
+#include <ndn-cxx/util/io.hpp>
 #include <ndn-cxx/link.hpp>
 #include <ndn-cxx/security/signing-helpers.hpp>
+#include <ndn-cxx/security/transform.hpp>
+
 
 namespace ndn {
 namespace ndns {
 
 NDNS_LOG_INIT("ManagementTool")
 
+using security::transform::base64Encode;
+using security::transform::streamSink;
+using security::transform::bufferSource;
+using security::v2::Certificate;
+using security::Identity;
+using security::Key;
+
 ManagementTool::ManagementTool(const std::string& dbFile, KeyChain& keyChain)
   : m_keyChain(keyChain)
   , m_dbMgr(dbFile)
 {
 }
 
-void
-ManagementTool::createZone(const Name &zoneName,
+Zone
+ManagementTool::createZone(const Name& zoneName,
                            const Name& parentZoneName,
                            const time::seconds& cacheTtl,
                            const time::seconds& certValidity,
                            const Name& kskCertName,
-                           const Name& dskCertName)
+                           const Name& dskCertName,
+                           const Name& dkeyCertName)
 {
   bool isRoot = zoneName == ROOT_ZONE;
+  Name zoneIdentityName = Name(zoneName).append(label::NDNS_CERT_QUERY);
 
   //check preconditions
   Zone zone(zoneName, cacheTtl);
   if (m_dbMgr.find(zone)) {
-    throw Error(zoneName.toUri() + " is already presented in the NDNS db");
+    BOOST_THROW_EXCEPTION(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");
+    BOOST_THROW_EXCEPTION(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());
+    BOOST_THROW_EXCEPTION(Error(parentZoneName.toUri() + " is not a prefix of " + zoneName.toUri()));
   }
 
   // if dsk is provided, there is no need to check ksk
   if (dskCertName != DEFAULT_CERT) {
-    if (!matchCertificate(dskCertName, zoneName)) {
-      throw Error("Cannot verify DSK certificate");
+    if (!matchCertificate(dskCertName, zoneIdentityName)) {
+      BOOST_THROW_EXCEPTION(Error("Cannot verify DSK certificate"));
     }
   }
   else if (kskCertName != DEFAULT_CERT) {
-    if (!matchCertificate(kskCertName, zoneName)) {
-      throw Error("Cannot verify KSK certificate");
+    if (!matchCertificate(kskCertName, zoneIdentityName)) {
+      BOOST_THROW_EXCEPTION(Error("Cannot verify KSK certificate"));
     }
   }
 
-  if (kskCertName == DEFAULT_CERT && isRoot) {
-    throw Error("Cannot generate KSK for root zone");
+  if (dkeyCertName == DEFAULT_CERT && isRoot) {
+    BOOST_THROW_EXCEPTION(Error("Cannot generate dkey 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");
-  Name dskName;
-  shared_ptr<IdentityCertificate> dskCert;
-  if (dskCertName == DEFAULT_CERT) {
-    // if no dsk provided, then generate a dsk either signed by ksk auto generated or user provided
-    time::system_clock::TimePoint notBefore = time::system_clock::now();
-    time::system_clock::TimePoint notAfter = notBefore + certValidity;
-    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, parentZoneName);
-      kskCert->setFreshnessPeriod(cacheTtl);
-
-      m_keyChain.selfSign(*kskCert);
-      m_keyChain.addCertificate(*kskCert);
-      NDNS_LOG_INFO("Generated KSK: " << kskCert->getName());
-    }
-    else {
-      kskCert = m_keyChain.getCertificate(kskCertName);
-    }
-
-    dskName = m_keyChain.generateRsaKeyPairAsDefault(zoneName, false);
-    //create DSK's certificate
-    std::vector<CertificateSubjectDescription> dskDesc;
-    dskCert = m_keyChain.prepareUnsignedIdentityCertificate(dskName, zoneName, notBefore, notAfter,
-                                                            dskDesc, zoneName);
-    dskCert->setFreshnessPeriod(cacheTtl);
-    m_keyChain.sign(*dskCert, kskCert->getName());
-    m_keyChain.addCertificateAsKeyDefault(*dskCert);
-    NDNS_LOG_INFO("Generated DSK: " << dskCert->getName());
+  // Generate a parentZone's identity to generate a D-Key.
+  // This D-key will be passed to parent zone and resigned.
+  Name dkeyIdentityName;
+  if (dkeyCertName == DEFAULT_CERT) {
+    dkeyIdentityName = Name(parentZoneName).append(label::NDNS_CERT_QUERY)
+      .append(zoneName.getSubName(parentZoneName.size()));
   }
   else {
-    dskCert = m_keyChain.getCertificate(dskCertName);
-    dskName = dskCert->getPublicKeyName();
-    m_keyChain.setDefaultKeyNameForIdentity(dskName);
-    m_keyChain.setDefaultCertificateNameForKey(dskCert->getName());
+    dkeyIdentityName = CertHelper::getIdentityNameFromCert(dkeyCertName);
+  }
+  NDNS_LOG_INFO("Generated D-Key's identityName: " + dkeyIdentityName.toUri());
+
+  Name dskName;
+  Key ksk;
+  Key dsk;
+  Key dkey;
+  Certificate dskCert;
+  Certificate kskCert;
+  Certificate dkeyCert;
+  Identity zoneIdentity = m_keyChain.createIdentity(zoneIdentityName);
+  Identity dkeyIdentity = m_keyChain.createIdentity(dkeyIdentityName);
+
+  if (dkeyCertName == DEFAULT_CERT) {
+    dkey = m_keyChain.createKey(dkeyIdentity);
+    m_keyChain.deleteCertificate(dkey, dkey.getDefaultCertificate().getName());
+
+    dkeyCert = CertHelper::createCertificate(m_keyChain, dkey, dkey, label::CERT_RR_TYPE.toUri(), time::days(90));
+    dkeyCert.setFreshnessPeriod(cacheTtl);
+    m_keyChain.addCertificate(dkey, dkeyCert);
+    NDNS_LOG_INFO("Generated DKEY: " << dkeyCert.getName());
+
+  }
+  else {
+    dkeyCert = CertHelper::getCertificate(m_keyChain, dkeyIdentityName, dkeyCertName);
+    dkey = dkeyIdentity.getKey(dkeyCert.getKeyName());
+  }
+
+  if (kskCertName == DEFAULT_CERT) {
+    ksk = m_keyChain.createKey(zoneIdentity);
+    // delete automatically generated certificates,
+    // because its issue is 'self' instead of CERT_RR_TYPE
+    m_keyChain.deleteCertificate(ksk, ksk.getDefaultCertificate().getName());
+    kskCert = CertHelper::createCertificate(m_keyChain, ksk, dkey, label::CERT_RR_TYPE.toUri(), time::days(90));
+    kskCert.setFreshnessPeriod(cacheTtl);
+    m_keyChain.addCertificate(ksk, kskCert);
+    NDNS_LOG_INFO("Generated KSK: " << kskCert.getName());
+  }
+  else {
+    // ksk usually might not be the default key of a zone
+    kskCert = CertHelper::getCertificate(m_keyChain, zoneIdentityName, kskCertName);
+    ksk = zoneIdentity.getKey(kskCert.getKeyName());
+  }
+
+  if (dskCertName == DEFAULT_CERT) {
+    // if no dsk provided, then generate a dsk either signed by ksk auto generated or user provided
+    dsk = m_keyChain.createKey(zoneIdentity);
+    m_keyChain.deleteCertificate(dsk, dsk.getDefaultCertificate().getName());
+    dskCert = CertHelper::createCertificate(m_keyChain, dsk, ksk, label::CERT_RR_TYPE.toUri(), certValidity);
+    dskCert.setFreshnessPeriod(cacheTtl);
+    // dskCert will become the default certificate, since the default cert has been deleted.
+    m_keyChain.addCertificate(dsk, dskCert);
+    m_keyChain.setDefaultKey(zoneIdentity, dsk);
+    NDNS_LOG_INFO("Generated DSK: " << dskCert.getName());
+  }
+  else {
+    dskCert = CertHelper::getCertificate(m_keyChain, zoneIdentityName, dskCertName);
+    dsk = zoneIdentity.getKey(dskCert.getKeyName());
+    m_keyChain.setDefaultKey(zoneIdentity, dsk);
+    m_keyChain.setDefaultCertificate(dsk, dskCert);
   }
 
   //second add zone to the database
@@ -136,8 +175,18 @@
   addZone(zone);
 
   //third create ID-cert
-  NDNS_LOG_INFO("Start creating DSK's ID-CERT");
-  addIdCert(zone, dskCert, cacheTtl);
+  NDNS_LOG_INFO("Start adding Certificates to NDNS database");
+  addIdCert(zone, kskCert, cacheTtl, dskCert);
+  addIdCert(zone, dskCert, cacheTtl, dskCert);
+
+  NDNS_LOG_INFO("Start saving KSK and DSK's id to ZoneInfo");
+  m_dbMgr.setZoneInfo(zone, "ksk", kskCert.wireEncode());
+  m_dbMgr.setZoneInfo(zone, "dsk", dskCert.wireEncode());
+
+  NDNS_LOG_INFO("Start saving DKEY certificate id to ZoneInfo");
+  m_dbMgr.setZoneInfo(zone, "dkey", dkeyCert.wireEncode());
+
+  return zone;
 }
 
 void
@@ -146,7 +195,7 @@
   //check pre-conditions
   Zone zone(zoneName);
   if (!m_dbMgr.find(zone)) {
-    throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+    BOOST_THROW_EXCEPTION(Error(zoneName.toUri() + " is not presented in the NDNS db"));
   }
 
   //first remove all rrsets of this zone from local ndns database
@@ -162,37 +211,34 @@
 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);
+  // only search in local NDNS database
+  security::v2::Certificate cert;
+  shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<NDNS>(<>+)<CERT><>");
+  if (!regex->match(certName)) {
+    BOOST_THROW_EXCEPTION(Error("Certificate name is illegal"));
+    return;
+  }
+
+  Name zoneName = regex->expand("\\1");
+  Name identityName = Name(zoneName).append(label::NDNS_CERT_QUERY);
+  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)) {
+    cert = security::v2::Certificate(rrset.getData());
   }
   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());
-    }
+    BOOST_THROW_EXCEPTION(Error("Cannot find the cert: " + certName.toUri()));
   }
 
   if (outFile == DEFAULT_IO) {
-    ndn::io::save(*cert, std::cout);
+    ndn::io::save(cert, std::cout);
   }
   else {
-    ndn::io::save(*cert, outFile);
+    ndn::io::save(cert, outFile);
     NDNS_LOG_INFO("save cert to file: " << outFile);
   }
 }
@@ -253,7 +299,7 @@
 ManagementTool::addRrset(Rrset& rrset)
 {
   if (rrset.getLabel().size() > 1) {
-    throw Error("Cannot add rrset with label size > 1, should use addMultiLevelLabelRrset instead");
+    BOOST_THROW_EXCEPTION(Error("Cannot add rrset with label size > 1, should use addMultiLevelLabelRrset instead"));
   }
 
   // check that it does not override existing AUTH
@@ -280,26 +326,27 @@
 {
   //check precondition
   Zone zone(zoneName);
+  Name zoneIdentityName = Name(zoneName).append(label::NDNS_CERT_QUERY);
   if (!m_dbMgr.find(zone)) {
-    throw Error(zoneName.toUri() + " is not presented in the NDNS db");
+    BOOST_THROW_EXCEPTION(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);
+    dskName = CertHelper::getDefaultKeyNameOfIdentity(m_keyChain, zoneIdentityName);
+    dskCertName = CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, zoneIdentityName);
   }
   else {
-    if (!matchCertificate(dskCertName, zoneName)) {
-      throw Error("Cannot verify certificate");
+    if (!matchCertificate(dskCertName, zoneIdentityName)) {
+      BOOST_THROW_EXCEPTION(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");
+      BOOST_THROW_EXCEPTION(Error("Data: " + inFile + " does not exist"));
     }
   }
 
@@ -311,7 +358,7 @@
     data = ndn::io::load<ndn::Data>(inFile, encoding);
 
   if (data == nullptr) {
-    throw Error("input does not contain a valid Data packet");
+    BOOST_THROW_EXCEPTION(Error("input does not contain a valid Data packet"));
   }
 
   if (needResign) {
@@ -335,16 +382,23 @@
   rrset.setData(data->wireEncode());
 
   checkRrsetVersion(rrset);
-  NDNS_LOG_INFO("Added " << rrset);
+  NDNS_LOG_INFO("Adding rrset from file " << rrset);
   m_dbMgr.insert(rrset);
 }
 
+security::v2::Certificate
+ManagementTool::getZoneDkey(Zone& zone)
+{
+  std::map<std::string, Block> zoneInfo = m_dbMgr.getZoneInfo(zone);
+  return security::v2::Certificate(zoneInfo["dkey"]);
+}
+
 void
 ManagementTool::listZone(const Name& zoneName, std::ostream& os, const bool printRaw)
 {
   Zone zone(zoneName);
   if (!m_dbMgr.find(zone)) {
-    throw Error("Zone " + zoneName.toUri() + " is not found in the database");
+    BOOST_THROW_EXCEPTION(Error("Zone " + zoneName.toUri() + " is not found in the database"));
   }
 
   //first output the zone name
@@ -383,7 +437,7 @@
                     || re.getContentType() == NDNS_KEY
                     || re.getContentType() == NDNS_AUTH ? 1 : re.getRrs().size();
 
-    const std::vector<Block> &rrs = re.getRrs();
+    const std::vector<Block>& rrs = re.getRrs();
 
     if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
       os << "; rrset=" << rrset.getLabel().toUri()
@@ -405,7 +459,6 @@
       os << rrset.getType().toUri();
 
       if (re.getContentType() != NDNS_BLOB && re.getContentType() != NDNS_KEY) {
-        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;
@@ -415,20 +468,20 @@
           if (re.getContentType() == NDNS_AUTH) {
             const std::string authStr = "NDNS-Auth";
             os << authStr;
-          } else {
+          }
+          else {
             Link link(rrset.getData());
-            const Link::DelegationSet& ds = link.getDelegations();
+            const DelegationList& ds = link.getDelegationList();
             for (const auto& i: ds) {
-              std::string str = boost::lexical_cast<std::string>(i.first)
-                + "," + i.second.toUri() + ";";
+              std::string str = std::to_string(i.preference);
+                + "," + i.name.toUri() + ";";
               os << str;
             }
           }
           os << std::endl;
         }
         else {
-          StringSource ss(rrs[i].wire(), rrs[i].size(), true,
-                          new Base64Encoder(new FileSink(os), true, 64));
+          bufferSource(rrs[i].wire(), rrs[i].size()) >> base64Encode() >> streamSink(os);
         }
       }
     }
@@ -442,17 +495,15 @@
 
       if (printRaw && (re.getContentType() == NDNS_BLOB
                        || re.getContentType() == NDNS_KEY)) {
-        util::IndentedStream istream(os, "; ");
+        ndn::util::IndentedStream istream(os, "; ");
 
         if (re.getRrType() == label::CERT_RR_TYPE) {
-          shared_ptr<Data> data = re.toData();
-          IdentityCertificate cert(*data);
-          cert.printCertificate(istream);
+          security::v2::Certificate cert(rrset.getData());
+          os << cert;
+          // cert.printCertificate(istream);
         }
         else {
-          using namespace CryptoPP;
-          StringSource ss(re.getAppContent().wire(), re.getAppContent().size(), true,
-                          new Base64Encoder(new FileSink(istream), true, 64));
+          bufferSource(re.getAppContent().wire(), re.getAppContent().size()) >> base64Encode() >> streamSink(os);
         }
       }
       os << std::endl;
@@ -477,11 +528,12 @@
     os.setf(os.left);
     os.width(nameWidth + 2);
     os << zone.getName().toUri();
+    Name zoneIdentity = Name(zone.getName()).append(label::NDNS_CERT_QUERY);
 
     os << "; default-ttl=" << zone.getTtl().count();
-    os << " default-key=" << m_keyChain.getDefaultKeyNameForIdentity(zone.getName());
+    os << " default-key=" << CertHelper::getDefaultKeyNameOfIdentity(m_keyChain, zoneIdentity);
     os << " default-certificate="
-       << m_keyChain.getDefaultCertificateNameForIdentity(zone.getName());
+       << CertHelper::getDefaultCertificateNameOfIdentity(m_keyChain, zoneIdentity);
     os << std::endl;
   }
 }
@@ -518,39 +570,39 @@
     return;
   }
 
-  using namespace CryptoPP;
-  StringSource ss(rrset.getData().wire(), rrset.getData().size(), true,
-                  new Base64Encoder(new FileSink(os), true, 64));
+  bufferSource(rrset.getData().wire(), rrset.getData().size()) >> base64Encode() >> streamSink(os);
 }
 
 void
-ManagementTool::addIdCert(Zone& zone, shared_ptr<IdentityCertificate> cert,
-                          const time::seconds& ttl)
+ManagementTool::addIdCert(Zone& zone, const Certificate& cert,
+                          const time::seconds& ttl,
+                          const Certificate& dskCert)
 {
-  Rrset rrset(&zone);
+  Rrset rrsetKey(&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());
+  Name label = cert.getName().getSubName(size + 1, cert.getName().size() - size - 3);
+  rrsetKey.setLabel(label);
+  rrsetKey.setType(label::CERT_RR_TYPE);
+  rrsetKey.setTtl(ttl);
+  rrsetKey.setVersion(cert.getName().get(-1));
+  rrsetKey.setData(cert.wireEncode());
 
-  if (m_dbMgr.find(rrset)) {
-    throw Error("ID-CERT with label=" + label.toUri() +
-                " is already presented in local NDNS databse");
+  if (m_dbMgr.find(rrsetKey)) {
+    BOOST_THROW_EXCEPTION(Error("CERT with label=" + label.toUri() +
+                                " is already presented in local NDNS databse"));
   }
+
+  m_dbMgr.insert(rrsetKey);
   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");
+    BOOST_THROW_EXCEPTION(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);
@@ -569,26 +621,15 @@
 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;
+  security::Identity id = m_keyChain.getPib().getIdentity(identity);
+  for (const security::Key& key: id.getKeys()) {
+    try {
+      key.getCertificate(certName);
+      return true;
+    } catch (const std::exception&) {
+    }
   }
-
-  //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, KeyClass::PRIVATE)) {
-    NDNS_LOG_WARN("Private key: " << keyName.toUri() << " is not present in KeyChain");
-    return false;
-  }
-
-  return true;
+  return false;
 }
 
 void
@@ -598,10 +639,12 @@
   if (m_dbMgr.find(originalRrset)) {
     // update only if rrset has a newer version
     if (originalRrset.getVersion() == rrset.getVersion()) {
-      throw Error("Duplicate: " + boost::lexical_cast<std::string>(originalRrset));
+      BOOST_THROW_EXCEPTION(Error("Duplicate: "
+                                  + boost::lexical_cast<std::string>(originalRrset)));
     }
     else if (originalRrset.getVersion() > rrset.getVersion()) {
-      throw Error("Newer version exists: " + boost::lexical_cast<std::string>(originalRrset));
+      BOOST_THROW_EXCEPTION(Error("Newer version exists: "
+                                  + boost::lexical_cast<std::string>(originalRrset)));
     }
 
     m_dbMgr.remove(originalRrset);
diff --git a/src/mgmt/management-tool.hpp b/src/mgmt/management-tool.hpp
index efa8138..4c50c16 100644
--- a/src/mgmt/management-tool.hpp
+++ b/src/mgmt/management-tool.hpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2014-2017, Regents of the University of California.
  *
  * This file is part of NDNS (Named Data Networking Domain Name Service).
@@ -30,8 +30,7 @@
 
 #include <stdexcept>
 #include <ndn-cxx/common.hpp>
-#include <ndn-cxx/security/v1/identity-certificate.hpp>
-#include <ndn-cxx/security/v1/key-chain.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
 #include <ndn-cxx/util/io.hpp>
 
 namespace ndn {
@@ -77,7 +76,7 @@
    *  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.
+   *  2. Local NDNS database: an 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.
@@ -97,21 +96,23 @@
    *  @param kskCertName if given, a zone will be created with this ksk certificate
    *  @param dskCertName if given, a zone will be created with this dsk certificate and provided
    *                     ksk certificate will be ignored
+   *  @param dkeyCertName if given, ksk will be signed by this d-key.
    */
-  void
+  Zone
   createZone(const Name& zoneName,
              const Name& parentZoneName,
              const time::seconds& cacheTtl = DEFAULT_CACHE_TTL,
              const time::seconds& certValidity = DEFAULT_CERT_TTL,
              const Name& kskCertName = DEFAULT_CERT,
-             const Name& dskCertName = DEFAULT_CERT);
+             const Name& dskCertName = DEFAULT_CERT,
+             const Name& dkeyCertName = 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
+   *  3) Local NDNS database: delete the CERT of the zone's DSK
    */
   void
   deleteZone(const Name& zoneName);
@@ -205,6 +206,9 @@
            const name::Component& type,
            std::ostream& os);
 
+  security::v2::Certificate
+  getZoneDkey(Zone& zone);
+
   /** @brief generates an output like DNS zone file. Reference:
    *  http://en.wikipedia.org/wiki/Zone_file
    *
@@ -224,10 +228,12 @@
   listAllZones(std::ostream& os);
 
 private:
-  /** @brief add ID-CERT to the NDNS local database
+  /** @brief add CERT to the NDNS local database
    */
   void
-  addIdCert(Zone& zone, shared_ptr<IdentityCertificate> cert, const time::seconds& ttl);
+  addIdCert(Zone& zone, const ndn::security::v2::Certificate& cert,
+            const time::seconds& ttl,
+            const ndn::security::v2::Certificate& dskCertName);
 
   /** @brief add zone to the NDNS local database
    */
diff --git a/src/ndns-label.hpp b/src/ndns-label.hpp
index 63df2ad..93713d7 100644
--- a/src/ndns-label.hpp
+++ b/src/ndns-label.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -45,9 +45,9 @@
 // const name::Component NDNS_RECURSIVE_QUERY("NDNS-R");
 
 /**
- * @brief NDNS ID-CERT query type
+ * @brief NDNS CERT query type
  */
-const name::Component NDNS_CERT_QUERY("KEY");
+const name::Component NDNS_CERT_QUERY("NDNS");
 
 /////////////////////////////////////////////
 
@@ -65,9 +65,9 @@
 const name::Component NS_RR_TYPE("NS");
 
 /**
- * @brief ID-CERT resource record type
+ * @brief CERT resource record type
  */
-const name::Component CERT_RR_TYPE("ID-CERT");
+const name::Component CERT_RR_TYPE("CERT");
 
 /**
  * @brief TXT resource record type
diff --git a/src/util/cert-helper.cpp b/src/util/cert-helper.cpp
new file mode 100644
index 0000000..b4f3cab
--- /dev/null
+++ b/src/util/cert-helper.cpp
@@ -0,0 +1,126 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014-2017, 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 "cert-helper.hpp"
+
+namespace ndn {
+namespace ndns {
+
+security::Identity
+CertHelper::getIdentity(const KeyChain& keyChain, const Name& identityName)
+{
+  return keyChain.getPib().getIdentity(identityName);
+}
+
+bool
+CertHelper::doesIdentityExist(const KeyChain& keyChain, const Name& identityName)
+{
+  try {
+    keyChain.getPib().getIdentity(identityName);
+    return true;
+  } catch (const std::exception&) {
+    return false;
+  }
+}
+
+security::v2::Certificate
+CertHelper::getCertificate(const KeyChain& keyChain,
+                           const Name& identity,
+                           const Name& certName)
+{
+  security::Identity id = keyChain.getPib().getIdentity(identity);
+  for (const auto& key : id.getKeys()) {
+    for (const auto& cert : key.getCertificates()) {
+      if (cert.getName() == certName) {
+        return cert;
+      }
+    }
+  }
+  BOOST_THROW_EXCEPTION(std::runtime_error(certName.toUri() + " does not exist"));
+}
+
+Name
+CertHelper::getIdentityNameFromCert(const Name& certName)
+{
+  static Name::Component keyComp("KEY");
+  for (size_t i = 0; i < certName.size(); ++i) {
+    if (certName.get(i) == keyComp) {
+      return certName.getPrefix(i);
+    }
+  }
+  BOOST_THROW_EXCEPTION(std::runtime_error(certName.toUri() + " is not a legal cert name"));
+}
+
+security::v2::Certificate
+CertHelper::getCertificate(const KeyChain& keyChain,
+                           const Name& certName)
+{
+  Name identityName = getIdentityNameFromCert(certName);
+  return getCertificate(keyChain, identityName, certName);
+}
+
+const Name&
+CertHelper::getDefaultKeyNameOfIdentity(const KeyChain& keyChain, const Name& identityName)
+{
+  return getIdentity(keyChain, identityName).getDefaultKey().getName();
+}
+
+const Name&
+CertHelper::getDefaultCertificateNameOfIdentity(const KeyChain& keyChain, const Name& identityName)
+{
+  return getIdentity(keyChain, identityName).getDefaultKey()
+                                            .getDefaultCertificate()
+                                            .getName();
+}
+
+security::v2::Certificate
+CertHelper::createCertificate(KeyChain& keyChain,
+                              const security::Key& key,
+                              const security::Key& signingKey,
+                              const std::string& issuer,
+                              const time::seconds& certValidity)
+{
+  Name certificateName = key.getName();
+  certificateName
+    .append(issuer)
+    .appendVersion();
+  security::v2::Certificate certificate;
+  certificate.setName(certificateName);
+
+  // set metainfo
+  certificate.setContentType(ndn::tlv::ContentType_Key);
+  certificate.setFreshnessPeriod(time::hours(1));
+
+  // set content
+  certificate.setContent(key.getPublicKey().data(), key.getPublicKey().size());
+
+  // set signature-info
+  // to overcome the round-up issue in ndn-cxx setPeriod (notBefore is round up to the the next whole second)
+  // notBefore = now() - 1 second
+  SignatureInfo info;
+  info.setValidityPeriod(security::ValidityPeriod(time::system_clock::now() - time::seconds(1),
+                                                  time::system_clock::now() + certValidity));
+
+  keyChain.sign(certificate, signingByKey(signingKey).setSignatureInfo(info));
+  return certificate;
+}
+
+} // namespace ndns
+} // namespace ndn
+
diff --git a/src/util/cert-helper.hpp b/src/util/cert-helper.hpp
new file mode 100644
index 0000000..8e7297f
--- /dev/null
+++ b/src/util/cert-helper.hpp
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014-2017, 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_UTIL_CERT_HELPER_HPP
+#define NDNS_UTIL_CERT_HELPER_HPP
+
+#include "common.hpp"
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/security/signing-helpers.hpp>
+
+namespace ndn {
+namespace ndns {
+
+class CertHelper
+{
+public:
+  static security::Identity
+  getIdentity(const KeyChain& keyChain, const Name& identityName);
+
+  static bool
+  doesIdentityExist(const KeyChain& keyChain, const Name& identityName);
+
+  static Name
+  getIdentityNameFromCert(const Name& certName);
+
+  static security::v2::Certificate
+  getCertificate(const KeyChain& keyChain,
+                 const Name& identity,
+                 const Name& certName);
+
+  static security::v2::Certificate
+  getCertificate(const KeyChain& keyChain,
+                 const Name& certName);
+
+  static const Name&
+  getDefaultKeyNameOfIdentity(const KeyChain& keyChain, const Name& identityName);
+
+  static const Name&
+  getDefaultCertificateNameOfIdentity(const KeyChain& keyChain, const Name& identityName);
+
+  static security::v2::Certificate
+  createCertificate(KeyChain& keyChain,
+                    const security::Key& key,
+                    const security::Key& signingKey,
+                    const std::string& issuer,
+                    const time::seconds& certValidity = time::days(10));
+};
+
+
+} // namespace ndns
+} // namespace ndn
+
+#endif // NDNS_UTIL_CERT_HELPER_HPP
diff --git a/src/util/util.cpp b/src/util/util.cpp
index 3c8adb8..47fbc52 100644
--- a/src/util/util.cpp
+++ b/src/util/util.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -18,11 +18,16 @@
  */
 
 #include "util.hpp"
-#include <ndn-cxx/security/v1/cryptopp.hpp>
+
+#include <ndn-cxx/security/transform.hpp>
 
 namespace ndn {
 namespace ndns {
 
+using security::transform::base64Encode;
+using security::transform::streamSink;
+using security::transform::bufferSource;
+
 NdnsContentType
 toNdnsContentType(const std::string& str)
 {
@@ -45,17 +50,14 @@
 void
 output(const Data& data, std::ostream& os, const bool isPretty)
 {
-  using namespace CryptoPP;
   const Block& block = data.wireEncode();
   if (!isPretty) {
-    StringSource ss(block.wire(), block.size(), true,
-                    new Base64Encoder(new FileSink(os), true, 64));
+    bufferSource(block.wire(), block.size()) >> base64Encode() >> streamSink(os);
   }
   else {
     os << "Name: " << data.getName().toUri() << std::endl;
     os << "KeyLocator: " << data.getSignature().getKeyLocator().getName().toUri() << std::endl;
-    StringSource ss(block.wire(), block.size(), true,
-                    new Base64Encoder(new FileSink(os), true, 64));
+    bufferSource(block.wire(), block.size()) >> base64Encode() >> streamSink(os);
     os << std::endl;
   }
 }
diff --git a/src/validator.cpp b/src/validator.cpp
index 71c9680..9eb9a2e 100644
--- a/src/validator.cpp
+++ b/src/validator.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -17,106 +17,30 @@
  * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "validator.hpp"
 #include "logger.hpp"
 #include "config.hpp"
-#include "validator.hpp"
 
-#include "ndn-cxx/data.hpp"
-#include <ndn-cxx/security/validator-config.hpp>
-
+#include <ndn-cxx/security/v2/validation-policy-config.hpp>
+#include <ndn-cxx/security/v2/certificate-fetcher-from-network.hpp>
 
 namespace ndn {
 namespace ndns {
 
 NDNS_LOG_INIT("validator")
 
-std::string Validator::VALIDATOR_CONF_FILE = DEFAULT_CONFIG_PATH "/" "validator.conf";
+std::string NdnsValidatorBuilder::VALIDATOR_CONF_FILE = DEFAULT_CONFIG_PATH "/" "validator.conf";
 
-Validator::Validator(Face& face, const std::string& confFile /* = VALIDATOR_CONF_FILE */)
-  : ValidatorConfig(face)
+unique_ptr<security::v2::Validator>
+NdnsValidatorBuilder::create(Face& face, const std::string& confFile)
 {
-  try {
-    this->load(confFile);
-    NDNS_LOG_TRACE("Validator loads configuration: " << confFile);
-  }
-  catch (std::exception&) {
-    std::string config =
-      "rule                                                                       \n"
-      "{                                                                          \n"
-      "  id \"NDNS Validator\"                                                    \n"
-      "  for data                                                                 \n"
-      "  checker                                                                  \n"
-      "  {                                                                        \n"
-      "    type customized                                                        \n"
-      "    sig-type rsa-sha256                                                    \n"
-      "    key-locator                                                            \n"
-      "    {                                                                      \n"
-      "      type name                                                            \n"
-      "      hyper-relation                                                       \n"
-      "      {                                                                    \n"
-      "        k-regex ^(<>*)<KEY>(<>*)<><ID-CERT>$                               \n"
-      "        k-expand \\\\1\\\\2                                                \n"
-      "        h-relation is-prefix-of                                            \n"
-      "        p-regex ^(<>*)[<KEY><NDNS>](<>*)<><>$                              \n"
-      "        p-expand \\\\1\\\\2                                                \n"
-      "      }                                                                    \n"
-      "    }                                                                      \n"
-      "  }                                                                        \n"
-      "}                                                                          \n"
-      "                                                                           \n"
-      "                                                                           \n"
-      "trust-anchor                                                               \n"
-      "{                                                                          \n"
-      "  type file                                                                \n"
-      "  file-name \""
-      ;
+  auto validator = make_unique<security::v2::Validator>(make_unique<security::v2::ValidationPolicyConfig>(),
+                                                        make_unique<security::v2::CertificateFetcherFromNetwork>(face));
+  security::v2::ValidationPolicyConfig& policy = dynamic_cast<security::v2::ValidationPolicyConfig&>(validator->getPolicy());
+  policy.load(confFile);
+  NDNS_LOG_TRACE("Validator loads configuration: " << confFile);
 
-    config += DEFAULT_CONFIG_PATH "/" "anchors/root.cert";
-
-    config +=
-      "\"                                                                         \n"
-      "}                                                                          \n"
-      "                                                                           \n"
-      ;
-
-    this->load(config, "embededConf");
-    NDNS_LOG_TRACE("Validator loads embedded configuration with anchors path: anchors/root.cert");
-  }
-
-}
-
-void
-Validator::validate(const Data& data,
-                    const OnDataValidated& onValidated,
-                    const OnDataValidationFailed& onValidationFailed)
-{
-  NDNS_LOG_TRACE("[* ?? *] verify data: " << data.getName() << ". KeyLocator: "
-                 << data.getSignature().getKeyLocator().getName());
-  ValidatorConfig::validate(data,
-                            [this, onValidated] (const shared_ptr<const Data>& data) {
-                              this->onDataValidated(data);
-                              onValidated(data);
-                            },
-                            [this, onValidationFailed] (const shared_ptr<const Data>& data,
-                                                        const std::string& str) {
-                              this->onDataValidationFailed(data, str);
-                              onValidationFailed(data, str);
-                            }
-                            );
-}
-
-void
-Validator::onDataValidated(const shared_ptr<const Data>& data)
-{
-  NDNS_LOG_TRACE("[* VV *] pass validation: " << data->getName() << ". KeyLocator = "
-                 << data->getSignature().getKeyLocator().getName());
-}
-
-void
-Validator::onDataValidationFailed(const shared_ptr<const Data>& data, const std::string& str)
-{
-  NDNS_LOG_WARN("[* XX *] fail validation: " << data->getName() << ". due to: " << str
-                << ". KeyLocator = " << data->getSignature().getKeyLocator().getName());
+  return validator;
 }
 
 } // namespace ndns
diff --git a/src/validator.hpp b/src/validator.hpp
index 030c1fb..d082c38 100644
--- a/src/validator.hpp
+++ b/src/validator.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, Regents of the University of California.
+/*
+ * Copyright (c) 2014-2017, 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.
@@ -22,63 +22,21 @@
 
 #include "config.hpp"
 
-#include "ndn-cxx/data.hpp"
-#include <ndn-cxx/security/validator-config.hpp>
-
+#include <ndn-cxx/data.hpp>
+#include <ndn-cxx/security/v2/validator.hpp>
 
 namespace ndn {
 namespace ndns {
 
-/**
- * @brief NDNS validator, which validates Data with hierarchical way. Validator is used in three
- * scenarios:
- * 1) Dig client gets the final response Data;
- * 2) Authoritative name server receives update request;
- * 3) Update client gets the result of update request.
- *
- * @note Compared to its parent class, ValidatorConfig, the class provides is customized according
- * to config file and the above working scenarios:
- * 1) give the default path of config file;
- * 2) default rule is the given path if not valid or the content is wrong.
- *    Validator rule is must for NDNS, the daemon/dig/update must work even without manually edit
- * 3) some wrapper provides default behavior when verification succeeds or fails
- */
-class Validator : public ValidatorConfig
+class NdnsValidatorBuilder
 {
-
 public:
   static std::string VALIDATOR_CONF_FILE;
 
-  /**
-   * @brief the callback function which is called after validation finishes
-   */
-  explicit
-  Validator(Face& face, const std::string& confFile = VALIDATOR_CONF_FILE);
-
-  /**
-   * @brief validate the Data
-   */
-  virtual void
-  validate(const Data& data,
-           const OnDataValidated& onValidated,
-           const OnDataValidationFailed& onValidationFailed);
-
-private:
-  /**
-   * @brief the default callback function on data validated
-   */
-  void
-  onDataValidated(const shared_ptr<const Data>& data);
-
-  /**
-   * @brief the default callback function on data validation failed
-   */
-  void
-  onDataValidationFailed(const shared_ptr<const Data>& data, const std::string& str);
-
+  static unique_ptr<security::v2::Validator>
+  create(Face& face, const std::string& confFile = VALIDATOR_CONF_FILE);
 };
 
-
 } // namespace ndns
 } // namespace ndn