security: Move PIB-related code into security/pib/

Change-Id: I94ea7ce646e66382f7c534ca1c8d6cbeeb87b1a4
diff --git a/src/security/pib/certificate-container.cpp b/src/security/pib/certificate-container.cpp
new file mode 100644
index 0000000..a05dd52
--- /dev/null
+++ b/src/security/pib/certificate-container.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "certificate-container.hpp"
+#include "pib-impl.hpp"
+
+namespace ndn {
+namespace security {
+
+CertificateContainer::const_iterator::const_iterator(std::set<Name>::const_iterator it,
+                                                     shared_ptr<PibImpl> impl)
+  : m_it(it)
+  , m_impl(impl)
+{
+}
+
+v1::IdentityCertificate
+CertificateContainer::const_iterator::operator*()
+{
+  return m_impl->getCertificate(*m_it);
+}
+
+CertificateContainer::const_iterator&
+CertificateContainer::const_iterator::operator++()
+{
+  ++m_it;
+  return *this;
+}
+
+CertificateContainer::const_iterator
+CertificateContainer::const_iterator::operator++(int)
+{
+  const_iterator it(m_it, m_impl);
+  ++m_it;
+  return it;
+}
+
+bool
+CertificateContainer::const_iterator::operator==(const const_iterator& other)
+{
+  return (m_impl == other.m_impl && m_it == other.m_it);
+}
+
+bool
+CertificateContainer::const_iterator::operator!=(const const_iterator& other)
+{
+  return !(*this == other);
+}
+
+CertificateContainer::CertificateContainer()
+{
+}
+
+CertificateContainer::CertificateContainer(std::set<Name>&& certNames,
+                                           shared_ptr<PibImpl> impl)
+  : m_certNames(certNames)
+  , m_impl(impl)
+{
+}
+
+CertificateContainer::const_iterator
+CertificateContainer::begin() const
+{
+  return const_iterator(m_certNames.begin(), m_impl);
+}
+
+CertificateContainer::const_iterator
+CertificateContainer::end() const
+{
+  return const_iterator(m_certNames.end(), m_impl);
+}
+
+CertificateContainer::const_iterator
+CertificateContainer::find(const Name& certName) const
+{
+  return const_iterator(m_certNames.find(certName), m_impl);
+}
+
+size_t
+CertificateContainer::size() const
+{
+  return m_certNames.size();
+}
+
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/certificate-container.hpp b/src/security/pib/certificate-container.hpp
new file mode 100644
index 0000000..8e77e43
--- /dev/null
+++ b/src/security/pib/certificate-container.hpp
@@ -0,0 +1,93 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_CERTIFICATE_CONTAINER_HPP
+#define NDN_SECURITY_PIB_CERTIFICATE_CONTAINER_HPP
+
+#include <set>
+#include "../v1/identity-certificate.hpp"
+
+namespace ndn {
+namespace security {
+
+class PibImpl;
+
+/// @brief A handler to search or enumerate certificates of a key.
+class CertificateContainer
+{
+public:
+  class const_iterator
+  {
+  public:
+    friend class CertificateContainer;
+
+  public:
+    v1::IdentityCertificate
+    operator*();
+
+    const_iterator&
+    operator++();
+
+    const_iterator
+    operator++(int);
+
+    bool
+    operator==(const const_iterator& other);
+
+    bool
+    operator!=(const const_iterator& other);
+
+  private:
+    const_iterator(std::set<Name>::const_iterator it, shared_ptr<PibImpl> impl);
+
+  private:
+    std::set<Name>::const_iterator m_it;
+    shared_ptr<PibImpl> m_impl;
+  };
+
+  typedef const_iterator iterator;
+
+public:
+  CertificateContainer();
+
+  CertificateContainer(std::set<Name>&& certNames, shared_ptr<PibImpl> impl);
+
+  const_iterator
+  begin() const;
+
+  const_iterator
+  end() const;
+
+  const_iterator
+  find(const Name& certName) const;
+
+  size_t
+  size() const;
+
+private:
+  std::set<Name> m_certNames;
+  shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_CERTIFICATE_CONTAINER_HPP
diff --git a/src/security/pib/identity-container.cpp b/src/security/pib/identity-container.cpp
new file mode 100644
index 0000000..605be8b
--- /dev/null
+++ b/src/security/pib/identity-container.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "identity-container.hpp"
+#include "pib-impl.hpp"
+
+namespace ndn {
+namespace security {
+
+IdentityContainer::const_iterator::const_iterator(std::set<Name>::const_iterator it,
+                                                  shared_ptr<PibImpl> impl)
+  : m_it(it)
+  , m_impl(impl)
+{
+}
+
+Identity
+IdentityContainer::const_iterator::operator*()
+{
+  return Identity(*m_it, m_impl);
+}
+
+IdentityContainer::const_iterator&
+IdentityContainer::const_iterator::operator++()
+{
+  ++m_it;
+  return *this;
+}
+
+IdentityContainer::const_iterator
+IdentityContainer::const_iterator::operator++(int)
+{
+  const_iterator it(*this);
+  ++m_it;
+  return it;
+}
+
+bool
+IdentityContainer::const_iterator::operator==(const const_iterator& other)
+{
+  return (m_impl == other.m_impl && m_it == other.m_it);
+}
+
+bool
+IdentityContainer::const_iterator::operator!=(const const_iterator& other)
+{
+  return !(*this == other);
+}
+
+IdentityContainer::IdentityContainer()
+{
+}
+
+IdentityContainer::IdentityContainer(std::set<Name>&& identities,
+                                     shared_ptr<PibImpl> impl)
+  : m_identities(identities)
+  , m_impl(impl)
+{
+}
+
+IdentityContainer::const_iterator
+IdentityContainer::begin() const
+{
+  return const_iterator(m_identities.begin(), m_impl);
+}
+
+IdentityContainer::const_iterator
+IdentityContainer::end() const
+{
+  return const_iterator(m_identities.end(), m_impl);
+}
+
+IdentityContainer::const_iterator
+IdentityContainer::find(const Name& identity) const
+{
+  return const_iterator(m_identities.find(identity), m_impl);
+}
+
+size_t
+IdentityContainer::size() const
+{
+  return m_identities.size();
+}
+
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/identity-container.hpp b/src/security/pib/identity-container.hpp
new file mode 100644
index 0000000..1de18c7
--- /dev/null
+++ b/src/security/pib/identity-container.hpp
@@ -0,0 +1,94 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_IDENTITY_CONTAINER_HPP
+#define NDN_SECURITY_PIB_IDENTITY_CONTAINER_HPP
+
+#include <set>
+#include "identity.hpp"
+
+namespace ndn {
+namespace security {
+
+class PibImpl;
+
+/// @brief A handler to search or enumerate identities in PIB.
+class IdentityContainer
+{
+public:
+  class const_iterator
+  {
+  public:
+    friend class IdentityContainer;
+
+  public:
+    Identity
+    operator*();
+
+    const_iterator&
+    operator++();
+
+    const_iterator
+    operator++(int);
+
+    bool
+    operator==(const const_iterator& other);
+
+    bool
+    operator!=(const const_iterator& other);
+
+  private:
+    const_iterator(std::set<Name>::const_iterator it, shared_ptr<PibImpl> impl);
+
+  private:
+    Name m_identity;
+    std::set<Name>::const_iterator m_it;
+    shared_ptr<PibImpl> m_impl;
+  };
+
+  typedef const_iterator iterator;
+
+public:
+  IdentityContainer();
+
+  IdentityContainer(std::set<Name>&& identities, shared_ptr<PibImpl> impl);
+
+  const_iterator
+  begin() const;
+
+  const_iterator
+  end() const;
+
+  const_iterator
+  find(const Name& keyId) const;
+
+  size_t
+  size() const;
+
+private:
+  std::set<Name> m_identities;
+  shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_IDENTITY_CONTAINER_HPP
diff --git a/src/security/pib/identity.cpp b/src/security/pib/identity.cpp
new file mode 100644
index 0000000..176814c
--- /dev/null
+++ b/src/security/pib/identity.cpp
@@ -0,0 +1,164 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "identity.hpp"
+#include "pib-impl.hpp"
+#include "pib.hpp"
+
+namespace ndn {
+namespace security {
+
+const name::Component Identity::EMPTY_KEY_ID;
+
+Identity::Identity()
+  : m_hasDefaultKey(false)
+  , m_needRefreshKeys(false)
+  , m_impl(nullptr)
+{
+}
+
+Identity::Identity(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit)
+  : m_name(identityName)
+  , m_hasDefaultKey(false)
+  , m_needRefreshKeys(true)
+  , m_impl(impl)
+{
+  validityCheck();
+
+  if (needInit)
+    m_impl->addIdentity(m_name);
+  else if (!m_impl->hasIdentity(m_name))
+    BOOST_THROW_EXCEPTION(Pib::Error("Identity: " + m_name.toUri() + " does not exist"));
+}
+
+const Name&
+Identity::getName() const
+{
+  validityCheck();
+
+  return m_name;
+}
+
+Key
+Identity::addKey(const v1::PublicKey& publicKey, const name::Component& keyId)
+{
+  validityCheck();
+
+  name::Component actualKeyId = keyId;
+  if (actualKeyId == EMPTY_KEY_ID) {
+    const Block& digest = publicKey.computeDigest();
+    actualKeyId = name::Component(digest.wire(), digest.size());
+  }
+
+  if (!m_needRefreshKeys && m_keys.find(actualKeyId) == m_keys.end()) {
+    // if we have already loaded all the keys, but the new key is not one of them
+    // the KeyContainer should be refreshed
+    m_needRefreshKeys = true;
+  }
+
+  return Key(m_name, actualKeyId, publicKey, m_impl);
+}
+
+void
+Identity::removeKey(const name::Component& keyId)
+{
+  validityCheck();
+
+  if (m_hasDefaultKey && m_defaultKey.getKeyId() == keyId)
+    m_hasDefaultKey = false;
+
+  m_impl->removeKey(m_name, keyId);
+  m_needRefreshKeys = true;
+}
+
+Key
+Identity::getKey(const name::Component& keyId) const
+{
+  validityCheck();
+
+  return Key(m_name, keyId, m_impl);
+}
+
+const KeyContainer&
+Identity::getKeys() const
+{
+  validityCheck();
+
+  if (m_needRefreshKeys) {
+    m_keys = KeyContainer(m_name, m_impl->getKeysOfIdentity(m_name), m_impl);
+    m_needRefreshKeys = false;
+  }
+
+  return m_keys;
+}
+
+Key&
+Identity::setDefaultKey(const name::Component& keyId)
+{
+  validityCheck();
+
+  m_defaultKey = Key(m_name, keyId, m_impl);
+  m_hasDefaultKey = true;
+
+  m_impl->setDefaultKeyOfIdentity(m_name, keyId);
+  return m_defaultKey;
+}
+
+Key&
+Identity::setDefaultKey(const v1::PublicKey& publicKey, const name::Component& keyId)
+{
+  const Key& keyEntry = addKey(publicKey, keyId);
+  return setDefaultKey(keyEntry.getKeyId());
+}
+
+Key&
+Identity::getDefaultKey() const
+{
+  validityCheck();
+
+  if (!m_hasDefaultKey) {
+    m_defaultKey = Key(m_name, m_impl->getDefaultKeyOfIdentity(m_name), m_impl);
+    m_hasDefaultKey = true;
+  }
+
+  return m_defaultKey;
+}
+
+Identity::operator bool() const
+{
+  return !(this->operator!());
+}
+
+bool
+Identity::operator!() const
+{
+  return (m_impl == nullptr);
+}
+
+void
+Identity::validityCheck() const
+{
+  if (m_impl == nullptr)
+    BOOST_THROW_EXCEPTION(std::domain_error("Invalid Identity instance"));
+}
+
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/identity.hpp b/src/security/pib/identity.hpp
new file mode 100644
index 0000000..3c081ef
--- /dev/null
+++ b/src/security/pib/identity.hpp
@@ -0,0 +1,194 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_IDENTITY_HPP
+#define NDN_SECURITY_PIB_IDENTITY_HPP
+
+#include "key-container.hpp"
+
+namespace ndn {
+namespace security {
+
+class PibImpl;
+class Pib;
+class IdentityContainer;
+
+/**
+ * @brief represents an identity
+ *
+ * Identity is at the top level in PIB's Identity-Key-Certificate hierarchy.
+ * An identity has a Name, and contains one or more keys, one of which is set
+ * as the default key of this identity.  Properties of a key can be accessed
+ * after obtaining a Key object.
+ *
+ * @throw PibImpl::Error when underlying implementation has non-semantic error.
+ */
+class Identity
+{
+public:
+  friend class Pib;
+  friend class IdentityContainer;
+  friend class KeyChain;
+
+public:
+  /**
+   * @brief Default Constructor
+   *
+   * Identity created using this default constructor is just a place holder.
+   * It must obtain an actual instance from Pib::getIdentity(...).  A typical
+   * usage would be for exception handling:
+   *
+   *   Identity id;
+   *   try {
+   *     id = pib.getIdentity(...);
+   *   }
+   *   catch (Pib::Error&) {
+   *     ...
+   *   }
+   *
+   * An Identity instance created using the constructor is invalid. Calling a
+   * member method on an invalid Identity instance may cause an std::domain_error.
+   */
+  Identity();
+
+  /// @brief Get the name of the identity.
+  const Name&
+  getName() const;
+
+  /**
+   * @brief Get a key with id @p keyId.
+   *
+   * @param keyId The id of the key to get.
+   * @throw Pib::Error if the key does not exist.
+   */
+  Key
+  getKey(const name::Component& keyId) const;
+
+  /// @brief Get all the keys for this Identity.
+  const KeyContainer&
+  getKeys() const;
+
+  /**
+   * @brief Get the default key for this Identity.
+   *
+   * @throws Pib::Error if the default key does not exist.
+   */
+  Key&
+  getDefaultKey() const;
+
+  /// @brief Check if the Identity instance is valid
+  operator bool() const;
+
+  /// @brief Check if the Identity instance is invalid
+  bool
+  operator!() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
+
+  /**
+   * @brief Add a key.
+   *
+   * If the key already exists, do nothing.
+   *
+   * If no default key is set before, the new key will be set as the default key of the identity.
+   *
+   * @param publicKey The public key to add.
+   * @param keyId The key id component of the new key to add.
+   *              By default, the keyId will be set to the hash of the public key bits.
+   * @return the added key or existing key with the same key id.
+   */
+  Key
+  addKey(const v1::PublicKey& publicKey, const name::Component& keyId = EMPTY_KEY_ID);
+
+  /**
+   * @brief Remove a key.
+   *
+   * @param keyId The key id component of the key to delete.
+   */
+  void
+  removeKey(const name::Component& keyId);
+
+  /**
+   * @brief Set the key with id @p keyId as the default key.
+   *
+   * @param keyId The key id component of the default key.
+   * @return The default key
+   * @throws Pib::Error if the key does not exist.
+   */
+  Key&
+  setDefaultKey(const name::Component& keyId);
+
+  /**
+   * @brief Set the default key.
+   *
+   * If the key does not exist, add the key and set it as the default of the Identity.
+   * If the key exists, simply set it as the default key of the Identity.
+   *
+   * @param publicKey The public key to add.
+   * @param keyId The key id component of the default key.
+   * @return the default key
+   */
+  Key&
+  setDefaultKey(const v1::PublicKey& publicKey, const name::Component& keyId = EMPTY_KEY_ID);
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+  /**
+   * @brief Create an Identity with @p identityName.
+   *
+   * @param identityName The name of the Identity.
+   * @param impl The backend implementation.
+   * @param needInit If true, create the identity in backend when the identity does not exist.
+   *                 Otherwise, throw Pib::Error when the identity does not exist.
+   */
+  Identity(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit = false);
+
+  /**
+   * @brief Check the validity of this instance
+   *
+   * @throws std::domain_error if the instance is invalid
+   */
+  void
+  validityCheck() const;
+
+public:
+  /**
+   * @brief The default value of keyId when add a new key.
+   *
+   * An empty keyId implies that the key digest should be used as the actual keyId.
+   */
+  static const name::Component EMPTY_KEY_ID;
+
+private:
+  Name m_name;
+
+  mutable bool m_hasDefaultKey;
+  mutable Key m_defaultKey;
+
+  mutable bool m_needRefreshKeys;
+  mutable KeyContainer m_keys;
+
+  shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_IDENTITY_HPP
diff --git a/src/security/pib/key-container.cpp b/src/security/pib/key-container.cpp
new file mode 100644
index 0000000..ca30ab9
--- /dev/null
+++ b/src/security/pib/key-container.cpp
@@ -0,0 +1,108 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "key-container.hpp"
+#include "pib-impl.hpp"
+
+namespace ndn {
+namespace security {
+
+KeyContainer::const_iterator::const_iterator(const Name& identity,
+                                             std::set<name::Component>::const_iterator it,
+                                             shared_ptr<PibImpl> impl)
+  : m_identity(identity)
+  , m_it(it)
+  , m_impl(impl)
+{
+}
+
+Key
+KeyContainer::const_iterator::operator*()
+{
+  return Key(m_identity, *m_it, m_impl);
+}
+
+KeyContainer::const_iterator&
+KeyContainer::const_iterator::operator++()
+{
+  ++m_it;
+  return *this;
+}
+
+KeyContainer::const_iterator
+KeyContainer::const_iterator::operator++(int)
+{
+  const_iterator it(*this);
+  ++m_it;
+  return it;
+}
+
+bool
+KeyContainer::const_iterator::operator==(const const_iterator& other)
+{
+  return (m_impl == other.m_impl && m_identity == other.m_identity && m_it == other.m_it);
+}
+
+bool
+KeyContainer::const_iterator::operator!=(const const_iterator& other)
+{
+  return !(*this == other);
+}
+
+KeyContainer::KeyContainer()
+{
+}
+
+KeyContainer::KeyContainer(const Name& identity,
+                           std::set<name::Component>&& keyIds,
+                           shared_ptr<PibImpl> impl)
+  : m_identity(identity)
+  , m_keyIds(keyIds)
+  , m_impl(impl)
+{
+}
+
+KeyContainer::const_iterator
+KeyContainer::begin() const
+{
+  return const_iterator(m_identity, m_keyIds.begin(), m_impl);
+}
+
+KeyContainer::const_iterator
+KeyContainer::end() const
+{
+  return const_iterator(m_identity, m_keyIds.end(), m_impl);
+}
+
+KeyContainer::const_iterator
+KeyContainer::find(const name::Component& keyId) const
+{
+  return const_iterator(m_identity, m_keyIds.find(keyId), m_impl);
+}
+
+size_t
+KeyContainer::size() const
+{
+  return m_keyIds.size();
+}
+
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/key-container.hpp b/src/security/pib/key-container.hpp
new file mode 100644
index 0000000..7d88da9
--- /dev/null
+++ b/src/security/pib/key-container.hpp
@@ -0,0 +1,99 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_KEY_CONTAINER_HPP
+#define NDN_SECURITY_PIB_KEY_CONTAINER_HPP
+
+#include <set>
+#include "key.hpp"
+
+namespace ndn {
+namespace security {
+
+class PibImpl;
+
+/// @brief A handler to search or enumerate keys of an identity.
+class KeyContainer
+{
+public:
+  class const_iterator
+  {
+  public:
+    friend class KeyContainer;
+
+  public:
+    Key
+    operator*();
+
+    const_iterator&
+    operator++();
+
+    const_iterator
+    operator++(int);
+
+    bool
+    operator==(const const_iterator& other);
+
+    bool
+    operator!=(const const_iterator& other);
+
+  private:
+    const_iterator(const Name& identity,
+                   std::set<name::Component>::const_iterator it,
+                   shared_ptr<PibImpl> impl);
+
+  private:
+    Name m_identity;
+    std::set<name::Component>::const_iterator m_it;
+    shared_ptr<PibImpl> m_impl;
+  };
+
+  typedef const_iterator iterator;
+
+public:
+  KeyContainer();
+
+  KeyContainer(const Name& identity,
+               std::set<name::Component>&& keyIds,
+               shared_ptr<PibImpl> impl);
+
+  const_iterator
+  begin() const;
+
+  const_iterator
+  end() const;
+
+  const_iterator
+  find(const name::Component& keyId) const;
+
+  size_t
+  size() const;
+
+private:
+  Name m_identity;
+  std::set<name::Component> m_keyIds;
+  shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_KEY_CONTAINER_HPP
diff --git a/src/security/pib/key.cpp b/src/security/pib/key.cpp
new file mode 100644
index 0000000..c59a39d
--- /dev/null
+++ b/src/security/pib/key.cpp
@@ -0,0 +1,200 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "key.hpp"
+#include "pib-impl.hpp"
+#include "pib.hpp"
+
+namespace ndn {
+namespace security {
+
+Key::Key()
+  : m_hasDefaultCertificate(false)
+  , m_needRefreshCerts(false)
+  , m_impl(nullptr)
+{
+}
+
+Key::Key(const Name& identityName, const name::Component& keyId,
+         const v1::PublicKey& publicKey, shared_ptr<PibImpl> impl)
+  : m_id(identityName)
+  , m_keyId(keyId)
+  , m_key(publicKey)
+  , m_hasDefaultCertificate(false)
+  , m_needRefreshCerts(true)
+  , m_impl(impl)
+{
+  validityCheck();
+
+  m_keyName = m_id;
+  m_keyName.append(m_keyId);
+
+  m_impl->addIdentity(m_id);
+  m_impl->addKey(m_id, m_keyId, publicKey);
+}
+
+Key::Key(const Name& identityName, const name::Component& keyId,
+         shared_ptr<PibImpl> impl)
+  : m_id(identityName)
+  , m_keyId(keyId)
+  , m_hasDefaultCertificate(false)
+  , m_needRefreshCerts(true)
+  , m_impl(impl)
+{
+  validityCheck();
+
+  m_keyName = m_id;
+  m_keyName.append(m_keyId);
+
+  m_key = m_impl->getKeyBits(m_id, m_keyId);
+}
+
+const Name&
+Key::getName() const
+{
+  validityCheck();
+
+  return m_keyName;
+}
+
+const Name&
+Key::getIdentity() const
+{
+  validityCheck();
+
+  return m_id;
+}
+
+const name::Component&
+Key::getKeyId() const
+{
+  validityCheck();
+
+  return m_keyId;
+}
+
+const v1::PublicKey&
+Key::getPublicKey() const
+{
+  validityCheck();
+
+  return m_key;
+}
+
+void
+Key::addCertificate(const v1::IdentityCertificate& certificate)
+{
+  validityCheck();
+
+  if (!m_needRefreshCerts &&
+      m_certificates.find(certificate.getName()) == m_certificates.end()) {
+    // if we have already loaded all the certificate, but the new certificate is not one of them
+    // the CertificateContainer should be refreshed
+    m_needRefreshCerts = true;
+  }
+
+  m_impl->addCertificate(certificate);
+}
+
+void
+Key::removeCertificate(const Name& certName)
+{
+  validityCheck();
+
+  if (m_hasDefaultCertificate && m_defaultCertificate.getName() == certName)
+    m_hasDefaultCertificate = false;
+
+  m_impl->removeCertificate(certName);
+  m_needRefreshCerts = true;
+}
+
+v1::IdentityCertificate
+Key::getCertificate(const Name& certName) const
+{
+  validityCheck();
+
+  return m_impl->getCertificate(certName);
+}
+
+const CertificateContainer&
+Key::getCertificates() const
+{
+  validityCheck();
+
+  if (m_needRefreshCerts) {
+    m_certificates = CertificateContainer(m_impl->getCertificatesOfKey(m_id, m_keyId), m_impl);
+    m_needRefreshCerts = false;
+  }
+
+  return m_certificates;
+}
+
+const v1::IdentityCertificate&
+Key::setDefaultCertificate(const Name& certName)
+{
+  validityCheck();
+
+  m_defaultCertificate = m_impl->getCertificate(certName);
+  m_impl->setDefaultCertificateOfKey(m_id, m_keyId, certName);
+  m_hasDefaultCertificate = true;
+  return m_defaultCertificate;
+}
+
+const v1::IdentityCertificate&
+Key::setDefaultCertificate(const v1::IdentityCertificate& certificate)
+{
+  addCertificate(certificate);
+  return setDefaultCertificate(certificate.getName());
+}
+
+const v1::IdentityCertificate&
+Key::getDefaultCertificate() const
+{
+  validityCheck();
+
+  if (!m_hasDefaultCertificate) {
+    m_defaultCertificate = m_impl->getDefaultCertificateOfKey(m_id, m_keyId);
+    m_hasDefaultCertificate = true;
+  }
+
+  return m_defaultCertificate;
+}
+
+Key::operator bool() const
+{
+  return !(this->operator!());
+}
+
+bool
+Key::operator!() const
+{
+  return (m_impl == nullptr);
+}
+
+void
+Key::validityCheck() const
+{
+  if (m_impl == nullptr)
+    BOOST_THROW_EXCEPTION(std::domain_error("Invalid Key instance"));
+}
+
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/key.hpp b/src/security/pib/key.hpp
new file mode 100644
index 0000000..7118149
--- /dev/null
+++ b/src/security/pib/key.hpp
@@ -0,0 +1,207 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_KEY_HPP
+#define NDN_SECURITY_PIB_KEY_HPP
+
+#include "../v1/identity-certificate.hpp"
+#include "certificate-container.hpp"
+
+namespace ndn {
+namespace security {
+
+class PibImpl;
+class Identity;
+class KeyContainer;
+
+/**
+ * @brief represents a key
+ *
+ * Key is at the second level in PIB's Identity-Key-Certificate hierarchy.
+ * An Key has a Name (identity + keyId), and contains one or more certificates,
+ * one of which is set as the default certificate of this key.  A certificate
+ * can be directly accessed from a Key object.
+ *
+ * @throw PibImpl::Error when underlying implementation has non-semantic error.
+ */
+class Key
+{
+public:
+  friend class Identity;
+  friend class KeyContainer;
+  friend class KeyChain;
+
+public:
+  /**
+   * @brief Default Constructor
+   *
+   * Key created using this default constructor is just a place holder.
+   * It must obtain an actual instance from Identity::getKey(...).  A typical
+   * usage would be for exception handling:
+   *
+   *   Key key;
+   *   try {
+   *     key = Identity.getKey(...);
+   *   }
+   *   catch (Pib::Error&) {
+   *     ...
+   *   }
+   *
+   * A Key instance created using the constructor is invalid. Calling a
+   * member method on an invalid Key instance may cause an std::domain_error.
+   */
+  Key();
+
+  /// @brief Get the name of the key.
+  const Name&
+  getName() const;
+
+  /// @brief Get the name of the belonging identity.
+  const Name&
+  getIdentity() const;
+
+  /// @brief Get the key id of the key.
+  const name::Component&
+  getKeyId() const;
+
+  /// @brief Get public key
+  const v1::PublicKey&
+  getPublicKey() const;
+
+  /**
+   * @brief Get a certificate.
+   *
+   * @return the certificate
+   * @throws Pib::Error if the certificate does not exist.
+   */
+  v1::IdentityCertificate
+  getCertificate(const Name& certName) const;
+
+  /// @brief Get all the certificates for this key.
+  const CertificateContainer&
+  getCertificates() const;
+
+  /**
+   * @brief Get the default certificate for this Key.
+   *
+   * @throws Pib::Error if the default certificate does not exist.
+   */
+  const v1::IdentityCertificate&
+  getDefaultCertificate() const;
+
+  /// @brief Check if the Key instance is valid
+  operator bool() const;
+
+  /// @brief Check if the Key instance is invalid
+  bool
+  operator!() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
+
+  /**
+   * @brief Add a certificate.
+   *
+   * @param certificate The certificate to add.
+   */
+  void
+  addCertificate(const v1::IdentityCertificate& certificate);
+
+  /**
+   * @brief Remove a certificate.
+   *
+   * @param certName The name of the certificate to delete.
+   */
+  void
+  removeCertificate(const Name& certName);
+
+  /**
+   * @brief Set the default certificate.
+   *
+   * @param certName The name of the default certificate of the key.
+   * @return the default certificate
+   * @throws Pib::Error if the certificate does not exist.
+   */
+  const v1::IdentityCertificate&
+  setDefaultCertificate(const Name& certName);
+
+  /**
+   * @brief Set the default certificate.
+   *
+   * If the certificate does not exist, add it and set it as the default certificate of the key.
+   * If the certificate exists, simply set it as the default certificate of the key.
+   *
+   * @param certificate The certificate to add.
+   * @return the default certificate
+   */
+  const v1::IdentityCertificate&
+  setDefaultCertificate(const v1::IdentityCertificate& certificate);
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+  /**
+   * @brief Create a Key with @p identityName and @p keyId.
+   *
+   * If the key/identity does not exist in the backend, create it in backend.
+   *
+   * @param identityName The name of the Identity.
+   * @param keyId The key id of the key.
+   * @param publicKey The public key to add.
+   * @param impl The actual backend implementation.
+   */
+  Key(const Name& identityName, const name::Component& keyId,
+      const v1::PublicKey& publicKey, shared_ptr<PibImpl> impl);
+
+  /**
+   * @brief Create an KeyEntry with @p identityName and @p keyId.
+   *
+   * @param identityName The name of the Identity.
+   * @param keyId The key id of the key.
+   * @param impl The actual backend implementation.
+   * @throws Pib::Error if the key does not exist.
+   */
+  Key(const Name& identityName, const name::Component& keyId, shared_ptr<PibImpl> impl);
+
+  /**
+   * @brief Check the validity of this instance
+   *
+   * @throws std::domain_error if the instance is invalid
+   */
+  void
+  validityCheck() const;
+
+private:
+  Name m_id;
+  name::Component m_keyId;
+  Name m_keyName;
+  v1::PublicKey m_key;
+
+  mutable bool m_hasDefaultCertificate;
+  mutable v1::IdentityCertificate m_defaultCertificate;
+
+  mutable bool m_needRefreshCerts;
+  mutable CertificateContainer m_certificates;
+
+  shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_PIB_HPP
diff --git a/src/security/pib/pib-impl.hpp b/src/security/pib/pib-impl.hpp
new file mode 100644
index 0000000..7aa47a2
--- /dev/null
+++ b/src/security/pib/pib-impl.hpp
@@ -0,0 +1,304 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_PIB_IMPL_HPP
+#define NDN_SECURITY_PIB_PIB_IMPL_HPP
+
+#include <set>
+#include "../v1/identity-certificate.hpp"
+
+namespace ndn {
+namespace security {
+
+/**
+ * @brief Abstract class of PIB implementation
+ *
+ * This class defines the interface that an actual PIB (e.g., one based on sqlite3)
+ * implementation should provide.
+ */
+class PibImpl
+{
+public:
+  /**
+   * @brief represents a non-semantic error
+   *
+   * A subclass of PibImpl may throw a subclass of this type when
+   * there's a non-semantic error, such as a storage problem.
+  */
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+public:
+
+  virtual
+  ~PibImpl()
+  {
+  }
+
+public: // TpmLocator management
+
+  /**
+   * @brief Set the corresponding TPM information to @p tpmLocator.
+   *
+   * If the provided @p tpmLocator is different from the existing one, the
+   * content in PIB will be cleaned up, otherwise nothing will be changed.
+   *
+   * @param tpmLocator The name for the new TPM locator
+   */
+  virtual void
+  setTpmLocator(const std::string& tpmLocator) = 0;
+
+  /**
+   * @brief Get TPM Locator
+   */
+  virtual std::string
+  getTpmLocator() const = 0;
+
+public: // Identity management
+
+  /**
+   * @brief Check the existence of an identity.
+   *
+   * @param identity The name of the identity.
+   * @return true if the identity exists, otherwise false.
+   */
+  virtual bool
+  hasIdentity(const Name& identity) const = 0;
+
+  /**
+   * @brief Add an identity.
+   *
+   * If the identity already exists, do nothing.
+   * If no default identity has been set, set the added one as default identity.
+   *
+   * @param identity The name of the identity to add.
+   */
+  virtual void
+  addIdentity(const Name& identity) = 0;
+
+  /**
+   * @brief Remove an identity
+   *
+   * If the identity does not exist, do nothing.
+   * Remove related keys and certificates as well.
+   *
+   * @param identity The name of the identity to remove.
+   */
+  virtual void
+  removeIdentity(const Name& identity) = 0;
+
+  /// @brief Get the name of all the identities
+  virtual std::set<Name>
+  getIdentities() const = 0;
+
+  /**
+   * @brief Set an identity with name @p identityName as the default identity.
+   *
+   * Since adding an identity only requires the identity name, create the
+   * identity if it does not exist.
+   *
+   * @param identityName The name for the default identity.
+   */
+  virtual void
+  setDefaultIdentity(const Name& identityName) = 0;
+
+  /**
+   * @brief Get the default identity.
+   *
+   * @return The name for the default identity.
+   * @throws Pib::Error if no default identity.
+   */
+  virtual Name
+  getDefaultIdentity() const = 0;
+
+public: // Key management
+
+  /**
+   * @brief Check the existence of a key.
+   *
+   * @param identity The name of the belonged identity.
+   * @param keyId The key id component.
+   * @return true if the key exists, otherwise false. Return false if the identity does not exist
+   */
+  virtual bool
+  hasKey(const Name& identity, const name::Component& keyId) const = 0;
+
+  /**
+   * @brief Add a key.
+   *
+   * If the key already exists, do nothing.
+   * If the identity does not exist, add the identity as well.
+   * If no default key of the identity has been set, set the added one as default
+   * key of the identity.
+   *
+   * @param identity The name of the belonged identity.
+   * @param keyId The key id component.
+   * @param publicKey The public key bits.
+   */
+  virtual void
+  addKey(const Name& identity, const name::Component& keyId, const v1::PublicKey& publicKey) = 0;
+
+  /**
+   * @brief Remove a key.
+   *
+   * If the key does not exist, do nothing.
+   * Remove related certificates as well.
+   *
+   * @param identity The name of the belonged identity.
+   * @param keyId The key id component.
+   */
+  virtual void
+  removeKey(const Name& identity, const name::Component& keyId) = 0;
+
+  /**
+   * @brief Get the key bits of a key.
+   *
+   * @param identity The name of the belonged identity.
+   * @param keyId The key id component.
+   * @return key bits
+   * @throws Pib::Error if the key does not exist.
+   */
+  virtual v1::PublicKey
+  getKeyBits(const Name& identity, const name::Component& keyId) const = 0;
+
+  /**
+   * @brief Get all the key ids of an identity with name @p identity
+   *
+   * The returned key ids can be used to create a KeyContainer.
+   * With key id, identity name, backend implementation, one can create a Key frontend instance.
+   *
+   * @return the key id name component set. If the identity does not exist, return an empty set.
+   */
+  virtual std::set<name::Component>
+  getKeysOfIdentity(const Name& identity) const = 0;
+
+  /**
+   * @brief Set an key with id @p keyId as the default key of an identity with name @p identity.
+   *
+   * @param identity The name of the belonged identity.
+   * @param keyId The key id component.
+   * @throws Pib::Error if the key does not exist.
+   */
+  virtual void
+  setDefaultKeyOfIdentity(const Name& identity, const name::Component& keyId) = 0;
+
+  /**
+   * @brief Get the id of the default key of an identity with name @p identity.
+   *
+   * @param identity The name of the belonged identity.
+   * @throws Pib::Error if no default key or the identity does not exist.
+   */
+  virtual name::Component
+  getDefaultKeyOfIdentity(const Name& identity) const = 0;
+
+public: // Certificate Management
+
+  /**
+   * @brief Check the existence of a certificate with name @p certName.
+   *
+   * @param certName The name of the certificate.
+   * @return true if the certificate exists, otherwise false.
+   */
+  virtual bool
+  hasCertificate(const Name& certName) const = 0;
+
+  /**
+   * @brief Add a certificate.
+   *
+   * If the certificate already exists, do nothing.
+   * If the key or identity do not exist, add them as well.
+   * If no default certificate of the key has been set, set the added one as
+   * default certificate of the key.
+   *
+   * @param certificate The certificate to add.
+   */
+  virtual void
+  addCertificate(const v1::IdentityCertificate& certificate) = 0;
+
+  /**
+   * @brief Remove a certificate with name @p certName.
+   *
+   * If the certificate does not exist, do nothing.
+   *
+   * @param certName The name of the certificate.
+   */
+  virtual void
+  removeCertificate(const Name& certName) = 0;
+
+  /**
+   * @brief Get a certificate with name @p certName.
+   *
+   * @param certName The name of the certificate.
+   * @return the certificate.
+   * @throws Pib::Error if the certificate does not exist.
+   */
+  virtual v1::IdentityCertificate
+  getCertificate(const Name& certName) const = 0;
+
+  /**
+   * @brief Get a list of certificate names of a key with id @p keyId of @p identity.
+   *
+   * The returned certificate names can be used to create a CertificateContainer.
+   * With certificate name and backend implementation, one can obtain the certificate directly.
+   *
+   * @param identity The name of the belonging identity.
+   * @param keyId The key id.
+   * @return The certificate name set. If the key does not exist, return an empty set.
+   */
+  virtual std::set<Name>
+  getCertificatesOfKey(const Name& identity, const name::Component& keyId) const = 0;
+
+  /**
+   * @brief Set a cert with name @p certName as the default of a key with id @p keyId of @p identity.
+   *
+   * @param identity The name of the belonging identity.
+   * @param keyId The key id.
+   * @param certName The name of the certificate.
+   * @throws Pib::Error if the certificate with name @p certName does not exist.
+   */
+  virtual void
+  setDefaultCertificateOfKey(const Name& identity, const name::Component& keyId,
+                             const Name& certName) = 0;
+
+  /**
+   * @brief Get the default certificate of a key with id @p keyId of @p identity.
+   *
+   * @param identity The name of the belonging identity.
+   * @param keyId The key id.
+   * @return a pointer to the certificate, null if no default certificate for the key.
+   * @throws Pib::Error if the default certificate does not exist.
+   */
+  virtual v1::IdentityCertificate
+  getDefaultCertificateOfKey(const Name& identity, const name::Component& keyId) const = 0;
+
+};
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_PIB_IMPL_HPP
diff --git a/src/security/pib/pib-memory.cpp b/src/security/pib/pib-memory.cpp
new file mode 100644
index 0000000..c472863
--- /dev/null
+++ b/src/security/pib/pib-memory.cpp
@@ -0,0 +1,257 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "pib-memory.hpp"
+#include "pib.hpp"
+
+namespace ndn {
+namespace security {
+
+PibMemory::PibMemory()
+  : m_hasDefaultIdentity(false)
+{
+}
+
+void
+PibMemory::setTpmLocator(const std::string& tpmLocator)
+{
+  BOOST_THROW_EXCEPTION(Error("PibMemory does not need a locator"));
+}
+
+std::string
+PibMemory::getTpmLocator() const
+{
+  return "tpm-memory:";
+}
+
+bool
+PibMemory::hasIdentity(const Name& identity) const
+{
+  return (m_identities.count(identity) > 0);
+}
+
+void
+PibMemory::addIdentity(const Name& identity)
+{
+  m_identities.insert(identity);
+
+  if (!m_hasDefaultIdentity) {
+    m_defaultIdentity = identity;
+    m_hasDefaultIdentity = true;
+  }
+}
+
+void
+PibMemory::removeIdentity(const Name& identity)
+{
+  m_identities.erase(identity);
+  if (identity == m_defaultIdentity)
+    m_hasDefaultIdentity = false;
+
+  auto keyIds = this->getKeysOfIdentity(identity);
+  for (const name::Component& keyId : keyIds) {
+    this->removeKey(identity, keyId);
+  }
+}
+
+std::set<Name>
+PibMemory::getIdentities() const
+{
+  return m_identities;
+}
+
+void
+PibMemory::setDefaultIdentity(const Name& identityName)
+{
+  addIdentity(identityName);
+  m_defaultIdentity = identityName;
+  m_hasDefaultIdentity = true;
+}
+
+Name
+PibMemory::getDefaultIdentity() const
+{
+  if (m_hasDefaultIdentity)
+    return m_defaultIdentity;
+
+  BOOST_THROW_EXCEPTION(Pib::Error("No default identity"));
+}
+
+bool
+PibMemory::hasKey(const Name& identity, const name::Component& keyId) const
+{
+  return (m_keys.count(getKeyName(identity, keyId)) > 0);
+}
+
+void
+PibMemory::addKey(const Name& identity, const name::Component& keyId, const v1::PublicKey& publicKey)
+{
+  this->addIdentity(identity);
+
+  Name keyName = getKeyName(identity, keyId);
+  m_keys[keyName] = publicKey;
+
+  if (m_defaultKey.find(identity) == m_defaultKey.end())
+    m_defaultKey[identity] = keyName;
+}
+
+void
+PibMemory::removeKey(const Name& identity, const name::Component& keyId)
+{
+  Name keyName = getKeyName(identity, keyId);
+  m_keys.erase(keyName);
+  m_defaultKey.erase(identity);
+
+
+  auto certNames = this->getCertificatesOfKey(identity, keyId);
+  for (const auto& certName : certNames) {
+    this->removeCertificate(certName);
+  }
+}
+
+v1::PublicKey
+PibMemory::getKeyBits(const Name& identity, const name::Component& keyId) const
+{
+  if (!hasKey(identity, keyId))
+    BOOST_THROW_EXCEPTION(Pib::Error("No key"));
+
+  auto it = m_keys.find(getKeyName(identity, keyId));
+  return it->second;
+}
+
+std::set<name::Component>
+PibMemory::getKeysOfIdentity(const Name& identity) const
+{
+  std::set<name::Component> ids;
+  for (const auto& it : m_keys) {
+    if (identity == it.first.getPrefix(-1))
+      ids.insert(it.first.get(-1));
+  }
+  return ids;
+}
+
+void
+PibMemory::setDefaultKeyOfIdentity(const Name& identity, const name::Component& keyId)
+{
+  Name keyName = getKeyName(identity, keyId);
+
+  if (!hasKey(identity, keyId))
+    BOOST_THROW_EXCEPTION(Pib::Error("No key"));
+
+  m_defaultKey[identity] = keyName;
+}
+
+name::Component
+PibMemory::getDefaultKeyOfIdentity(const Name& identity) const
+{
+  auto it = m_defaultKey.find(identity);
+  if (it == m_defaultKey.end())
+    BOOST_THROW_EXCEPTION(Pib::Error("No default key"));
+
+  return it->second.get(-1);
+}
+
+Name
+PibMemory::getKeyName(const Name& identity, const name::Component& keyId) const
+{
+  Name keyName = identity;
+  keyName.append(keyId);
+  return keyName;
+}
+
+bool
+PibMemory::hasCertificate(const Name& certName) const
+{
+  return (m_certs.count(certName) > 0);
+}
+
+void
+PibMemory::addCertificate(const v1::IdentityCertificate& certificate)
+{
+  this->addKey(certificate.getPublicKeyName().getPrefix(-1),
+               certificate.getPublicKeyName().get(-1),
+               certificate.getPublicKeyInfo());
+
+  m_certs[certificate.getName()] = certificate;
+
+  const Name& keyName = certificate.getPublicKeyName();
+  if (m_defaultCert.find(keyName) == m_defaultCert.end())
+    m_defaultCert[keyName] = certificate.getName();
+}
+
+void
+PibMemory::removeCertificate(const Name& certName)
+{
+  m_certs.erase(certName);
+  m_defaultCert.erase(v1::IdentityCertificate::certificateNameToPublicKeyName(certName));
+}
+
+v1::IdentityCertificate
+PibMemory::getCertificate(const Name& certName) const
+{
+  if (!hasCertificate(certName))
+    BOOST_THROW_EXCEPTION(Pib::Error("No cert"));
+
+  auto it = m_certs.find(certName);
+  return it->second;
+}
+
+std::set<Name>
+PibMemory::getCertificatesOfKey(const Name& identity, const name::Component& keyId) const
+{
+  Name keyName = getKeyName(identity, keyId);
+
+  std::set<Name> certNames;
+  for (const auto& it : m_certs) {
+    if (it.second.getPublicKeyName() == keyName)
+      certNames.insert(it.first);
+  }
+  return certNames;
+}
+
+void
+PibMemory::setDefaultCertificateOfKey(const Name& identity, const name::Component& keyId, const Name& certName)
+{
+  if (!hasCertificate(certName))
+    BOOST_THROW_EXCEPTION(Pib::Error("No cert"));
+
+  Name keyName = getKeyName(identity, keyId);
+  m_defaultCert[keyName] = certName;
+}
+
+v1::IdentityCertificate
+PibMemory::getDefaultCertificateOfKey(const Name& identity, const name::Component& keyId) const
+{
+  Name keyName = getKeyName(identity, keyId);
+
+  auto it = m_defaultCert.find(keyName);
+  if (it == m_defaultCert.end())
+    BOOST_THROW_EXCEPTION(Pib::Error("No default certificate"));
+
+  auto certIt = m_certs.find(it->second);
+  if (certIt == m_certs.end())
+    BOOST_THROW_EXCEPTION(Pib::Error("No default certificate"));
+  else
+    return certIt->second;
+}
+
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/pib-memory.hpp b/src/security/pib/pib-memory.hpp
new file mode 100644
index 0000000..0cfe7c1
--- /dev/null
+++ b/src/security/pib/pib-memory.hpp
@@ -0,0 +1,153 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_PIB_MEMORY_HPP
+#define NDN_SECURITY_PIB_PIB_MEMORY_HPP
+
+#include "pib-impl.hpp"
+
+namespace ndn {
+namespace security {
+
+/**
+ * @brief An in-memory implementation of Pib
+ *
+ * All the contents in Pib are stored in memory
+ * and have the same lifetime as the implementation instance.
+ */
+class PibMemory : public PibImpl
+{
+public:
+  class Error : public PibImpl::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : PibImpl::Error(what)
+    {
+    }
+  };
+
+public:
+  PibMemory();
+
+public: // TpmLocator management
+
+  void
+  setTpmLocator(const std::string& tpmLocator) override;
+
+  std::string
+  getTpmLocator() const override;
+
+public: // Identity management
+
+  bool
+  hasIdentity(const Name& identity) const override;
+
+  void
+  addIdentity(const Name& identity) override;
+
+  void
+  removeIdentity(const Name& identity) override;
+
+  std::set<Name>
+  getIdentities() const override;
+
+  void
+  setDefaultIdentity(const Name& identityName) override;
+
+  Name
+  getDefaultIdentity() const override;
+
+public: // Key management
+
+  bool
+  hasKey(const Name& identity, const name::Component& keyId) const override;
+
+  void
+  addKey(const Name& identity, const name::Component& keyId, const v1::PublicKey& publicKey) override;
+
+  void
+  removeKey(const Name& identity, const name::Component& keyId) override;
+
+  v1::PublicKey
+  getKeyBits(const Name& identity, const name::Component& keyId) const override;
+
+  std::set<name::Component>
+  getKeysOfIdentity(const Name& identity) const override;
+
+  void
+  setDefaultKeyOfIdentity(const Name& identity, const name::Component& keyId) override;
+
+  name::Component
+  getDefaultKeyOfIdentity(const Name& identity) const override;
+
+public: // Certificate management
+
+  bool
+  hasCertificate(const Name& certName) const override;
+
+  void
+  addCertificate(const v1::IdentityCertificate& certificate) override;
+
+  void
+  removeCertificate(const Name& certName) override;
+
+  v1::IdentityCertificate
+  getCertificate(const Name& certName) const override;
+
+  std::set<Name>
+  getCertificatesOfKey(const Name& identity, const name::Component& keyId) const override;
+
+  void
+  setDefaultCertificateOfKey(const Name& identity, const name::Component& keyId, const Name& certName) override;
+
+  v1::IdentityCertificate
+  getDefaultCertificateOfKey(const Name& identity, const name::Component& keyId) const override;
+
+private: // Key management
+
+  Name
+  getKeyName(const Name& identity, const name::Component& keyId) const;
+
+private:
+
+  std::set<Name> m_identities;
+  bool m_hasDefaultIdentity;
+  Name m_defaultIdentity;
+
+  /// @brief keyName => keyBits
+  std::map<Name, v1::PublicKey> m_keys;
+
+  /// @brief identity => default key Name
+  std::map<Name, Name> m_defaultKey;
+
+  /// @brief certificate Name => certificate
+  std::map<Name, v1::IdentityCertificate> m_certs;
+
+  /// @brief keyName => default certificate Name
+  std::map<Name, Name> m_defaultCert;
+};
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_PIB_MEMORY_HPP
diff --git a/src/security/pib/pib-sqlite3.cpp b/src/security/pib/pib-sqlite3.cpp
new file mode 100644
index 0000000..dc21610
--- /dev/null
+++ b/src/security/pib/pib-sqlite3.cpp
@@ -0,0 +1,565 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "pib-sqlite3.hpp"
+
+#include "common.hpp"
+#include "pib.hpp"
+#include "util/sqlite3-statement.hpp"
+
+#include <sqlite3.h>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string.hpp>
+
+namespace ndn {
+namespace security {
+
+using std::string;
+using util::Sqlite3Statement;
+
+static const string INITIALIZATION =
+  "CREATE TABLE IF NOT EXISTS                    \n"
+  "  tpmInfo(                                    \n"
+  "    tpm_locator           BLOB                \n"
+  "  );                                          \n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  tpm_update_trigger                          \n"
+  "  BEFORE UPDATE ON tpmInfo                    \n"
+  "  WHEN NEW.tpm_locator!=OLD.tpm_locator       \n"
+  "  BEGIN                                       \n"
+  "    DELETE FROM certificates;                 \n"
+  "    DELETE FROM keys;                         \n"
+  "    DELETE FROM identities;                   \n"
+  "  END;                                        \n"
+  "                                              \n"
+  "                                              \n"
+  "CREATE TABLE IF NOT EXISTS                    \n"
+  "  identities(                                 \n"
+  "    id                    INTEGER PRIMARY KEY,\n"
+  "    identity              BLOB NOT NULL,      \n"
+  "    is_default            INTEGER DEFAULT 0   \n"
+  "  );                                          \n"
+  "                                              \n"
+  "CREATE UNIQUE INDEX IF NOT EXISTS             \n"
+  "  identityIndex ON identities(identity);      \n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  identity_default_before_insert_trigger      \n"
+  "  BEFORE INSERT ON identities                 \n"
+  "  FOR EACH ROW                                \n"
+  "  WHEN NEW.is_default=1                       \n"
+  "  BEGIN                                       \n"
+  "    UPDATE identities SET is_default=0;       \n"
+  "  END;                                        \n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  identity_default_after_insert_trigger       \n"
+  "  AFTER INSERT ON identities                  \n"
+  "  FOR EACH ROW                                \n"
+  "  WHEN NOT EXISTS                             \n"
+  "    (SELECT id                                \n"
+  "       FROM identities                        \n"
+  "       WHERE is_default=1)                    \n"
+  "  BEGIN                                       \n"
+  "    UPDATE identities                         \n"
+  "      SET is_default=1                        \n"
+  "      WHERE identity=NEW.identity;            \n"
+  "  END;                                        \n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  identity_default_update_trigger             \n"
+  "  BEFORE UPDATE ON identities                 \n"
+  "  FOR EACH ROW                                \n"
+  "  WHEN NEW.is_default=1 AND OLD.is_default=0  \n"
+  "  BEGIN                                       \n"
+  "    UPDATE identities SET is_default=0;       \n"
+  "  END;                                        \n"
+  "                                              \n"
+  "                                              \n"
+  "CREATE TABLE IF NOT EXISTS                    \n"
+  "  keys(                                       \n"
+  "    id                    INTEGER PRIMARY KEY,\n"
+  "    identity_id           INTEGER NOT NULL,   \n"
+  "    key_name              BLOB NOT NULL,      \n"
+  "    key_type              INTEGER NOT NULL,   \n"
+  "    key_bits              BLOB NOT NULL,      \n"
+  "    is_default            INTEGER DEFAULT 0,  \n"
+  "    FOREIGN KEY(identity_id)                  \n"
+  "      REFERENCES identities(id)               \n"
+  "      ON DELETE CASCADE                       \n"
+  "      ON UPDATE CASCADE                       \n"
+  "  );                                          \n"
+  "                                              \n"
+  "CREATE UNIQUE INDEX IF NOT EXISTS             \n"
+  "  keyIndex ON keys(key_name);                 \n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  key_default_before_insert_trigger           \n"
+  "  BEFORE INSERT ON keys                       \n"
+  "  FOR EACH ROW                                \n"
+  "  WHEN NEW.is_default=1                       \n"
+  "  BEGIN                                       \n"
+  "    UPDATE keys                               \n"
+  "      SET is_default=0                        \n"
+  "      WHERE identity_id=NEW.identity_id;      \n"
+  "  END;                                        \n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  key_default_after_insert_trigger            \n"
+  "  AFTER INSERT ON keys                        \n"
+  "  FOR EACH ROW                                \n"
+  "  WHEN NOT EXISTS                             \n"
+  "    (SELECT id                                \n"
+  "       FROM keys                              \n"
+  "       WHERE is_default=1                     \n"
+  "         AND identity_id=NEW.identity_id)     \n"
+  "  BEGIN                                       \n"
+  "    UPDATE keys                               \n"
+  "      SET is_default=1                        \n"
+  "      WHERE key_name=NEW.key_name;            \n"
+  "  END;                                        \n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  key_default_update_trigger                  \n"
+  "  BEFORE UPDATE ON keys                       \n"
+  "  FOR EACH ROW                                \n"
+  "  WHEN NEW.is_default=1 AND OLD.is_default=0  \n"
+  "  BEGIN                                       \n"
+  "    UPDATE keys                               \n"
+  "      SET is_default=0                        \n"
+  "      WHERE identity_id=NEW.identity_id;      \n"
+  "  END;                                        \n"
+  "                                              \n"
+  "                                              \n"
+  "CREATE TABLE IF NOT EXISTS                    \n"
+  "  certificates(                               \n"
+  "    id                    INTEGER PRIMARY KEY,\n"
+  "    key_id                INTEGER NOT NULL,   \n"
+  "    certificate_name      BLOB NOT NULL,      \n"
+  "    certificate_data      BLOB NOT NULL,      \n"
+  "    is_default            INTEGER DEFAULT 0,  \n"
+  "    FOREIGN KEY(key_id)                       \n"
+  "      REFERENCES keys(id)                     \n"
+  "      ON DELETE CASCADE                       \n"
+  "      ON UPDATE CASCADE                       \n"
+  "  );                                          \n"
+  "                                              \n"
+  "CREATE UNIQUE INDEX IF NOT EXISTS             \n"
+  "  certIndex ON certificates(certificate_name);\n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  cert_default_before_insert_trigger          \n"
+  "  BEFORE INSERT ON certificates               \n"
+  "  FOR EACH ROW                                \n"
+  "  WHEN NEW.is_default=1                       \n"
+  "  BEGIN                                       \n"
+  "    UPDATE certificates                       \n"
+  "      SET is_default=0                        \n"
+  "      WHERE key_id=NEW.key_id;                \n"
+  "  END;                                        \n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  cert_default_after_insert_trigger           \n"
+  "  AFTER INSERT ON certificates                \n"
+  "  FOR EACH ROW                                \n"
+  "  WHEN NOT EXISTS                             \n"
+  "    (SELECT id                                \n"
+  "       FROM certificates                      \n"
+  "       WHERE is_default=1                     \n"
+  "         AND key_id=NEW.key_id)               \n"
+  "  BEGIN                                       \n"
+  "    UPDATE certificates                       \n"
+  "      SET is_default=1                        \n"
+  "      WHERE certificate_name=NEW.certificate_name;\n"
+  "  END;                                        \n"
+  "                                              \n"
+  "CREATE TRIGGER IF NOT EXISTS                  \n"
+  "  cert_default_update_trigger                 \n"
+  "  BEFORE UPDATE ON certificates               \n"
+  "  FOR EACH ROW                                \n"
+  "  WHEN NEW.is_default=1 AND OLD.is_default=0  \n"
+  "  BEGIN                                       \n"
+  "    UPDATE certificates                       \n"
+  "      SET is_default=0                        \n"
+  "      WHERE key_id=NEW.key_id;                \n"
+  "  END;                                        \n";
+
+static Name
+getKeyName(const Name& identity, const name::Component& keyId)
+{
+  Name keyName = identity;
+  keyName.append(keyId);
+  return keyName;
+}
+
+PibSqlite3::PibSqlite3(const string& dir)
+{
+  // Determine the path of PIB DB
+  boost::filesystem::path actualDir;
+  if (dir == "") {
+#ifdef NDN_CXX_HAVE_TESTS
+    if (getenv("TEST_HOME") != nullptr) {
+      actualDir = boost::filesystem::path(getenv("TEST_HOME")) / ".ndn";
+    }
+    else
+#endif // NDN_CXX_HAVE_TESTS
+    if (getenv("HOME") != nullptr) {
+      actualDir = boost::filesystem::path(getenv("HOME")) / ".ndn";
+    }
+    else {
+      actualDir = boost::filesystem::path(".") / ".ndn";
+    }
+  }
+  else {
+    actualDir = boost::filesystem::path(dir);
+  }
+  boost::filesystem::create_directories(actualDir);
+
+  // Open PIB
+  int result = sqlite3_open_v2((actualDir / "pib.db").c_str(), &m_database,
+                               SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+#ifdef NDN_CXX_DISABLE_SQLITE3_FS_LOCKING
+                               "unix-dotfile"
+#else
+                               nullptr
+#endif
+                               );
+
+  if (result != SQLITE_OK)
+    BOOST_THROW_EXCEPTION(PibImpl::Error("PIB DB cannot be opened/created: " + dir));
+
+
+  // enable foreign key
+  sqlite3_exec(m_database, "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
+
+  // initialize PIB tables
+  char* errorMessage = nullptr;
+  result = sqlite3_exec(m_database, INITIALIZATION.c_str(), nullptr, nullptr, &errorMessage);
+  if (result != SQLITE_OK && errorMessage != nullptr) {
+    sqlite3_free(errorMessage);
+    BOOST_THROW_EXCEPTION(PibImpl::Error("PIB DB cannot be initialized"));
+  }
+}
+
+PibSqlite3::~PibSqlite3()
+{
+  sqlite3_close(m_database);
+}
+
+void
+PibSqlite3::setTpmLocator(const std::string& tpmLocator)
+{
+  Sqlite3Statement statement(m_database, "UPDATE tpmInfo SET tpm_locator=?");
+  statement.bind(1, tpmLocator, SQLITE_TRANSIENT);
+  statement.step();
+
+  // no row is updated, tpm_locator does not exist, insert it directly
+  if (0 == sqlite3_changes(m_database)) {
+    Sqlite3Statement insertStatement(m_database, "INSERT INTO tpmInfo (tpm_locator) values (?)");
+    insertStatement.bind(1, tpmLocator, SQLITE_TRANSIENT);
+    insertStatement.step();
+  }
+}
+
+std::string
+PibSqlite3::getTpmLocator() const
+{
+  Sqlite3Statement statement(m_database, "SELECT tpm_locator FROM tpmInfo");
+  int res = statement.step();
+
+  string tpmLocator;
+  if (res == SQLITE_ROW)
+    return statement.getString(0);
+  else
+    BOOST_THROW_EXCEPTION(Pib::Error("TPM info does not exist"));
+}
+
+bool
+PibSqlite3::hasIdentity(const Name& identity) const
+{
+  Sqlite3Statement statement(m_database, "SELECT id FROM identities WHERE identity=?");
+  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
+  return (statement.step() == SQLITE_ROW);
+}
+
+void
+PibSqlite3::addIdentity(const Name& identity)
+{
+  Sqlite3Statement statement(m_database, "INSERT INTO identities (identity) values (?)");
+  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
+  statement.step();
+}
+
+void
+PibSqlite3::removeIdentity(const Name& identity)
+{
+  Sqlite3Statement statement(m_database, "DELETE FROM identities WHERE identity=?");
+  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
+  statement.step();
+}
+
+std::set<Name>
+PibSqlite3::getIdentities() const
+{
+  std::set<Name> identities;
+  Sqlite3Statement statement(m_database, "SELECT identity FROM identities");
+
+  while (statement.step() == SQLITE_ROW)
+    identities.insert(Name(statement.getBlock(0)));
+
+  return identities;
+}
+
+void
+PibSqlite3::setDefaultIdentity(const Name& identityName)
+{
+  Sqlite3Statement statement(m_database, "UPDATE identities SET is_default=1 WHERE identity=?");
+  statement.bind(1, identityName.wireEncode(), SQLITE_TRANSIENT);
+  statement.step();
+}
+
+Name
+PibSqlite3::getDefaultIdentity() const
+{
+  Sqlite3Statement statement(m_database, "SELECT identity FROM identities WHERE is_default=1");
+
+  if (statement.step() == SQLITE_ROW)
+    return Name(statement.getBlock(0));
+  else
+    BOOST_THROW_EXCEPTION(Pib::Error("No default identity"));
+}
+
+bool
+PibSqlite3::hasKey(const Name& identity, const name::Component& keyId) const
+{
+  Name keyName = getKeyName(identity, keyId);
+
+  Sqlite3Statement statement(m_database, "SELECT id FROM keys WHERE key_name=?");
+  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
+
+  return (statement.step() == SQLITE_ROW);
+}
+
+void
+PibSqlite3::addKey(const Name& identity, const name::Component& keyId, const v1::PublicKey& publicKey)
+{
+  if (hasKey(identity, keyId)) {
+    return;
+  }
+
+  // ensure identity exists
+  addIdentity(identity);
+
+  // add key
+  Name keyName = getKeyName(identity, keyId);
+
+  Sqlite3Statement statement(m_database,
+                             "INSERT INTO keys (identity_id, key_name, key_type, key_bits) "
+                             "VALUES ((SELECT id FROM identities WHERE identity=?), ?, ?, ?)");
+  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
+  statement.bind(2, keyName.wireEncode(), SQLITE_TRANSIENT);
+  statement.bind(3, static_cast<int>(publicKey.getKeyType()));
+  statement.bind(4, publicKey.get().buf(), publicKey.get().size(), SQLITE_STATIC);
+  statement.step();
+}
+
+void
+PibSqlite3::removeKey(const Name& identity, const name::Component& keyId)
+{
+  Name keyName = getKeyName(identity, keyId);
+
+  Sqlite3Statement statement(m_database, "DELETE FROM keys WHERE key_name=?");
+  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
+  statement.step();
+}
+
+v1::PublicKey
+PibSqlite3::getKeyBits(const Name& identity, const name::Component& keyId) const
+{
+  Name keyName = getKeyName(identity, keyId);
+
+  Sqlite3Statement statement(m_database, "SELECT key_bits FROM keys WHERE key_name=?");
+  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
+
+  if (statement.step() == SQLITE_ROW)
+    return v1::PublicKey(statement.getBlob(0), statement.getSize(0));
+  else
+    BOOST_THROW_EXCEPTION(Pib::Error("Key does not exist"));
+}
+
+std::set<name::Component>
+PibSqlite3::getKeysOfIdentity(const Name& identity) const
+{
+  std::set<name::Component> keyNames;
+
+  Sqlite3Statement statement(m_database,
+                             "SELECT key_name "
+                             "FROM keys JOIN identities ON keys.identity_id=identities.id "
+                             "WHERE identities.identity=?");
+  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
+
+  while (statement.step() == SQLITE_ROW) {
+    Name keyName(statement.getBlock(0));
+    keyNames.insert(keyName.get(-1));
+  }
+
+  return keyNames;
+}
+
+void
+PibSqlite3::setDefaultKeyOfIdentity(const Name& identity, const name::Component& keyId)
+{
+  Name keyName = getKeyName(identity, keyId);
+
+  if (!hasKey(identity, keyId)) {
+    BOOST_THROW_EXCEPTION(Pib::Error("No such key"));
+  }
+
+  Sqlite3Statement statement(m_database, "UPDATE keys SET is_default=1 WHERE key_name=?");
+  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
+  statement.step();
+}
+
+name::Component
+PibSqlite3::getDefaultKeyOfIdentity(const Name& identity) const
+{
+  if (!hasIdentity(identity)) {
+    BOOST_THROW_EXCEPTION(Pib::Error("Identity does not exist"));
+  }
+
+  Sqlite3Statement statement(m_database,
+                             "SELECT key_name "
+                             "FROM keys JOIN identities ON keys.identity_id=identities.id "
+                             "WHERE identities.identity=? AND keys.is_default=1");
+  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
+
+  if (statement.step() == SQLITE_ROW) {
+    Name keyName(statement.getBlock(0));
+    return keyName.get(-1);
+  }
+  else
+    BOOST_THROW_EXCEPTION(Pib::Error("No default key"));
+}
+
+bool
+PibSqlite3::hasCertificate(const Name& certName) const
+{
+  Sqlite3Statement statement(m_database, "SELECT id FROM certificates WHERE certificate_name=?");
+  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
+  return (statement.step() == SQLITE_ROW);
+}
+
+void
+PibSqlite3::addCertificate(const v1::IdentityCertificate& certificate)
+{
+  const Name& certName = certificate.getName();
+  const Name& keyName = certificate.getPublicKeyName();
+
+  name::Component keyId = keyName.get(-1);
+  Name identityName = keyName.getPrefix(-1);
+
+  // ensure key exists
+  addKey(identityName, keyId, certificate.getPublicKeyInfo());
+
+  Sqlite3Statement statement(m_database,
+                             "INSERT INTO certificates "
+                             "(key_id, certificate_name, certificate_data) "
+                             "VALUES ((SELECT id FROM keys WHERE key_name=?), ?, ?)");
+  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
+  statement.bind(2, certName.wireEncode(), SQLITE_TRANSIENT);
+  statement.bind(3, certificate.wireEncode(), SQLITE_STATIC);
+  statement.step();
+}
+
+void
+PibSqlite3::removeCertificate(const Name& certName)
+{
+  Sqlite3Statement statement(m_database, "DELETE FROM certificates WHERE certificate_name=?");
+  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
+  statement.step();
+}
+
+v1::IdentityCertificate
+PibSqlite3::getCertificate(const Name& certName) const
+{
+  Sqlite3Statement statement(m_database,
+                             "SELECT certificate_data FROM certificates WHERE certificate_name=?");
+  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
+
+  if (statement.step() == SQLITE_ROW)
+    return v1::IdentityCertificate(statement.getBlock(0));
+  else
+    BOOST_THROW_EXCEPTION(Pib::Error("Certificate does not exit"));
+}
+
+std::set<Name>
+PibSqlite3::getCertificatesOfKey(const Name& identity, const name::Component& keyId) const
+{
+  std::set<Name> certNames;
+
+  Name keyName = getKeyName(identity, keyId);
+
+  Sqlite3Statement statement(m_database,
+                             "SELECT certificate_name "
+                             "FROM certificates JOIN keys ON certificates.key_id=keys.id "
+                             "WHERE keys.key_name=?");
+  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
+
+  while (statement.step() == SQLITE_ROW)
+    certNames.insert(Name(statement.getBlock(0)));
+
+  return certNames;
+}
+
+void
+PibSqlite3::setDefaultCertificateOfKey(const Name& identity, const name::Component& keyId,
+                                       const Name& certName)
+{
+  if (!hasCertificate(certName)) {
+    BOOST_THROW_EXCEPTION(Pib::Error("Certificate does not exist"));
+  }
+
+  Sqlite3Statement statement(m_database,
+                             "UPDATE certificates SET is_default=1 WHERE certificate_name=?");
+  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
+  statement.step();
+}
+
+v1::IdentityCertificate
+PibSqlite3::getDefaultCertificateOfKey(const Name& identity, const name::Component& keyId) const
+{
+  Name keyName = getKeyName(identity, keyId);
+
+  Sqlite3Statement statement(m_database,
+                             "SELECT certificate_data "
+                             "FROM certificates JOIN keys ON certificates.key_id=keys.id "
+                             "WHERE certificates.is_default=1 AND keys.key_name=?");
+  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
+
+  if (statement.step() == SQLITE_ROW)
+    return v1::IdentityCertificate(statement.getBlock(0));
+  else
+    BOOST_THROW_EXCEPTION(Pib::Error("Certificate does not exit"));
+}
+
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/pib-sqlite3.hpp b/src/security/pib/pib-sqlite3.hpp
new file mode 100644
index 0000000..7e4b2c5
--- /dev/null
+++ b/src/security/pib/pib-sqlite3.hpp
@@ -0,0 +1,143 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITTY_PIB_PIB_SQLITE3_HPP
+#define NDN_SECURITTY_PIB_PIB_SQLITE3_HPP
+
+#include "pib-impl.hpp"
+
+struct sqlite3;
+
+namespace ndn {
+namespace security {
+
+/**
+ * @brief Pib backend implementation based on SQLite3 database
+ *
+ * All the contents in Pib are stored in a SQLite3 database file.
+ * This backend provides more persistent storage than PibMemory.
+ */
+class PibSqlite3 : public PibImpl
+{
+public:
+  /**
+   * @brief Constructor of PibSqlite3
+   *
+   * This method will create a SQLite3 database file under the directory @p dir.
+   * If the directory does not exist, it will be created automatically.
+   * It assumes that the directory does not contain a PIB database of an older version,
+   * It is user's responsibility to update the older version database or remove the database.
+   *
+   * @param dir The directory where the database file is located. By default, it points to the
+   *        $HOME/.ndn directory.
+   * @throws PibImpl::Error when initialization fails.
+   */
+  explicit
+  PibSqlite3(const std::string& dir = "");
+
+  /**
+   * @brief Destruct and cleanup internal state
+   */
+  ~PibSqlite3();
+
+public: // TpmLocator management
+
+  void
+  setTpmLocator(const std::string& tpmLocator) final;
+
+  std::string
+  getTpmLocator() const final;
+
+public: // Identity management
+
+  bool
+  hasIdentity(const Name& identity) const final;
+
+  void
+  addIdentity(const Name& identity) final;
+
+  void
+  removeIdentity(const Name& identity) final;
+
+  std::set<Name>
+  getIdentities() const final;
+
+  void
+  setDefaultIdentity(const Name& identityName) final;
+
+  Name
+  getDefaultIdentity() const final;
+
+public: // Key management
+
+  bool
+  hasKey(const Name& identity, const name::Component& keyId) const final;
+
+  void
+  addKey(const Name& identity, const name::Component& keyId, const v1::PublicKey& publicKey) final;
+
+  void
+  removeKey(const Name& identity, const name::Component& keyId) final;
+
+  v1::PublicKey
+  getKeyBits(const Name& identity, const name::Component& keyId) const final;
+
+  std::set<name::Component>
+  getKeysOfIdentity(const Name& identity) const final;
+
+  void
+  setDefaultKeyOfIdentity(const Name& identity, const name::Component& keyId) final;
+
+  name::Component
+  getDefaultKeyOfIdentity(const Name& identity) const final;
+
+public: // Certificate Management
+
+  bool
+  hasCertificate(const Name& certName) const final;
+
+  void
+  addCertificate(const v1::IdentityCertificate& certificate) final;
+
+  void
+  removeCertificate(const Name& certName) final;
+
+  v1::IdentityCertificate
+  getCertificate(const Name& certName) const final;
+
+  std::set<Name>
+  getCertificatesOfKey(const Name& identity, const name::Component& keyId) const final;
+
+  void
+  setDefaultCertificateOfKey(const Name& identity, const name::Component& keyId,
+                             const Name& certName) final;
+
+  v1::IdentityCertificate
+  getDefaultCertificateOfKey(const Name& identity, const name::Component& keyId) const final;
+
+private:
+  sqlite3* m_database;
+};
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITTY_PIB_PIB_SQLITE3_HPP
diff --git a/src/security/pib/pib.cpp b/src/security/pib/pib.cpp
new file mode 100644
index 0000000..511c96a
--- /dev/null
+++ b/src/security/pib/pib.cpp
@@ -0,0 +1,120 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "pib.hpp"
+#include "pib-impl.hpp"
+
+namespace ndn {
+namespace security {
+
+Pib::Pib(const std::string scheme, const std::string& location, shared_ptr<PibImpl> impl)
+  : m_scheme(scheme)
+  , m_location(location)
+  , m_hasDefaultIdentity(false)
+  , m_needRefreshIdentities(true)
+  , m_impl(impl)
+{
+}
+
+Pib::~Pib()
+{
+}
+
+std::string
+Pib::getPibLocator() const
+{
+  return m_scheme + ":" + m_location;
+}
+
+void
+Pib::setTpmLocator(const std::string& tpmLocator)
+{
+  m_impl->setTpmLocator(tpmLocator);
+}
+
+std::string
+Pib::getTpmLocator() const
+{
+  return m_impl->getTpmLocator();
+}
+
+Identity
+Pib::addIdentity(const Name& identity)
+{
+  if (!m_needRefreshIdentities && m_identities.find(identity) == m_identities.end()) {
+    // if we have already loaded all the identities, but the new identity is not one of them
+    // the IdentityContainer should be refreshed
+    m_needRefreshIdentities = true;
+  }
+  return Identity(identity, m_impl, true);
+}
+
+void
+Pib::removeIdentity(const Name& identity)
+{
+  if (m_hasDefaultIdentity && m_defaultIdentity.getName() == identity)
+    m_hasDefaultIdentity = false;
+
+  m_impl->removeIdentity(identity);
+  m_needRefreshIdentities = true;
+}
+
+Identity
+Pib::getIdentity(const Name& identity) const
+{
+  return Identity(identity, m_impl, false);
+}
+
+const IdentityContainer&
+Pib::getIdentities() const
+{
+  if (m_needRefreshIdentities) {
+    m_identities = IdentityContainer(m_impl->getIdentities(), m_impl);
+    m_needRefreshIdentities = false;
+  }
+
+  return m_identities;
+}
+
+Identity&
+Pib::setDefaultIdentity(const Name& identityName)
+{
+  m_defaultIdentity = addIdentity(identityName);
+  m_hasDefaultIdentity = true;
+
+  m_impl->setDefaultIdentity(identityName);
+  return m_defaultIdentity;
+}
+
+Identity&
+Pib::getDefaultIdentity() const
+{
+  if (!m_hasDefaultIdentity) {
+    m_defaultIdentity = Identity(m_impl->getDefaultIdentity(), m_impl, false);
+    m_hasDefaultIdentity = true;
+  }
+
+  return m_defaultIdentity;
+}
+
+
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/pib.hpp b/src/security/pib/pib.hpp
new file mode 100644
index 0000000..5c5a11c
--- /dev/null
+++ b/src/security/pib/pib.hpp
@@ -0,0 +1,187 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_PIB_HPP
+#define NDN_SECURITY_PIB_PIB_HPP
+
+#include "identity-container.hpp"
+
+namespace ndn {
+namespace security {
+
+class KeyChain;
+class PibImpl;
+
+/**
+ * @brief represents the PIB
+ *
+ * The PIB (Public Information Base) stores the public portion of a user's cryptography keys.
+ * The format and location of stored information is indicated by the PibLocator.
+ * The PIB is designed to work with a TPM (Trusted Platform Module) which stores private keys.
+ * There is a one-to-one association between PIB and TPM, and therefore the TpmLocator is recorded
+ * by the PIB to enforce this association and prevent one from operating on mismatched PIB and TPM.
+ *
+ * Information in the PIB is organized in a hierarchy of Identity-Key-Certificate. At the top level,
+ * the Pib class provides access to identities, and allows setting a default identity. Properties of
+ * an identity can be accessed after obtaining an Identity object.
+ *
+ * @throw PibImpl::Error when underlying implementation has non-semantic error.
+ */
+class Pib : noncopyable
+{
+public:
+  friend class KeyChain;
+
+public:
+  /// @brief represents a semantic error
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+public:
+
+  ~Pib();
+
+  /**
+   * @brief return the scheme of the PibLocator
+   */
+  std::string
+  getScheme() const
+  {
+    return m_scheme;
+  }
+
+  /**
+   * @brief Get PIB Locator
+   */
+  std::string
+  getPibLocator() const;
+
+  /**
+   * @brief Set the corresponding TPM information to @p tpmLocator.
+   *
+   * If the provided @p tpmLocator is different from the existing one, the
+   * PIB will be reset, otherwise nothing will be changed.
+   *
+   * @param tpmLocator The name for the new TPM locator
+   */
+  void
+  setTpmLocator(const std::string& tpmLocator);
+
+  /**
+   * @brief Get TPM Locator
+   */
+  std::string
+  getTpmLocator() const;
+
+  /**
+   * @brief Get an identity with name @p identityName.
+   *
+   * @param identityName The name for the identity to get.
+   * @throw Pib::Error if the identity does not exist.
+   */
+  Identity
+  getIdentity(const Name& identityName) const;
+
+  /// @brief Get all the identities
+  const IdentityContainer&
+  getIdentities() const;
+
+  /**
+   * @brief Get the default identity.
+   *
+   * @return the default identity.
+   * @throws Pib::Error if no default identity.
+   */
+  Identity&
+  getDefaultIdentity() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
+
+  /*
+   * @brief Create an identity with name @p identityName and return a reference to it.
+   *
+   * If there already exists an identity for the name @p identityName, then it is returned.
+   * If no default identity is set, the newly created identity will be set as the default.
+   *
+   * @param identityName The name for the identity to be added
+   */
+  Identity
+  addIdentity(const Name& identityName);
+
+  /*
+   * @brief Remove an identity with name @p identityName.
+   *
+   * @param identityName The name for the identity to be deleted
+   */
+  void
+  removeIdentity(const Name& identityName);
+
+  /**
+   * @brief Set an identity with name @p identityName as the default identity.
+   *
+   * Also create the identity if it does not exist.
+   *
+   * @param identityName The name for the default identity.
+   * @return the default identity
+   */
+  Identity&
+  setDefaultIdentity(const Name& identityName);
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+  /*
+   * @brief Create a new Pib with the specified @p location
+   *
+   * @param scheme The scheme for the Pib
+   * @param location The location for the Pib
+   * @param impl The backend implementation
+   */
+  Pib(const std::string scheme, const std::string& location, shared_ptr<PibImpl> impl);
+
+  shared_ptr<PibImpl>
+  getImpl()
+  {
+    return m_impl;
+  }
+
+protected:
+  std::string m_scheme;
+  std::string m_location;
+
+  mutable bool m_hasDefaultIdentity;
+  mutable Identity m_defaultIdentity;
+
+  mutable bool m_needRefreshIdentities;
+  mutable IdentityContainer m_identities;
+
+  shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_PIB_HPP