diff --git a/src/security/key-chain.hpp b/src/security/key-chain.hpp
index 4f43139..31b26ea 100644
--- a/src/security/key-chain.hpp
+++ b/src/security/key-chain.hpp
@@ -17,951 +17,23 @@
  * <http://www.gnu.org/licenses/>.
  *
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
  */
 
-#ifndef NDN_SECURITY_KEY_CHAIN_HPP
-#define NDN_SECURITY_KEY_CHAIN_HPP
+/**
+ * @file security/key-chain.hpp
+ */
 
-#include "sec-public-info.hpp"
-#include "sec-tpm.hpp"
-#include "key-params.hpp"
-#include "secured-bag.hpp"
-#include "signature-sha256-with-rsa.hpp"
-#include "signature-sha256-with-ecdsa.hpp"
-#include "digest-sha256.hpp"
-#include "signing-info.hpp"
-
-#include "../interest.hpp"
-#include "../util/crypto.hpp"
-#include "../util/random.hpp"
-#include <initializer_list>
+#include "security-common.hpp"
+#include "v1/key-chain.hpp"
+#include "v2/key-chain.hpp"
 
 namespace ndn {
 namespace security {
 
-/**
- * @brief The packet signing interface.
- */
-class KeyChain : noncopyable
-{
-public:
-  class Error : public std::runtime_error
-  {
-  public:
-    explicit
-    Error(const std::string& what)
-      : std::runtime_error(what)
-    {
-    }
-  };
-
-  /**
-   * @brief Error thrown when the supplied TPM locator to KeyChain constructor does not match
-   *        the locator stored in PIB
-   */
-  class MismatchError : public Error
-  {
-  public:
-    explicit
-    MismatchError(const std::string& what)
-      : Error(what)
-    {
-    }
-  };
-
-  typedef function<unique_ptr<SecPublicInfo> (const std::string&)> PibCreateFunc;
-  typedef function<unique_ptr<SecTpm>(const std::string&)> TpmCreateFunc;
-
-  /**
-   * @brief Register a new PIB
-   * @param aliases List of schemes with which this PIB will be associated.
-   *        The first alias in the list is considered a canonical name of the PIB instance.
-   */
-  template<class PibType>
-  static void
-  registerPib(std::initializer_list<std::string> aliases);
-
-  /**
-   * @brief Register a new TPM
-   * @param aliases List of schemes with which this TPM will be associated
-   *        The first alias in the list is considered a canonical name of the TPM instance.
-   */
-  template<class TpmType>
-  static void
-  registerTpm(std::initializer_list<std::string> aliases);
-
-  /**
-   * @brief Get default PIB locator
-   */
-  static std::string
-  getDefaultPibLocator();
-
-  /**
-    * @brief Create a PIB according to @p pibLocator
-    */
-  static unique_ptr<SecPublicInfo>
-  createPib(const std::string& pibLocator);
-
-  /**
-   * @brief Get default TPM locator
-   */
-  static std::string
-  getDefaultTpmLocator();
-
-  /**
-    * @brief Create a TPM according to @p tpmLocator
-    */
-  static unique_ptr<SecTpm>
-  createTpm(const std::string& tpmLocator);
-
-  /**
-   * @brief Constructor to create KeyChain with default PIB and TPM
-   *
-   * Default PIB and TPM are platform-dependent and can be overriden system-wide or on
-   * per-use basis.
-   *
-   * @todo Add detailed description about config file behavior here
-   */
-  KeyChain();
-
-  /**
-   * @brief KeyChain constructor
-   *
-   * @sa  http://redmine.named-data.net/issues/2260
-   *
-   * @param pibLocator PIB locator
-   * @param tpmLocator TPM locator
-   * @param allowReset if true, the PIB will be reset when the supplied tpmLocator
-   *        mismatches the one in PIB
-   */
-  KeyChain(const std::string& pibLocator,
-           const std::string& tpmLocator,
-           bool allowReset = false);
-
-  virtual
-  ~KeyChain();
-
-  /**
-   * @brief Create an identity by creating a pair of Key-Signing-Key (KSK) for this identity and a
-   *        self-signed certificate of the KSK.
-   *
-   * @param identityName The name of the identity.
-   * @param params The key parameter if a key needs to be generated for the identity.
-   * @return The name of the default certificate of the identity.
-   */
-  Name
-  createIdentity(const Name& identityName, const KeyParams& params = DEFAULT_KEY_PARAMS);
-
-  /**
-   * @brief Generate a pair of RSA keys for the specified identity.
-   *
-   * @param identityName The name of the identity.
-   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
-   * @param keySize The size of the key.
-   * @return The generated key name.
-   * @see generateEcdsaKeyPair
-   */
-  Name
-  generateRsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 2048);
-
-  /**
-   * @brief Generate a pair of ECDSA keys for the specified identity.
-   *
-   * @param identityName The name of the identity.
-   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
-   * @param keySize The size of the key.
-   * @return The generated key name.
-   * @see generateRsaKeyPair
-   */
-  Name
-  generateEcdsaKeyPair(const Name& identityName, bool isKsk = false, uint32_t keySize = 256);
-
-  /**
-   * @brief Generate a pair of RSA keys for the specified identity and set it as default key for
-   *        the identity.
-   *
-   * @param identityName The name of the identity.
-   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
-   * @param keySize The size of the key.
-   * @return The generated key name.
-   * @see generateRsaKeyPair, generateEcdsaKeyPair, generateEcdsaKeyPairAsDefault
-   */
-  Name
-  generateRsaKeyPairAsDefault(const Name& identityName, bool isKsk = false, uint32_t keySize = 2048);
-
-  /**
-   * @brief Generate a pair of ECDSA keys for the specified identity and set it as default key for
-   *        the identity.
-   *
-   * @param identityName The name of the identity.
-   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
-   * @param keySize The size of the key.
-   * @return The generated key name.
-   * @see generateRsaKeyPair, generateEcdsaKeyPair, generateRsaKeyPairAsDefault
-   */
-  Name
-  generateEcdsaKeyPairAsDefault(const Name& identityName, bool isKsk = false, uint32_t keySize = 256);
-
-  /**
-   * @brief prepare an unsigned identity certificate
-   *
-   * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
-   * @param signingIdentity The signing identity.
-   * @param notBefore Refer to v1::IdentityCertificate.
-   * @param notAfter Refer to v1::IdentityCertificate.
-   * @param subjectDescription Refer to v1::IdentityCertificate.
-   * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
-   *                   certificate name according to the relation between the signingIdentity and
-   *                   the subject identity. If signingIdentity is a prefix of the subject identity,
-   *                   `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
-   *                   after subject identity (i.e., before `ksk-....`).
-   * @return v1::IdentityCertificate.
-   */
-  shared_ptr<v1::IdentityCertificate>
-  prepareUnsignedIdentityCertificate(const Name& keyName,
-    const Name& signingIdentity,
-    const time::system_clock::TimePoint& notBefore,
-    const time::system_clock::TimePoint& notAfter,
-    const std::vector<security::v1::CertificateSubjectDescription>& subjectDescription,
-    const Name& certPrefix = DEFAULT_PREFIX);
-
-  /**
-   * @brief prepare an unsigned identity certificate
-   *
-   * @param keyName Key name, e.g., `/<identity_name>/ksk-123456`.
-   * @param publicKey Public key to sign.
-   * @param signingIdentity The signing identity.
-   * @param notBefore Refer to v1::IdentityCertificate.
-   * @param notAfter Refer to v1::IdentityCertificate.
-   * @param subjectDescription Refer to v1::IdentityCertificate.
-   * @param certPrefix Prefix before `KEY` component. By default, KeyChain will infer the
-   *                   certificate name according to the relation between the signingIdentity and
-   *                   the subject identity. If signingIdentity is a prefix of the subject identity,
-   *                   `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted
-   *                   after subject identity (i.e., before `ksk-....`).
-   * @return v1::IdentityCertificate.
-   */
-  shared_ptr<v1::IdentityCertificate>
-  prepareUnsignedIdentityCertificate(const Name& keyName,
-    const v1::PublicKey& publicKey,
-    const Name& signingIdentity,
-    const time::system_clock::TimePoint& notBefore,
-    const time::system_clock::TimePoint& notAfter,
-    const std::vector<security::v1::CertificateSubjectDescription>& subjectDescription,
-    const Name& certPrefix = DEFAULT_PREFIX);
-
-  /**
-   * @brief Sign data according to the supplied signing information
-   *
-   * This method uses the supplied signing information @p params to create the SignatureInfo block:
-   * - it selects a private key and its certificate to sign the packet
-   * - sets the KeyLocator field with the certificate name, and
-   * - adds other requested information to the SignatureInfo block).
-   *
-   * After that, the method assigns the created SignatureInfo to the data packets, generate a
-   * signature and sets as part of the SignatureValue block.
-   *
-   * @param data The data to sign
-   * @param params The signing parameters.
-   * @throws Error if signing fails.
-   * @see SigningInfo
-   */
-  void
-  sign(Data& data, const SigningInfo& params = DEFAULT_SIGNING_INFO);
-
-  /**
-   * @brief Sign interest according to the supplied signing information
-   *
-   * This method uses the supplied signing information @p params to create the SignatureInfo block:
-   * - it selects a private key and its certificate to sign the packet
-   * - sets the KeyLocator field with the certificate name, and
-   * - adds other requested information to the SignatureInfo block).
-   *
-   * After that, the method appends the created SignatureInfo to the interest name, generate a
-   * signature and appends it as part of the SignatureValue block to the interest name.
-   *
-   * @param interest The interest to sign
-   * @param params The signing parameters.
-   * @throws Error if signing fails.
-   * @see SigningInfo
-   */
-  void
-  sign(Interest& interest, const SigningInfo& params = DEFAULT_SIGNING_INFO);
-
-  /**
-   * @brief Sign buffer according to the supplied signing information
-   *
-   * @param buffer The buffer to sign
-   * @param bufferLength The buffer size
-   * @param params The signing parameters.
-   * @return a SignatureValue TLV block
-   * @throws Error if signing fails.
-   * @see SigningInfo
-   */
-  Block
-  sign(const uint8_t* buffer, size_t bufferLength, const SigningInfo& params);
-
-  /**
-   * @deprecated use sign sign(T&, const SigningInfo&)
-   * @brief Sign packet with a particular certificate.
-   *
-   * @param packet The packet to be signed.
-   * @param certificateName The certificate name of the key to use for signing.
-   * @throws SecPublicInfo::Error if certificate does not exist.
-   */
-  template<typename T>
-  void
-  sign(T& packet, const Name& certificateName);
-
-  /**
-   * @deprecated Use sign(const uint8_t*, size_t, const SigningInfo&) instead
-   * @brief Sign the byte array using a particular certificate.
-   *
-   * @param buffer The byte array to be signed.
-   * @param bufferLength the length of buffer.
-   * @param certificateName The certificate name of the signing key.
-   * @return The Signature.
-   * @throws SecPublicInfo::Error if certificate does not exist.
-   */
-  Signature
-  sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName);
-
-  /**
-   * @deprecated use sign sign(T&, const SigningInfo&)
-   * @brief Sign packet using the default certificate of a particular identity.
-   *
-   * If there is no default certificate of that identity, this method will create a self-signed
-   * certificate.
-   *
-   * @param packet The packet to be signed.
-   * @param identityName The signing identity name.
-   */
-  template<typename T>
-  void
-  signByIdentity(T& packet, const Name& identityName);
-
-  /**
-   * @deprecated use sign(const uint8_t*, size_t, const SigningInfo&) instead
-   * @brief Sign the byte array using the default certificate of a particular identity.
-   *
-   * @param buffer The byte array to be signed.
-   * @param bufferLength the length of buffer.
-   * @param identityName The identity name.
-   * @return The Signature.
-   */
-  Signature
-  signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName);
-
-  /**
-   * @deprecated use sign(Data&, SigningInfo(SigningInfo::SIGNER_TYPE_SHA256))
-   * @brief Set Sha256 weak signature for @p data
-   */
-  void
-  signWithSha256(Data& data);
-
-  /**
-   * @deprecated use sign(Interest&, SigningInfo(SigningInfo::SIGNER_TYPE_SHA256))
-   * @brief Set Sha256 weak signature for @p interest
-   */
-  void
-  signWithSha256(Interest& interest);
-
-  /**
-   * @brief Generate a self-signed certificate for a public key.
-   *
-   * @param keyName The name of the public key
-   * @return The generated certificate, shared_ptr<v1::IdentityCertificate>() if selfSign fails
-   */
-  shared_ptr<v1::IdentityCertificate>
-  selfSign(const Name& keyName);
-
-  /**
-   * @brief Self-sign the supplied identity certificate.
-   *
-   * @param cert The supplied cert.
-   * @throws SecTpm::Error if the private key does not exist.
-   */
-  void
-  selfSign(v1::IdentityCertificate& cert);
-
-  /**
-   * @brief delete a certificate.
-   *
-   * @param certificateName The certificate to be deleted.
-   * @throws KeyChain::Error if certificate cannot be deleted.
-   */
-  void
-  deleteCertificate(const Name& certificateName);
-
-  /**
-   * @brief delete a key.
-   *
-   * @param keyName The key to be deleted.
-   * @throws KeyChain::Error if key cannot be deleted.
-   */
-  void
-  deleteKey(const Name& keyName);
-
-  /**
-   * @brief delete an identity.
-   *
-   * @param identity The identity to be deleted.
-   * @throws KeyChain::Error if identity cannot be deleted.
-   */
-  void
-  deleteIdentity(const Name& identity);
-
-  /**
-   * @brief export an identity.
-   *
-   * @param identity The identity to export.
-   * @param passwordStr The password to secure the private key.
-   * @return The encoded export data.
-   * @throws SecPublicInfo::Error if anything goes wrong in exporting.
-   */
-  shared_ptr<SecuredBag>
-  exportIdentity(const Name& identity, const std::string& passwordStr);
-
-  /**
-   * @brief import an identity.
-   *
-   * @param securedBag The encoded import data.
-   * @param passwordStr The password to secure the private key.
-   */
-  void
-  importIdentity(const SecuredBag& securedBag, const std::string& passwordStr);
-
-  SecPublicInfo&
-  getPib()
-  {
-    return *m_pib;
-  }
-
-  const SecPublicInfo&
-  getPib() const
-  {
-    return *m_pib;
-  }
-
-  SecTpm&
-  getTpm()
-  {
-    return *m_tpm;
-  }
-
-  const SecTpm&
-  getTpm() const
-  {
-    return *m_tpm;
-  }
-
-  /*******************************
-   *  Wrapper of SecPublicInfo   *
-   *******************************/
-  bool
-  doesIdentityExist(const Name& identityName) const
-  {
-    return m_pib->doesIdentityExist(identityName);
-  }
-
-  void
-  addIdentity(const Name& identityName)
-  {
-    return m_pib->addIdentity(identityName);
-  }
-
-  bool
-  doesPublicKeyExist(const Name& keyName) const
-  {
-    return m_pib->doesPublicKeyExist(keyName);
-  }
-
-  void
-  addPublicKey(const Name& keyName, KeyType keyType, const v1::PublicKey& publicKeyDer)
-  {
-    return m_pib->addKey(keyName, publicKeyDer);
-  }
-
-  void
-  addKey(const Name& keyName, const v1::PublicKey& publicKeyDer)
-  {
-    return m_pib->addKey(keyName, publicKeyDer);
-  }
-
-  shared_ptr<v1::PublicKey>
-  getPublicKey(const Name& keyName) const
-  {
-    return m_pib->getPublicKey(keyName);
-  }
-
-  bool
-  doesCertificateExist(const Name& certificateName) const
-  {
-    return m_pib->doesCertificateExist(certificateName);
-  }
-
-  void
-  addCertificate(const v1::IdentityCertificate& certificate)
-  {
-    return m_pib->addCertificate(certificate);
-  }
-
-  shared_ptr<v1::IdentityCertificate>
-  getCertificate(const Name& certificateName) const
-  {
-    return m_pib->getCertificate(certificateName);
-  }
-
-  Name
-  getDefaultIdentity() const
-  {
-    return m_pib->getDefaultIdentity();
-  }
-
-  Name
-  getDefaultKeyNameForIdentity(const Name& identityName) const
-  {
-    return m_pib->getDefaultKeyNameForIdentity(identityName);
-  }
-
-  /**
-   * @brief Get default key parameters for the specified identity
-   *
-   * If identity has a previously generated key, the returned parameters
-   * will include the same type of the key.  If there are no existing
-   * keys, DEFAULT_KEY_PARAMS is used.
-   */
-  const KeyParams&
-  getDefaultKeyParamsForIdentity(const Name& identityName) const;
-
-  Name
-  getDefaultCertificateNameForKey(const Name& keyName) const
-  {
-    return m_pib->getDefaultCertificateNameForKey(keyName);
-  }
-
-  void
-  getAllIdentities(std::vector<Name>& nameList, bool isDefault) const
-  {
-    return m_pib->getAllIdentities(nameList, isDefault);
-  }
-
-  void
-  getAllKeyNames(std::vector<Name>& nameList, bool isDefault) const
-  {
-    return m_pib->getAllKeyNames(nameList, isDefault);
-  }
-
-  void
-  getAllKeyNamesOfIdentity(const Name& identity, std::vector<Name>& nameList, bool isDefault) const
-  {
-    return m_pib->getAllKeyNamesOfIdentity(identity, nameList, isDefault);
-  }
-
-  void
-  getAllCertificateNames(std::vector<Name>& nameList, bool isDefault) const
-  {
-    return m_pib->getAllCertificateNames(nameList, isDefault);
-  }
-
-  void
-  getAllCertificateNamesOfKey(const Name& keyName,
-                              std::vector<Name>& nameList,
-                              bool isDefault) const
-  {
-    return m_pib->getAllCertificateNamesOfKey(keyName, nameList, isDefault);
-  }
-
-  void
-  deleteCertificateInfo(const Name& certificateName)
-  {
-    return m_pib->deleteCertificateInfo(certificateName);
-  }
-
-  void
-  deletePublicKeyInfo(const Name& keyName)
-  {
-    return m_pib->deletePublicKeyInfo(keyName);
-  }
-
-  void
-  deleteIdentityInfo(const Name& identity)
-  {
-    return m_pib->deleteIdentityInfo(identity);
-  }
-
-  void
-  setDefaultIdentity(const Name& identityName)
-  {
-    return m_pib->setDefaultIdentity(identityName);
-  }
-
-  void
-  setDefaultKeyNameForIdentity(const Name& keyName)
-  {
-    return m_pib->setDefaultKeyNameForIdentity(keyName);
-  }
-
-  void
-  setDefaultCertificateNameForKey(const Name& certificateName)
-  {
-    return m_pib->setDefaultCertificateNameForKey(certificateName);
-  }
-
-  Name
-  getNewKeyName(const Name& identityName, bool useKsk)
-  {
-    return m_pib->getNewKeyName(identityName, useKsk);
-  }
-
-  Name
-  getDefaultCertificateNameForIdentity(const Name& identityName) const
-  {
-    return m_pib->getDefaultCertificateNameForIdentity(identityName);
-  }
-
-  Name
-  getDefaultCertificateName() const
-  {
-    return m_pib->getDefaultCertificateName();
-  }
-
-  void
-  addCertificateAsKeyDefault(const v1::IdentityCertificate& certificate)
-  {
-    return m_pib->addCertificateAsKeyDefault(certificate);
-  }
-
-  void
-  addCertificateAsIdentityDefault(const v1::IdentityCertificate& certificate)
-  {
-    return m_pib->addCertificateAsIdentityDefault(certificate);
-  }
-
-  void
-  addCertificateAsSystemDefault(const v1::IdentityCertificate& certificate)
-  {
-    return m_pib->addCertificateAsSystemDefault(certificate);
-  }
-
-  shared_ptr<v1::IdentityCertificate>
-  getDefaultCertificate() const
-  {
-    if (!static_cast<bool>(m_pib->getDefaultCertificate()))
-      const_cast<KeyChain*>(this)->setDefaultCertificateInternal();
-
-    return m_pib->getDefaultCertificate();
-  }
-
-  void
-  refreshDefaultCertificate()
-  {
-    return m_pib->refreshDefaultCertificate();
-  }
-
-  /*******************************
-   *  Wrapper of SecTpm          *
-   *******************************/
-
-  void
-  setTpmPassword(const uint8_t* password, size_t passwordLength)
-  {
-    return m_tpm->setTpmPassword(password, passwordLength);
-  }
-
-  void
-  resetTpmPassword()
-  {
-    return m_tpm->resetTpmPassword();
-  }
-
-  void
-  setInTerminal(bool inTerminal)
-  {
-    return m_tpm->setInTerminal(inTerminal);
-  }
-
-  bool
-  getInTerminal() const
-  {
-    return m_tpm->getInTerminal();
-  }
-
-  bool
-  isLocked() const
-  {
-    return m_tpm->isLocked();
-  }
-
-  bool
-  unlockTpm(const char* password, size_t passwordLength, bool usePassword)
-  {
-    return m_tpm->unlockTpm(password, passwordLength, usePassword);
-  }
-
-  void
-  generateKeyPairInTpm(const Name& keyName, const KeyParams& params)
-  {
-    return m_tpm->generateKeyPairInTpm(keyName, params);
-  }
-
-  void
-  deleteKeyPairInTpm(const Name& keyName)
-  {
-    return m_tpm->deleteKeyPairInTpm(keyName);
-  }
-
-  shared_ptr<v1::PublicKey>
-  getPublicKeyFromTpm(const Name& keyName) const
-  {
-    return m_tpm->getPublicKeyFromTpm(keyName);
-  }
-
-  Block
-  signInTpm(const uint8_t* data, size_t dataLength,
-            const Name& keyName,
-            DigestAlgorithm digestAlgorithm)
-  {
-    return m_tpm->signInTpm(data, dataLength, keyName, digestAlgorithm);
-  }
-
-  ConstBufferPtr
-  decryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
-  {
-    return m_tpm->decryptInTpm(data, dataLength, keyName, isSymmetric);
-  }
-
-  ConstBufferPtr
-  encryptInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, bool isSymmetric)
-  {
-    return m_tpm->encryptInTpm(data, dataLength, keyName, isSymmetric);
-  }
-
-  void
-  generateSymmetricKeyInTpm(const Name& keyName, const KeyParams& params)
-  {
-    return m_tpm->generateSymmetricKeyInTpm(keyName, params);
-  }
-
-  bool
-  doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) const
-  {
-    return m_tpm->doesKeyExistInTpm(keyName, keyClass);
-  }
-
-  bool
-  generateRandomBlock(uint8_t* res, size_t size) const
-  {
-    return m_tpm->generateRandomBlock(res, size);
-  }
-
-  void
-  addAppToAcl(const Name& keyName, KeyClass keyClass, const std::string& appPath, AclType acl)
-  {
-    return m_tpm->addAppToAcl(keyName, keyClass, appPath, acl);
-  }
-
-  ConstBufferPtr
-  exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& password)
-  {
-    return m_tpm->exportPrivateKeyPkcs5FromTpm(keyName, password);
-  }
-
-  bool
-  importPrivateKeyPkcs5IntoTpm(const Name& keyName,
-                               const uint8_t* buf, size_t size,
-                               const std::string& password)
-  {
-    return m_tpm->importPrivateKeyPkcs5IntoTpm(keyName, buf, size, password);
-  }
-
-private:
-  void
-  initialize(const std::string& pibLocatorUri,
-             const std::string& tpmLocatorUri,
-             bool needReset);
-
-  /**
-   * @brief Prepare a SignatureInfo TLV according to signing information and return the signing key name
-   *
-   * @param params The signing parameters.
-   * @return The signing key name and prepared SignatureInfo.
-   * @throw Error when the requested signing method cannot be satisfied.
-   */
-  std::tuple<Name, SignatureInfo>
-  prepareSignatureInfo(const SigningInfo& params);
-
-  /**
-   * @brief Internal abstraction of packet signing.
-   *
-   * @param packet The packet to sign
-   * @param params The signing parameters.
-   * @throw Error when the signing fails.
-   */
-  template<typename T>
-  void
-  signImpl(T& packet, const SigningInfo& params);
-
-  /**
-   * @brief Set default certificate if it is not initialized
-   */
-  void
-  setDefaultCertificateInternal();
-
-  /**
-   * @brief Generate a key pair for the specified identity.
-   *
-   * @param identityName The name of the specified identity.
-   * @param isKsk true for generating a Key-Signing-Key (KSK), false for a Data-Signing-Key (KSK).
-   * @param params The parameter of the key.
-   * @return The name of the generated key.
-   */
-  Name
-  generateKeyPair(const Name& identityName, bool isKsk = false,
-                  const KeyParams& params = DEFAULT_KEY_PARAMS);
-
-  /**
-   * @brief Sign the data using a particular key.
-   *
-   * @param data Reference to the data packet.
-   * @param signature Signature to be added.
-   * @param keyName The name of the signing key.
-   * @param digestAlgorithm the digest algorithm.
-   * @throws Tpm::Error
-   */
-  void
-  signPacketWrapper(Data& data, const Signature& signature,
-                    const Name& keyName, DigestAlgorithm digestAlgorithm);
-
-  /**
-   * @brief Sign the interest using a particular key.
-   *
-   * @param interest Reference to the interest packet.
-   * @param signature Signature to be added.
-   * @param keyName The name of the signing key.
-   * @param digestAlgorithm the digest algorithm.
-   * @throws Tpm::Error
-   */
-  void
-  signPacketWrapper(Interest& interest, const Signature& signature,
-                    const Name& keyName, DigestAlgorithm digestAlgorithm);
-
-  /**
-   * @brief Generate a SignatureValue block for a buffer @p buf with size @p size using
-   *        a key with name @p keyName and digest algorithm @p digestAlgorithm.
-   */
-  Block
-  pureSign(const uint8_t* buf, size_t size, const Name& keyName, DigestAlgorithm digestAlgorithm) const;
-
-  static void
-  registerPibImpl(const std::string& canonicalName,
-                  std::initializer_list<std::string> aliases, PibCreateFunc createFunc);
-
-  static void
-  registerTpmImpl(const std::string& canonicalName,
-                  std::initializer_list<std::string> aliases, TpmCreateFunc createFunc);
-
-public:
-  static tlv::SignatureTypeValue
-  getSignatureType(KeyType keyType, DigestAlgorithm digestAlgorithm);
-
-public:
-  static const Name DEFAULT_PREFIX;
-  static const SigningInfo DEFAULT_SIGNING_INFO;
-
-  // RsaKeyParams is set to be default for backward compatibility.
-  static const RsaKeyParams DEFAULT_KEY_PARAMS;
-
-  typedef std::map<std::string, Block> SignParams;
-
-private:
-  std::unique_ptr<SecPublicInfo> m_pib;
-  std::unique_ptr<SecTpm> m_tpm;
-  time::milliseconds m_lastTimestamp;
-};
-
-template<typename T>
-void
-KeyChain::signImpl(T& packet, const SigningInfo& params)
-{
-  Name keyName;
-  SignatureInfo sigInfo;
-  std::tie(keyName, sigInfo) = prepareSignatureInfo(params);
-
-  signPacketWrapper(packet, Signature(sigInfo),
-                    keyName, params.getDigestAlgorithm());
-}
-
-template<typename T>
-void
-KeyChain::sign(T& packet, const Name& certificateName)
-{
-  signImpl(packet, SigningInfo(SigningInfo::SIGNER_TYPE_CERT, certificateName));
-}
-
-template<typename T>
-void
-KeyChain::signByIdentity(T& packet, const Name& identityName)
-{
-  signImpl(packet, SigningInfo(SigningInfo::SIGNER_TYPE_ID, identityName));
-}
-
-template<class PibType>
-inline void
-KeyChain::registerPib(std::initializer_list<std::string> aliases)
-{
-  registerPibImpl(*aliases.begin(), aliases, [] (const std::string& locator) {
-      return make_unique<PibType>(locator);
-    });
-}
-
-template<class TpmType>
-inline void
-KeyChain::registerTpm(std::initializer_list<std::string> aliases)
-{
-  registerTpmImpl(*aliases.begin(), aliases, [] (const std::string& locator) {
-      return make_unique<TpmType>(locator);
-    });
-}
-
-/**
- * \brief Register SecPib class in ndn-cxx KeyChain
- *
- * This macro should be placed once in the implementation file of the
- * SecPib type within the namespace where the type is declared.
- */
-#define NDN_CXX_KEYCHAIN_REGISTER_PIB(PibType, ...)     \
-static class NdnCxxAuto ## PibType ## PibRegistrationClass    \
-{                                                             \
-public:                                                       \
-  NdnCxxAuto ## PibType ## PibRegistrationClass()             \
-  {                                                           \
-    ::ndn::KeyChain::registerPib<PibType>({__VA_ARGS__});     \
-  }                                                           \
-} ndnCxxAuto ## PibType ## PibRegistrationVariable
-
-/**
- * \brief Register SecTpm class in ndn-cxx KeyChain
- *
- * This macro should be placed once in the implementation file of the
- * SecTpm type within the namespace where the type is declared.
- */
-#define NDN_CXX_KEYCHAIN_REGISTER_TPM(TpmType, ...)     \
-static class NdnCxxAuto ## TpmType ## TpmRegistrationClass    \
-{                                                             \
-public:                                                       \
-  NdnCxxAuto ## TpmType ## TpmRegistrationClass()             \
-  {                                                           \
-    ::ndn::KeyChain::registerTpm<TpmType>({__VA_ARGS__});     \
-  }                                                           \
-} ndnCxxAuto ## TpmType ## TpmRegistrationVariable
+using security::v1::KeyChain;
 
 } // namespace security
 
-using security::KeyChain;
+using ndn::security::KeyChain;
 
 } // namespace ndn
-
-#endif // NDN_SECURITY_KEY_CHAIN_HPP
