security: Export/Import Identity from/into KeyChain

Change-Id: I757f51f1408cf08b9fb1b1927834889fd29c0231
diff --git a/src/encoding/tlv-security.hpp b/src/encoding/tlv-security.hpp
new file mode 100644
index 0000000..1a522ce
--- /dev/null
+++ b/src/encoding/tlv-security.hpp
@@ -0,0 +1,29 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#ifndef NDN_TLV_SECURITY_HPP
+#define NDN_TLV_SECURITY_HPP
+
+#include "tlv.hpp"
+
+namespace ndn {
+namespace tlv {
+namespace security {
+
+enum {
+  IdentityPackage    = 128,
+  KeyPackage         = 129,
+  CertificatePackage = 130
+};
+
+} // namespace security
+} // namespace tlv
+} // namespace ndn
+
+#endif // NDN_TLV_SECURITY_HPP
diff --git a/src/security/key-chain.hpp b/src/security/key-chain.hpp
index d9d475d..981dfce 100644
--- a/src/security/key-chain.hpp
+++ b/src/security/key-chain.hpp
@@ -13,6 +13,7 @@
 #include "public-key.hpp"
 #include "signature-sha256-with-rsa.hpp"
 #include "../interest.hpp"
+#include "../encoding/tlv-security.hpp"
 
 //PublicInfo
 #include "sec-public-info-sqlite3.hpp"
@@ -59,7 +60,7 @@
 
     if(certName.empty())
       {
-        ptr_lib::shared_ptr<IdentityCertificate> selfCert = selfSign(keyName); 
+        shared_ptr<IdentityCertificate> selfCert = selfSign(keyName); 
         Info::addCertificateAsIdentityDefault(*selfCert);
         certName = selfCert->getName();
       }
@@ -105,7 +106,7 @@
    * @param notAfter The notAfter vallue in validity field of the generated certificate.
    * @return The name of generated identity certificate.
    */
-  ptr_lib::shared_ptr<IdentityCertificate>
+  shared_ptr<IdentityCertificate>
   createIdentityCertificate
     (const Name& certificatePrefix,
      const Name& signerCertificateName,
@@ -114,11 +115,11 @@
   {
     Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
     
-    ptr_lib::shared_ptr<PublicKey> pubKey = Info::getPublicKey(keyName);
+    shared_ptr<PublicKey> pubKey = Info::getPublicKey(keyName);
     if (!pubKey)
       throw InfoError("Requested public key [" + keyName.toUri() + "] doesn't exist");
     
-    ptr_lib::shared_ptr<IdentityCertificate> certificate =
+    shared_ptr<IdentityCertificate> certificate =
       createIdentityCertificate(certificatePrefix,
                                 *pubKey,
                                 signerCertificateName,
@@ -139,7 +140,7 @@
    * @param notAfter The notAfter vallue in validity field of the generated certificate.
    * @return The generated identity certificate.
    */
-  ptr_lib::shared_ptr<IdentityCertificate>
+  shared_ptr<IdentityCertificate>
   createIdentityCertificate
     (const Name& certificatePrefix,
      const PublicKey& publicKey,
@@ -147,7 +148,7 @@
      const MillisecondsSince1970& notBefore,
      const MillisecondsSince1970& notAfter)
   {
-    ptr_lib::shared_ptr<IdentityCertificate> certificate (new IdentityCertificate());
+    shared_ptr<IdentityCertificate> certificate (new IdentityCertificate());
     Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
   
     Name certificateName = certificatePrefix;
@@ -243,7 +244,7 @@
   Signature
   sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
   {
-    ptr_lib::shared_ptr<IdentityCertificate> cert = Info::getCertificate(certificateName);
+    shared_ptr<IdentityCertificate> cert = Info::getCertificate(certificateName);
     if (!static_cast<bool>(cert))
       throw InfoError("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
 
@@ -306,18 +307,18 @@
    * @param keyName The name of the public key.
    * @return The generated certificate.
    */
-  ptr_lib::shared_ptr<IdentityCertificate>
+  shared_ptr<IdentityCertificate>
   selfSign(const Name& keyName)
   {
     if(keyName.empty())
       throw InfoError("Incorrect key name: " + keyName.toUri());
 
-    ptr_lib::shared_ptr<IdentityCertificate> certificate = ptr_lib::make_shared<IdentityCertificate>();
+    shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
     
     Name certificateName = keyName.getPrefix(-1);
     certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
     
-    ptr_lib::shared_ptr<PublicKey> pubKey = Info::getPublicKey(keyName);
+    shared_ptr<PublicKey> pubKey = Info::getPublicKey(keyName);
     if (!pubKey)
       throw InfoError("Requested public key [" + keyName.toUri() + "] doesn't exist");
   
@@ -366,7 +367,7 @@
   }
 
   void
-  deleteIdentity (const Name &identity)
+  deleteIdentity (const Name& identity)
   {
     if(Info::getDefaultIdentity() == identity)
       return;
@@ -382,6 +383,71 @@
       Tpm::deleteKeyPairInTpm(*it);
   }
 
+  Block
+  exportIdentity(const Name& identity, bool inTerminal = true, std::string passwordStr = "")
+  {
+    if (!Info::doesIdentityExist(identity))
+      throw InfoError("Identity does not exist!");
+ 
+    Name keyName = Info::getDefaultKeyNameForIdentity(identity);
+    
+    if(keyName.empty())
+      throw InfoError("Default key does not exist!");
+
+    ConstBufferPtr pkcs8 = Tpm::exportPrivateKeyPkcs8FromTpm(keyName, inTerminal, passwordStr);
+    Block wireKey(tlv::security::KeyPackage, pkcs8);
+
+    Name certName = Info::getDefaultCertificateNameForKey(keyName);
+
+    if(certName.empty())
+      {
+        shared_ptr<IdentityCertificate> selfCert = selfSign(keyName); 
+        Info::addCertificateAsIdentityDefault(*selfCert);
+        certName = selfCert->getName();
+      }
+
+    shared_ptr<IdentityCertificate> cert = Info::getCertificate(certName);
+    Block wireCert(tlv::security::CertificatePackage, cert->wireEncode());
+
+    Block wire(tlv::security::IdentityPackage);
+    wire.push_back(wireCert);
+    wire.push_back(wireKey);
+
+    return wire;
+  }
+
+  void
+  importIdentity(const Block& block, bool inTerminal = true, std::string passwordStr = "")
+  {
+    block.parse();
+    
+    Data data;
+    data.wireDecode(block.get(tlv::security::CertificatePackage).blockFromValue());
+    shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(data);
+    
+    Name keyName = IdentityCertificate::certificateNameToPublicKeyName(cert->getName());
+    Name identity = keyName.getPrefix(-1);
+
+    // Add identity
+    if (Info::doesIdentityExist(identity))
+      deleteIdentity(identity);
+    Info::addIdentity(identity);
+
+    // Add key
+    Block wireKey = block.get(tlv::security::KeyPackage);
+    if (Tpm::doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
+      deleteKey(keyName);
+    Tpm::importPrivateKeyPkcs8IntoTpm(keyName, wireKey.value(), wireKey.value_size(), inTerminal, passwordStr);
+    shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
+    Info::addPublicKey(keyName, KEY_TYPE_RSA, *pubKey); // HACK! We should set key type according to the pkcs8 info.
+    Info::setDefaultKeyNameForIdentity(keyName);
+
+    // Add cert
+    if (Info::doesCertificateExist(cert->getName()))
+        deleteCertificate(cert->getName());
+    Info::addCertificateAsIdentityDefault(*cert);
+  }
+
 
 private:
 
@@ -428,7 +494,7 @@
 
     Tpm::generateKeyPairInTpm(keyName.toUri(), keyType, keySize);
 
-    ptr_lib::shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
+    shared_ptr<PublicKey> pubKey = Tpm::getPublicKeyFromTpm(keyName.toUri());
     Info::addPublicKey(keyName, keyType, *pubKey);
 
     return keyName;
diff --git a/src/security/sec-tpm-file.cpp b/src/security/sec-tpm-file.cpp
index 47cf83b..78d7ef7 100644
--- a/src/security/sec-tpm-file.cpp
+++ b/src/security/sec-tpm-file.cpp
@@ -22,12 +22,15 @@
 #include <cryptopp/sha.h>
 #include <cryptopp/pssr.h>
 #include <cryptopp/modes.h>
+#include <cryptopp/pwdbased.h>
+#include <cryptopp/sha.h>
+#include <cryptopp/des.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
-using namespace CryptoPP;
-using namespace ndn;
+#include <algorithm>
+
 using namespace std;
 
 namespace ndn
@@ -45,6 +48,35 @@
     boost::filesystem::create_directories (m_keystorePath);
   }
 
+  boost::filesystem::path
+  nameTransform(const string& keyName, const string& extension)
+  {
+    using namespace CryptoPP;
+    string digest;
+    SHA256 hash;
+    StringSource src(keyName, true, new HashFilter(hash, new Base64Encoder (new CryptoPP::StringSink(digest))));
+
+    boost::algorithm::trim(digest);
+    std::replace(digest.begin(), digest.end(), '/', '%');
+    
+    return m_keystorePath / (digest + extension);
+  }
+
+  string 
+  maintainMapping(const string& keyName)
+  {
+    string keyFileName = nameTransform(keyName, "").string();
+    
+    ofstream outfile;
+    string dirFile = (m_keystorePath / "mapping.txt").string();
+    
+    outfile.open(dirFile.c_str(), std::ios_base::app);
+    outfile << keyName << ' ' << keyFileName << '\n';
+    outfile.close();
+    
+    return keyFileName;
+  }
+
 public:
   boost::filesystem::path m_keystorePath;
 };
@@ -64,8 +96,7 @@
   if(doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
     throw Error("private key exists");
 
-  string keyFileName = nameTransform(keyURI, "");
-  maintainMapping(keyURI, keyFileName);
+  string keyFileName = m_impl->maintainMapping(keyURI);
 
   try{
     switch(keyType){
@@ -104,8 +135,8 @@
 void
 SecTpmFile::deleteKeyPairInTpm(const Name &keyName)
 {
-  boost::filesystem::path publicKeyPath(nameTransform(keyName.toUri(), ".pub"));
-  boost::filesystem::path privateKeyPath(nameTransform(keyName.toUri(), ".pri"));
+  boost::filesystem::path publicKeyPath(m_impl->nameTransform(keyName.toUri(), ".pub"));
+  boost::filesystem::path privateKeyPath(m_impl->nameTransform(keyName.toUri(), ".pri"));
 
   if(boost::filesystem::exists(publicKeyPath))
     boost::filesystem::remove(publicKeyPath);
@@ -114,23 +145,61 @@
     boost::filesystem::remove(privateKeyPath);
 }
 
-ptr_lib::shared_ptr<PublicKey>
+shared_ptr<PublicKey>
 SecTpmFile::getPublicKeyFromTpm(const Name & keyName)
 {
   string keyURI = keyName.toUri();
 
   if(!doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
-    throw Error("public key doesn't exists");
+    return shared_ptr<PublicKey>();
 
-  string publicKeyFileName = nameTransform(keyURI, ".pub");
-  std::ostringstream os;
+  ostringstream os;
   try{
-    FileSource(publicKeyFileName.c_str(), true, new Base64Decoder(new FileSink(os)));
+    using namespace CryptoPP;
+    FileSource(m_impl->nameTransform(keyURI, ".pub").string().c_str(), true, new Base64Decoder(new FileSink(os)));
   }catch(const CryptoPP::Exception& e){
-    throw Error(e.what());
+    return shared_ptr<PublicKey>();
   }
 
-  return ptr_lib::make_shared<PublicKey>(reinterpret_cast<const uint8_t*>(os.str().c_str()), os.str().size());
+  return make_shared<PublicKey>(reinterpret_cast<const uint8_t*>(os.str().c_str()), os.str().size());
+}
+
+ConstBufferPtr
+SecTpmFile::exportPrivateKeyPkcs1FromTpm(const Name& keyName)
+{
+  OBufferStream privateKeyOs;
+  CryptoPP::FileSource(m_impl->nameTransform(keyName.toUri(), ".pri").string().c_str(), true, 
+                       new CryptoPP::Base64Decoder(new CryptoPP::FileSink(privateKeyOs)));
+  
+  return privateKeyOs.buf();
+}
+
+bool
+SecTpmFile::importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
+{
+  try{
+    string keyFileName = m_impl->maintainMapping(keyName.toUri());
+    keyFileName.append(".pri");
+    CryptoPP::StringSource(buf, size, true,
+                           new CryptoPP::Base64Encoder(new CryptoPP::FileSink(keyFileName.c_str())));
+    return true;
+  }catch(...){
+    return false;
+  }
+}
+
+bool
+SecTpmFile::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
+{
+  try{
+    string keyFileName = m_impl->maintainMapping(keyName.toUri());
+    keyFileName.append(".pub");
+    CryptoPP::StringSource(buf, size, true,
+                           new CryptoPP::Base64Encoder(new CryptoPP::FileSink(keyFileName.c_str())));
+    return true;
+  }catch(...){
+    return false;
+  }
 }
 
 Block
@@ -147,8 +216,7 @@
 
     //Read private key
     ByteQueue bytes;
-    string privateKeyFileName = nameTransform(keyURI, ".pri");
-    FileSource file(privateKeyFileName.c_str(), true, new Base64Decoder);
+    FileSource file(m_impl->nameTransform(keyURI, ".pri").string().c_str(), true, new Base64Decoder);
     file.TransferTo(bytes);
     bytes.MessageEnd();
     RSA::PrivateKey privateKey;
@@ -189,8 +257,7 @@
 
 	//Read private key
 	ByteQueue bytes;
-	string privateKeyFileName = nameTransform(keyURI, ".pri");
-	FileSource file(privateKeyFileName.c_str(), true, new Base64Decoder);
+	FileSource file(m_impl->nameTransform(keyURI, ".pri").string().c_str(), true, new Base64Decoder);
 	file.TransferTo(bytes);
 	bytes.MessageEnd();
 	RSA::PrivateKey privateKey;
@@ -214,7 +281,7 @@
 
       // try{
       // 	string keyBits;
-      // 	string symKeyFileName = nameTransform(keyURI, ".key");
+      // 	string symKeyFileName = m_impl->nameTransform(keyURI, ".key");
       // 	FileSource(symKeyFileName, true, new HexDecoder(new StringSink(keyBits)));
 	
       // 	using CryptoPP::AES;
@@ -251,8 +318,7 @@
 
 	  //Read private key
 	  ByteQueue bytes;
-	  string publicKeyFileName = nameTransform(keyURI, ".pub");
-	  FileSource file(publicKeyFileName.c_str(), true, new Base64Decoder);
+	  FileSource file(m_impl->nameTransform(keyURI, ".pub").string().c_str(), true, new Base64Decoder);
 	  file.TransferTo(bytes);
 	  bytes.MessageEnd();
 	  RSA::PublicKey publicKey;
@@ -276,7 +342,7 @@
 
       // try{
       // 	string keyBits;
-      // 	string symKeyFileName = nameTransform(keyURI, ".key");
+      // 	string symKeyFileName = m_impl->nameTransform(keyURI, ".key");
       // 	FileSource(symKeyFileName, true, new HexDecoder(new StringSink(keyBits)));
 
       // 	using CryptoPP::AES;
@@ -305,8 +371,7 @@
   if(doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
     throw Error("symmetric key exists");
 
-  string keyFileName = nameTransform(keyURI, "");
-  maintainMapping(keyURI, keyFileName);
+  string keyFileName = m_impl->maintainMapping(keyURI);
   string symKeyFileName = keyFileName + ".key";
 
   try{
@@ -338,27 +403,21 @@
   string keyURI = keyName.toUri();
   if (keyClass == KEY_CLASS_PUBLIC)
     {
-      string publicKeyName = SecTpmFile::nameTransform(keyURI, ".pub");
-      fstream fin(publicKeyName.c_str(),ios::in);
-      if (fin)
+      if(boost::filesystem::exists(m_impl->nameTransform(keyURI, ".pub")))
         return true;
       else
         return false;
     }
   if (keyClass == KEY_CLASS_PRIVATE)
     {
-      string privateKeyName = SecTpmFile::nameTransform(keyURI, ".pri");
-      fstream fin(privateKeyName.c_str(),ios::in);
-      if (fin)
+      if(boost::filesystem::exists(m_impl->nameTransform(keyURI, ".pri")))
         return true;
       else
         return false;
     }
   if (keyClass == KEY_CLASS_SYMMETRIC)
     {
-      string symmetricKeyName = SecTpmFile::nameTransform(keyURI, ".key");
-      fstream fin(symmetricKeyName.c_str(),ios::in);
-      if (fin)
+      if(boost::filesystem::exists(m_impl->nameTransform(keyURI, ".key")))
         return true;
       else
         return false;
@@ -366,38 +425,6 @@
   return false;
 }
 
-std::string SecTpmFile::nameTransform(const string &keyName, const string &extension)
-{
-  std::string digest;
-  CryptoPP::SHA256 hash;
-  CryptoPP::StringSource foo(keyName, true,
-                             new CryptoPP::HashFilter(hash,
-                                                      new CryptoPP::Base64Encoder (new CryptoPP::StringSink(digest))
-                                                      )
-                             );
-  boost::algorithm::trim(digest);
-  for (std::string::iterator ch = digest.begin(); ch != digest.end(); ch++)
-    {
-      if (*ch == '/')
-        {
-          *ch = '%';
-        }
-    }
-
-  return (m_impl->m_keystorePath / (digest + extension)).string();
-}
-
-void 
-SecTpmFile::maintainMapping(string str1, string str2)
-{
-  std::ofstream outfile;
-  string dirFile = (m_impl->m_keystorePath / "mapping.txt").string();
-
-  outfile.open(dirFile.c_str(), std::ios_base::app);
-  outfile << str1 << ' ' << str2 << '\n';
-  outfile.close();
-}
-
 bool
 SecTpmFile::generateRandomBlock(uint8_t* res, size_t size)
 {
diff --git a/src/security/sec-tpm-file.hpp b/src/security/sec-tpm-file.hpp
index 7a92ec1..f1e6fa8 100644
--- a/src/security/sec-tpm-file.hpp
+++ b/src/security/sec-tpm-file.hpp
@@ -106,15 +106,22 @@
   virtual bool
   doesKeyExistInTpm(const Name& keyName, KeyClass keyClass);
 
-  std::string
-  nameTransform(const std::string &keyName, const std::string &extension);
   virtual bool
   generateRandomBlock(uint8_t* res, size_t size);
 
-private:
-  void 
-  maintainMapping(std::string str1, std::string str2);
+protected:
+  /******************************
+   * From TrustedPlatformModule *
+   ******************************/
+  virtual ConstBufferPtr
+  exportPrivateKeyPkcs1FromTpm(const Name& keyName);
+
+  virtual bool
+  importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size);
   
+  virtual bool
+  importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size);
+
 private:
   class Impl;
   shared_ptr<Impl> m_impl;
diff --git a/src/security/sec-tpm-memory.cpp b/src/security/sec-tpm-memory.cpp
index a115d48..231a195 100644
--- a/src/security/sec-tpm-memory.cpp
+++ b/src/security/sec-tpm-memory.cpp
@@ -76,6 +76,24 @@
   throw Error("SecTpmMemory::deleteKeyPairInTpm not implemented");
 }
 
+ConstBufferPtr
+SecTpmMemory::exportPrivateKeyPkcs1FromTpm(const Name& keyName)
+{
+  throw Error("SecTpmMemory::exportPrivateKeyPkcs1FromTpm is not implemented");
+}
+
+bool
+SecTpmMemory::importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
+{
+  throw Error("SecTpmMemory::importPrivateKeyPkcs1IntoTpm is not implemented");
+}
+
+bool
+SecTpmMemory::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
+{
+  throw Error("SecTpmMemory::importPublicKeyPkcs1IntoTpm is not implemented");
+}
+
 ptr_lib::shared_ptr<PublicKey> 
 SecTpmMemory::getPublicKeyFromTpm(const Name& keyName)
 {
diff --git a/src/security/sec-tpm-memory.hpp b/src/security/sec-tpm-memory.hpp
index 69f5052..b24246b 100644
--- a/src/security/sec-tpm-memory.hpp
+++ b/src/security/sec-tpm-memory.hpp
@@ -29,24 +29,10 @@
   virtual 
   ~SecTpmMemory();
 
-  /**
-   * Set the public and private key for the keyName.
-   * @param keyName The key name.
-   * @param publicKeyDer The public key DER byte array.
-   * @param publicKeyDerLength The length of publicKeyDer.
-   * @param privateKeyDer The private key DER byte array.
-   * @param privateKeyDerLength The length of privateKeyDer.
-   */
-  void setKeyPairForKeyName(const Name& keyName,
-                            uint8_t *publicKeyDer, size_t publicKeyDerLength,
-                            uint8_t *privateKeyDer, size_t privateKeyDerLength);
-  
-  /**
-   * Generate a pair of asymmetric keys.
-   * @param keyName The name of the key pair.
-   * @param keyType The type of the key pair, e.g. KEY_TYPE_RSA.
-   * @param keySize The size of the key pair.
-   */
+  /******************************
+   * From TrustedPlatformModule *
+   ******************************/
+
   virtual void 
   generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize);
 
@@ -108,16 +94,41 @@
   generateSymmetricKeyInTpm(const Name& keyName, KeyType keyType, int keySize);
 
   virtual bool
+  doesKeyExistInTpm(const Name& keyName, KeyClass keyClass); 
+
+  virtual bool
   generateRandomBlock(uint8_t* res, size_t size);
 
+  /******************************
+   *   SecTpmMemory specific    *
+   ******************************/
+
   /**
-   * Check if a particular key exists.
-   * @param keyName The name of the key.
-   * @param keyClass The class of the key, e.g. KEY_CLASS_PUBLIC, KEY_CLASS_PRIVATE, or KEY_CLASS_SYMMETRIC.
-   * @return True if the key exists, otherwise false.
+   * @brief Set the public and private key for the keyName.
+   *
+   * @param keyName The key name.
+   * @param publicKeyDer The public key DER byte array.
+   * @param publicKeyDerLength The length of publicKeyDer.
+   * @param privateKeyDer The private key DER byte array.
+   * @param privateKeyDerLength The length of privateKeyDer.
    */
+  void setKeyPairForKeyName(const Name& keyName,
+                            uint8_t *publicKeyDer, size_t publicKeyDerLength,
+                            uint8_t *privateKeyDer, size_t privateKeyDerLength);
+
+protected:
+  /******************************
+   * From TrustedPlatformModule *
+   ******************************/
+  virtual ConstBufferPtr
+  exportPrivateKeyPkcs1FromTpm(const Name& keyName);
+
   virtual bool
-  doesKeyExistInTpm(const Name& keyName, KeyClass keyClass);  
+  importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size);
+  
+  virtual bool
+  importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size);
+  
   
 private:
   class RsaPrivateKey;
diff --git a/src/security/sec-tpm-osx.cpp b/src/security/sec-tpm-osx.cpp
index 3f14f43..d85636d 100644
--- a/src/security/sec-tpm-osx.cpp
+++ b/src/security/sec-tpm-osx.cpp
@@ -11,6 +11,8 @@
 
 #include "security/public-key.hpp"
 #include "util/logging.hpp"
+#include <cryptopp/files.h>
+#include <cryptopp/asn.h>
 
 #include <pwd.h>
 #include <unistd.h>
@@ -92,9 +94,6 @@
   long 
   getDigestSize(DigestAlgorithm digestAlgo);
 
-  bool
-  getPassWord(string& password, string target);
-
   ///////////////////////////////////////////////
   // everything here is public, including data //
   ///////////////////////////////////////////////
@@ -115,7 +114,7 @@
       string keyChainName("ndnroot.keychain");
       cerr << "No Default KeyChain! Create " << keyChainName << ":" << endl;
       string password;
-      while(!m_impl->getPassWord(password, keyChainName))
+      while(!getPassWord(password, keyChainName))
         {
           cerr << "Password mismatch!" << endl;
         }
@@ -226,25 +225,17 @@
 void
 SecTpmOsx::deleteKeyPairInTpm(const Name &keyName)
 {
-  string keyNameUri = keyName.toUri();
-
   CFStringRef keyLabel = CFStringCreateWithCString(NULL, 
-                                                   keyNameUri.c_str(), 
+                                                   keyName.toUri().c_str(), 
                                                    kCFStringEncodingUTF8);
-    
-  CFMutableDictionaryRef attrDict = CFDictionaryCreateMutable(NULL,
-                                                              5,
-                                                              &kCFTypeDictionaryKeyCallBacks,
-                                                              NULL);
 
-  CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
-  CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
-  CFDictionaryAddValue(attrDict, kSecMatchLimit, kSecMatchLimitAll);
+  CFMutableDictionaryRef searchDict = 
+    CFDictionaryCreateMutable(NULL, 5, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 
-  OSStatus res = SecItemDelete((CFDictionaryRef) attrDict);
-    
-  if(res != errSecSuccess)
-    _LOG_DEBUG("Fail to find the key!");
+  CFDictionaryAddValue(searchDict, kSecClass, kSecClassKey);
+  CFDictionaryAddValue(searchDict, kSecAttrLabel, keyLabel);
+  CFDictionaryAddValue(searchDict, kSecMatchLimit, kSecMatchLimitAll);
+  SecItemDelete(searchDict);
 }
 
 void 
@@ -293,7 +284,181 @@
                                NULL,
                                &exportedKey);
 
-  return ptr_lib::make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
+  shared_ptr<PublicKey> key = make_shared<PublicKey>(CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
+  CFRelease(exportedKey);
+  return key;
+}
+
+ConstBufferPtr
+SecTpmOsx::exportPrivateKeyPkcs1FromTpm(const Name& keyName)
+{
+  using namespace CryptoPP;
+
+  SecKeychainItemRef privateKey = m_impl->getKey(keyName, KEY_CLASS_PRIVATE);
+  CFDataRef exportedKey;
+  OSStatus res = SecItemExport(privateKey,
+                               kSecFormatOpenSSL,
+                               0,
+                               NULL,
+                               &exportedKey);
+
+  if(res != errSecSuccess)
+    {
+      return shared_ptr<Buffer>();
+    }
+
+  OBufferStream pkcs1Os;
+  FileSink sink(pkcs1Os);
+
+  uint32_t version = 0;
+  OID algorithm("1.2.840.113549.1.1.1");
+  SecByteBlock rawKeyBits;
+  // PrivateKeyInfo ::= SEQUENCE {
+  //   version              INTEGER,
+  //   privateKeyAlgorithm  SEQUENCE,
+  //   privateKey           OCTECT STRING}
+  DERSequenceEncoder privateKeyInfo(sink);
+  {
+    DEREncodeUnsigned<uint32_t>(privateKeyInfo, version, INTEGER);
+    DERSequenceEncoder privateKeyAlgorithm(privateKeyInfo);
+    {
+      algorithm.encode(privateKeyAlgorithm);
+      DEREncodeNull(privateKeyAlgorithm);
+    }
+    privateKeyAlgorithm.MessageEnd();
+    DEREncodeOctetString(privateKeyInfo, CFDataGetBytePtr(exportedKey), CFDataGetLength(exportedKey));
+  }
+  privateKeyInfo.MessageEnd(); 
+
+  CFRelease(exportedKey);
+  return pkcs1Os.buf();
+}
+
+bool
+SecTpmOsx::importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
+{
+  using namespace CryptoPP;
+
+  StringSource privateKeySource(buf, size, true);
+  uint32_t tmpNum;
+  OID tmpOID;
+  SecByteBlock rawKeyBits;
+  // PrivateKeyInfo ::= SEQUENCE {
+  //   INTEGER,
+  //   SEQUENCE,
+  //   OCTECT STRING}
+  BERSequenceDecoder privateKeyInfo(privateKeySource);
+  {
+    BERDecodeUnsigned<uint32_t>(privateKeyInfo, tmpNum, INTEGER);
+    BERSequenceDecoder sequenceDecoder(privateKeyInfo);
+    {
+      tmpOID.decode(sequenceDecoder);
+      BERDecodeNull(sequenceDecoder);
+    }
+    BERDecodeOctetString(privateKeyInfo, rawKeyBits);
+  }
+  privateKeyInfo.MessageEnd(); 
+
+  CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
+                                                      rawKeyBits.BytePtr(),
+                                                      rawKeyBits.size(),
+                                                      kCFAllocatorNull);
+
+  SecExternalFormat externalFormat = kSecFormatOpenSSL;
+  SecExternalItemType externalType = kSecItemTypePrivateKey;
+  SecKeyImportExportParameters keyParams;
+  memset(&keyParams, 0, sizeof(keyParams));
+  keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+  keyParams.keyAttributes = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
+  SecAccessRef access;
+  CFStringRef keyLabel = CFStringCreateWithCString(NULL, 
+                                                   keyName.toUri().c_str(), 
+                                                   kCFStringEncodingUTF8);
+  SecAccessCreate(keyLabel, NULL, &access);
+  keyParams.accessRef = access;
+  CFArrayRef outItems;
+
+  OSStatus res = SecKeychainItemImport (importedKey,
+                                        NULL,
+                                        &externalFormat,
+                                        &externalType,
+                                        0,
+                                        &keyParams,
+                                        m_impl->m_keyChainRef,
+                                        &outItems);
+  
+  if(res != errSecSuccess)
+    {
+      return false;
+    }
+
+  SecKeychainItemRef privateKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
+  SecKeychainAttribute attrs[1]; // maximum number of attributes
+  SecKeychainAttributeList attrList = { 0, attrs };
+  string keyUri = keyName.toUri();
+  {
+    attrs[attrList.count].tag = kSecKeyPrintName;
+    attrs[attrList.count].length = keyUri.size();
+    attrs[attrList.count].data = (void *)keyUri.c_str();
+    attrList.count++;
+  }
+
+  res = SecKeychainItemModifyAttributesAndData(privateKey, 
+                                               &attrList,
+                                               0,
+                                               NULL);
+  
+  if(res != errSecSuccess)
+    {
+      return false;
+    }
+ 
+  CFRelease(importedKey);
+  return true;
+}
+
+bool
+SecTpmOsx::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
+{
+  CFDataRef importedKey = CFDataCreateWithBytesNoCopy(NULL,
+                                                      buf,
+                                                      size,
+                                                      kCFAllocatorNull);
+
+  SecExternalFormat externalFormat = kSecFormatOpenSSL;
+  SecExternalItemType externalType = kSecItemTypePublicKey;
+  CFArrayRef outItems;
+
+  OSStatus res = SecItemImport (importedKey,
+                                NULL,
+                                &externalFormat,
+                                &externalType,
+                                0,
+                                NULL,
+                                m_impl->m_keyChainRef,
+                                &outItems);
+
+  if(res != errSecSuccess)
+    return false;
+
+  SecKeychainItemRef publicKey = (SecKeychainItemRef)CFArrayGetValueAtIndex(outItems, 0);
+  SecKeychainAttribute attrs[1]; // maximum number of attributes
+  SecKeychainAttributeList attrList = { 0, attrs };
+  string keyUri = keyName.toUri();
+  {
+    attrs[attrList.count].tag = kSecKeyPrintName;
+    attrs[attrList.count].length = keyUri.size();
+    attrs[attrList.count].data = (void *)keyUri.c_str();
+    attrList.count++;
+  }
+
+  res = SecKeychainItemModifyAttributesAndData(publicKey, 
+                                               &attrList,
+                                               0,
+                                               NULL);
+  
+  CFRelease(importedKey);
+  return true;
 }
 
 Block
@@ -549,17 +714,17 @@
                                                               NULL);
 
   CFDictionaryAddValue(attrDict, kSecClass, kSecClassKey);
-  CFDictionaryAddValue(attrDict, kSecAttrKeyClass, m_impl->getKeyClass(keyClass));
+  // CFDictionaryAddValue(attrDict, kSecAttrKeyClass, m_impl->getKeyClass(keyClass));
   CFDictionaryAddValue(attrDict, kSecAttrLabel, keyLabel);
   CFDictionaryAddValue(attrDict, kSecReturnRef, kCFBooleanTrue);
     
   SecKeychainItemRef itemRef;
   OSStatus res = SecItemCopyMatching((CFDictionaryRef)attrDict, (CFTypeRef*)&itemRef);
     
-  if(res == errSecItemNotFound)
-    return false;
-  else
+  if(res == errSecSuccess)
     return true;
+  else
+    return false;
 
 }
 
@@ -688,40 +853,5 @@
     return -1;
   }
 }
-
-bool
-SecTpmOsx::Impl::getPassWord(string& password, string target)
-{
-  int result = false;
-
-  string prompt1 = "Password for " + target + ":";
-  string prompt2 = "Confirm password for " + target + ":";
-  char* pw0 = NULL;
-  
-  pw0 = getpass(prompt1.c_str());
-  if(!pw0) 
-    return false;
-  string password1 = pw0;
-  memset(pw0, 0, strlen(pw0));
-
-  pw0 = getpass(prompt2.c_str());
-  if(!pw0)
-    {
-      char* pw1 = const_cast<char*>(password1.c_str());
-      memset(pw1, 0, password1.size());
-      return false;
-    }
-
-  if(!password1.compare(pw0))
-    {
-      result = true;
-      password.swap(password1);
-    }
-
-  char* pw1 = const_cast<char*>(password1.c_str());
-  memset(pw1, 0, password1.size());
-  memset(pw0, 0, strlen(pw0));  
-  return result;
-}
   
 }// ndn
diff --git a/src/security/sec-tpm-osx.hpp b/src/security/sec-tpm-osx.hpp
index c4a4972..251df24 100644
--- a/src/security/sec-tpm-osx.hpp
+++ b/src/security/sec-tpm-osx.hpp
@@ -107,18 +107,20 @@
   bool 
   setACL(const Name& keyName, KeyClass keyClass, int acl, const std::string& appPath);
 
-  // /**
-  //  * verify data (test only)
-  //  * @param keyName the name of key
-  //  * @param pData the data to be verified
-  //  * @param pSig the signature associated with the data
-  //  * @param digestAlgo digest algorithm
-  //  * @return true if signature can be verified, otherwise false
-  //  */
-  // bool 
-  // verifyData(const Name & keyName, const Blob & pData, const Blob & pSig, DigestAlgorithm digestAlgo = DIGEST_ALGORITHM_SHA256);
+protected:
+  /******************************
+   * From TrustedPlatformModule *
+   ******************************/
+  virtual ConstBufferPtr
+  exportPrivateKeyPkcs1FromTpm(const Name& keyName);
 
- private:
+  virtual bool
+  importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size);
+
+  virtual bool
+  importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size);
+  
+private:
   class Impl;
   shared_ptr<Impl> m_impl;
 };
diff --git a/src/security/sec-tpm.cpp b/src/security/sec-tpm.cpp
new file mode 100644
index 0000000..13b04a8
--- /dev/null
+++ b/src/security/sec-tpm.cpp
@@ -0,0 +1,287 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "sec-tpm.hpp"
+
+#include <cryptopp/rsa.h>
+#include <cryptopp/files.h>
+#include <cryptopp/base64.h>
+#include <cryptopp/hex.h>
+#include <cryptopp/osrng.h>
+#include <cryptopp/sha.h>
+#include <cryptopp/pssr.h>
+#include <cryptopp/modes.h>
+#include <cryptopp/pwdbased.h>
+#include <cryptopp/sha.h>
+#include <cryptopp/des.h>
+
+using namespace std;
+
+namespace ndn {
+
+ConstBufferPtr
+SecTpm::exportPrivateKeyPkcs8FromTpm(const Name& keyName, bool inTerminal, const string& passwordStr)
+{
+  uint8_t salt[8] = {0};
+  uint8_t iv[8] = {0};
+    
+  try{
+    using namespace CryptoPP;
+
+    // check password
+    string password;
+    if(passwordStr.empty())
+      if(!inTerminal)
+        return shared_ptr<Buffer>();
+      else
+        {
+          int count = 0;
+          while(!getPassWord(password, keyName.toUri()))
+            {
+              cerr << "Password mismatch!" << endl;
+              count++;
+              if(count > 3)
+                return shared_ptr<Buffer>();
+            }
+        }
+    else
+      password = passwordStr;
+
+    // derive key
+    if(!generateRandomBlock(salt, 8))
+      return shared_ptr<Buffer>();
+    
+    if(!generateRandomBlock(iv, 8))
+      return shared_ptr<Buffer>();
+    
+    uint32_t iterationCount = 2048;
+
+    PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
+    size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
+    byte derived[24] = {0};
+    byte purpose = 0;
+
+    keyGenerator.DeriveKey(derived, derivedLen, 
+                           purpose, 
+                           reinterpret_cast<const byte*>(password.c_str()), password.size(), 
+                           salt, 8, 
+                           iterationCount); 
+    
+    memset(const_cast<char*>(password.c_str()), 0, password.size());
+
+    //encrypt
+    CBC_Mode< DES_EDE3 >::Encryption e;
+    e.SetKeyWithIV(derived, derivedLen, iv);
+    
+    string encrypted;
+    OBufferStream encryptedOs;
+    ConstBufferPtr pkcs1PrivateKey = exportPrivateKeyPkcs1FromTpm(keyName);
+    StringSource stringSource(pkcs1PrivateKey->buf(), pkcs1PrivateKey->size(), true, 
+			      new StreamTransformationFilter(e, new FileSink(encryptedOs)));
+
+    //encode
+    OID pbes2Id("1.2.840.113549.1.5.13");
+    OID pbkdf2Id("1.2.840.113549.1.5.12");
+    OID pbes2encsId("1.2.840.113549.3.7");
+
+    OBufferStream pkcs8Os;
+    FileSink sink(pkcs8Os);
+  
+    // EncryptedPrivateKeyInfo ::= SEQUENCE {
+    //   encryptionAlgorithm  EncryptionAlgorithmIdentifier,
+    //   encryptedData        OCTET STRING }
+    DERSequenceEncoder encryptedPrivateKeyInfo(sink);
+    {
+      // EncryptionAlgorithmIdentifier ::= SEQUENCE {
+      //   algorithm      OBJECT IDENTIFIER {{PBES2-id}},
+      //   parameters     SEQUENCE {{PBES2-params}} }
+      DERSequenceEncoder encryptionAlgorithm(encryptedPrivateKeyInfo);
+      {
+        pbes2Id.encode(encryptionAlgorithm);
+        // PBES2-params ::= SEQUENCE {
+        //   keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+        //   encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
+        DERSequenceEncoder pbes2Params(encryptionAlgorithm);
+        {
+          // AlgorithmIdentifier ::= SEQUENCE {
+          //   algorithm      OBJECT IDENTIFIER {{PBKDF2-id}},
+          //   parameters     SEQUENCE {{PBKDF2-params}} }
+          DERSequenceEncoder pbes2KDFs(pbes2Params);
+          {
+             pbkdf2Id.encode(pbes2KDFs);
+            // AlgorithmIdentifier ::= SEQUENCE {
+            //   salt           OCTET STRING,
+            //   iterationCount INTEGER (1..MAX),
+            //   keyLength      INTEGER (1..MAX) OPTIONAL,
+            //   prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
+            DERSequenceEncoder pbkdf2Params(pbes2KDFs);
+            {
+              DEREncodeOctetString(pbkdf2Params, salt, 8);
+              DEREncodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
+            }
+            pbkdf2Params.MessageEnd();
+          }
+          pbes2KDFs.MessageEnd();
+        
+          // AlgorithmIdentifier ::= SEQUENCE {
+          //   algorithm   OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
+          //   parameters  OCTET STRING} {{iv}} }
+          DERSequenceEncoder pbes2Encs(pbes2Params);
+          {
+            pbes2encsId.encode(pbes2Encs);
+            DEREncodeOctetString(pbes2Encs, iv, 8);
+          }
+          pbes2Encs.MessageEnd();
+        }
+        pbes2Params.MessageEnd();
+      }
+      encryptionAlgorithm.MessageEnd();
+
+      DEREncodeOctetString(encryptedPrivateKeyInfo, encryptedOs.buf()->buf(), encryptedOs.buf()->size());
+    }
+    encryptedPrivateKeyInfo.MessageEnd();
+
+    return pkcs8Os.buf();
+  }catch(...){
+    return shared_ptr<Buffer>();
+  }
+}
+
+bool
+SecTpm::importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, bool inTerminal, const string& passwordStr)
+{
+  try{
+    using namespace CryptoPP;
+    
+    OID pbes2Id;
+    OID pbkdf2Id;
+    SecByteBlock saltBlock;
+    uint32_t iterationCount;
+    OID pbes2encsId;
+    SecByteBlock ivBlock;
+    SecByteBlock encryptedDataBlock;
+    
+    //decode some decoding processes are not necessary for now, because we assume only one encryption scheme.
+    StringSource source(buf, size, true);
+    
+    // EncryptedPrivateKeyInfo ::= SEQUENCE {
+    //   encryptionAlgorithm  EncryptionAlgorithmIdentifier,
+    //   encryptedData        OCTET STRING }
+    BERSequenceDecoder encryptedPrivateKeyInfo(source);
+    {
+      // EncryptionAlgorithmIdentifier ::= SEQUENCE {
+      //   algorithm      OBJECT IDENTIFIER {{PBES2-id}},
+      //   parameters     SEQUENCE {{PBES2-params}} }
+      BERSequenceDecoder encryptionAlgorithm(encryptedPrivateKeyInfo);
+      {
+        pbes2Id.decode(encryptionAlgorithm);
+        // PBES2-params ::= SEQUENCE {
+        //   keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+        //   encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
+        BERSequenceDecoder pbes2Params(encryptionAlgorithm);
+        {
+          // AlgorithmIdentifier ::= SEQUENCE {
+          //   algorithm      OBJECT IDENTIFIER {{PBKDF2-id}},
+          //   parameters     SEQUENCE {{PBKDF2-params}} }
+          BERSequenceDecoder pbes2KDFs(pbes2Params);
+          {
+            pbkdf2Id.decode(pbes2KDFs);
+            // AlgorithmIdentifier ::= SEQUENCE {
+            //   salt           OCTET STRING,
+            //   iterationCount INTEGER (1..MAX),
+            //   keyLength      INTEGER (1..MAX) OPTIONAL,
+            //   prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
+            BERSequenceDecoder pbkdf2Params(pbes2KDFs);
+            {
+              BERDecodeOctetString(pbkdf2Params, saltBlock);
+              BERDecodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
+            }
+            pbkdf2Params.MessageEnd();
+          }
+          pbes2KDFs.MessageEnd();
+        
+          // AlgorithmIdentifier ::= SEQUENCE {
+          //   algorithm   OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
+          //   parameters  OCTET STRING} {{iv}} }
+          BERSequenceDecoder pbes2Encs(pbes2Params);
+          {
+            pbes2encsId.decode(pbes2Encs);
+            BERDecodeOctetString(pbes2Encs, ivBlock);
+          }
+          pbes2Encs.MessageEnd();
+        }
+        pbes2Params.MessageEnd();
+      }
+      encryptionAlgorithm.MessageEnd();
+
+      BERDecodeOctetString(encryptedPrivateKeyInfo, encryptedDataBlock);
+    }
+    encryptedPrivateKeyInfo.MessageEnd();
+
+  
+    PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
+    size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
+    byte derived[24] = {0};
+    byte purpose = 0;
+
+    string password;
+    if(passwordStr.empty())
+      if(inTerminal)
+        {
+          char* pw = getpass("Password for the private key: ");
+          if (!pw)
+            return false;
+          password = pw;
+          memset(pw, 0, strlen(pw));
+        }
+      else
+        return false;
+    else
+      password = passwordStr;
+      
+    keyGenerator.DeriveKey(derived, derivedLen, 
+                           purpose, 
+                           reinterpret_cast<const byte*>(password.c_str()), password.size(), 
+                           saltBlock.BytePtr(), saltBlock.size(), 
+                           iterationCount);
+
+    memset(const_cast<char*>(password.c_str()), 0, password.size());
+        
+    //decrypt
+    CBC_Mode< DES_EDE3 >::Decryption d;
+    d.SetKeyWithIV(derived, derivedLen, ivBlock.BytePtr());
+    
+    OBufferStream privateKeyOs;
+    StringSource encryptedSource(encryptedDataBlock.BytePtr(), encryptedDataBlock.size(), true, 
+                                 new StreamTransformationFilter(d,  new FileSink(privateKeyOs)));
+
+    if(!importPrivateKeyPkcs1IntoTpm(keyName, privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()))
+      return false;
+    
+    //derive public key
+    RSA::PrivateKey privateKey;
+    privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref());
+
+    RSAFunction publicKey(privateKey);
+
+    OBufferStream publicKeyOs;
+    FileSink publicKeySink(publicKeyOs);
+    publicKey.DEREncode(publicKeySink);
+    publicKeySink.MessageEnd();
+
+    if(!importPublicKeyPkcs1IntoTpm(keyName, publicKeyOs.buf()->buf(), publicKeyOs.buf()->size()))
+      return false;
+
+    return true;
+  }catch(std::runtime_error& e){
+    cerr << e.what() << endl;
+    return false;
+  }
+}
+
+
+}//ndn
diff --git a/src/security/sec-tpm.hpp b/src/security/sec-tpm.hpp
index 9c15ad7..dcdea95 100644
--- a/src/security/sec-tpm.hpp
+++ b/src/security/sec-tpm.hpp
@@ -104,16 +104,115 @@
   doesKeyExistInTpm(const Name& keyName, KeyClass keyClass) = 0;  
 
   /**
-   * @brief Generate a random number.
+   * @brief Generate a random block.
    * 
-   * @param res The pointer to the generated number.
-   * @param size The random number size.
+   * @param res The pointer to the generated block.
+   * @param size The random block size.
    * @return true for success, otherwise false.
    */
   virtual bool
   generateRandomBlock(uint8_t* res, size_t size) = 0;
+
+  /**
+   * @brief Export a private key in PKCS#8 format.
+   * 
+   * @param keyName The private key name.
+   * @param password The password to encrypt the private key.
+   * @param inTerminal If password is not supplied, get it via terminal if inTerminal is true, otherwise fail.
+   * @return The private key info (in PKCS8 format) if exist, otherwise a NULL pointer.
+   */
+  ConstBufferPtr
+  exportPrivateKeyPkcs8FromTpm(const Name& keyName, bool inTerminal, const std::string& password);
+
+  /**
+   * @brief Import a private key in PKCS#8 format.
+   * 
+   * Also recover the public key and installed it in TPM.
+   * 
+   * @param keyName The private key name.
+   * @param key The encoded private key info.
+   * @param password The password to encrypt the private key.
+   * @param inTerminal If password is not supplied, get it via terminal if inTerminal is true, otherwise fail.
+   * @return False if import fails.
+   */
+  bool
+  importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, bool inTerminal, const std::string& password);
+
+protected:
+  /**
+   * @brief Export a private key in PKCS#1 format.
+   * 
+   * @param keyName The private key name.
+   * @return The private key info (in PKCS#1 format) if exist, otherwise a NULL pointer.
+   */
+  virtual ConstBufferPtr
+  exportPrivateKeyPkcs1FromTpm(const Name& keyName) = 0;
+
+  /**
+   * @brief Import a private key in PKCS#1 format.
+   * 
+   * @param keyName The private key name.
+   * @param key The encoded private key info.
+   * @return False if import fails.
+   */
+  virtual bool
+  importPrivateKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size) = 0;
+
+  /**
+   * @brief Import a public key in PKCS#1 format.
+   * 
+   * @param keyName The public key name.
+   * @param key The encoded public key info.
+   * @return False if import fails.
+   */
+  virtual bool
+  importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size) = 0;
+
+
+  /**
+   * @brief Get password.
+   *
+   * @param password On return, the password.
+   * @param prompt Prompt for password, i.e., "Password for key:"
+   * @return true if password has been obtained.
+   */
+  inline virtual bool
+  getPassWord(std::string& password, const std::string& prompt);
 };
 
+bool
+SecTpm::getPassWord(std::string& password, const std::string& prompt)
+{
+  int result = false;
+
+  char* pw0 = NULL;
+  
+  pw0 = getpass(prompt.c_str());
+  if(!pw0) 
+    return false;
+  std::string password1 = pw0;
+  memset(pw0, 0, strlen(pw0));
+
+  pw0 = getpass("Confirm:");
+  if(!pw0)
+    {
+      char* pw1 = const_cast<char*>(password1.c_str());
+      memset(pw1, 0, password1.size());
+      return false;
+    }
+
+  if(!password1.compare(pw0))
+    {
+      result = true;
+      password.swap(password1);
+    }
+
+  char* pw1 = const_cast<char*>(password1.c_str());
+  memset(pw1, 0, password1.size());
+  memset(pw0, 0, strlen(pw0));  
+  return result;
+}
+
 }
 
 #endif
diff --git a/src/security/validator-regex.cpp b/src/security/validator-regex.cpp
index 1b9dcb9..b85bad2 100644
--- a/src/security/validator-regex.cpp
+++ b/src/security/validator-regex.cpp
@@ -62,7 +62,7 @@
     }
   else
     {
-      _LOG_DEBUG("Wrong Invalidity: " << e.what());
+      _LOG_DEBUG("Wrong Invalidity:");
       onValidationFailed(data);
       return;
     }
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
index a44c333..6eec2d0 100644
--- a/src/security/validator.cpp
+++ b/src/security/validator.cpp
@@ -122,7 +122,7 @@
       }
     default:
       {
-        _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
+        _LOG_DEBUG("verifySignature: Unknown signature type: " << data.getSignature().getType());
         return false;
       }
     }
diff --git a/tests/security/test-keychain.cpp b/tests/security/test-keychain.cpp
new file mode 100644
index 0000000..985ef82
--- /dev/null
+++ b/tests/security/test-keychain.cpp
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi0@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include <boost/test/unit_test.hpp>
+
+#include "security/key-chain.hpp"
+#include "util/time.hpp"
+
+using namespace std;
+
+namespace ndn {
+
+BOOST_AUTO_TEST_SUITE(TestKeyChain)
+
+BOOST_AUTO_TEST_CASE (ExportIdentity)
+{
+  KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> keyChain;
+
+  Name identity(string("/TestKeyChain/ExportIdentity/") + boost::lexical_cast<std::string>(time::now()));
+  keyChain.createIdentity(identity);
+  
+  Block exported = keyChain.exportIdentity(identity, true, "1234");
+
+  Name keyName = keyChain.getDefaultKeyNameForIdentity(identity);
+  Name certName = keyChain.getDefaultCertificateNameForKey(keyName);
+
+  keyChain.deleteIdentity(identity);
+
+  BOOST_REQUIRE(keyChain.doesIdentityExist(identity) == false);
+  BOOST_REQUIRE(keyChain.doesPublicKeyExist(keyName) == false);
+  BOOST_REQUIRE(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
+  BOOST_REQUIRE(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+  BOOST_REQUIRE(keyChain.doesCertificateExist(certName) == false);
+
+  keyChain.importIdentity(exported, true, "1234");
+
+  BOOST_REQUIRE(keyChain.doesIdentityExist(identity));
+  BOOST_REQUIRE(keyChain.doesPublicKeyExist(keyName));
+  BOOST_REQUIRE(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE));
+  BOOST_REQUIRE(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC));
+  BOOST_REQUIRE(keyChain.doesCertificateExist(certName));
+
+  keyChain.deleteIdentity(identity);
+
+  BOOST_REQUIRE(keyChain.doesIdentityExist(identity) == false);
+  BOOST_REQUIRE(keyChain.doesPublicKeyExist(keyName) == false);
+  BOOST_REQUIRE(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
+  BOOST_REQUIRE(keyChain.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+  BOOST_REQUIRE(keyChain.doesCertificateExist(certName) == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace ndn
diff --git a/tests/security/test-sec-tpm-file.cpp b/tests/security/test-sec-tpm-file.cpp
index 55bc983..04adf1f 100644
--- a/tests/security/test-sec-tpm-file.cpp
+++ b/tests/security/test-sec-tpm-file.cpp
@@ -12,6 +12,7 @@
 
 #include "security/key-chain.hpp"
 #include <cryptopp/rsa.h>
+#include <cryptopp/hex.h>
 
 using namespace std;
 namespace ndn {
@@ -85,6 +86,85 @@
   BOOST_CHECK_CLOSE(dev / 256, 0.001, 100);
 
 }
+
+BOOST_AUTO_TEST_CASE (ImportExportKey)
+{
+  using namespace CryptoPP;
+
+  string imported(
+"3082050E304006092A864886F70D01050D3033301B06092A864886F70D01050C300E0408209CF0B1B4C856A802020800301406082A864886F70D0307040884B1229D80690211048204C8DA62C11E1CCFC43F318D0C03DA4B11350122B18F23645C454F41BB46C7F8EED4F95041A9130B33E989AF338951A286B55FB9A707AF1C5B2E1FAE7CD66D6D556CBFD90640BDA0D7904DD8D89CF15AB24F1A652AB76E16411B78E8A9AAEEB6EE06FA793B2B4A3EE4B9B5DFB3FC3D38076145915A11CEC8FD2EAB70F51A0DA8B88B73B4DD5BAFB933ABCD92FFBA7843083CCE6B7A6BD9A51094EFF93DC93A19B4982F5FF8696FDF07B76366B6408EC18F4EA218A4F6B5EA85A5AF3B082D0E3AE74665BDD9FC7DE87A7A54EB038AB2E9196365F8481F1CC601EB866D554B4FBCDABECD35CBE404F3CB313E9799D111AD955C42629FB1A01E6138EFF15E6DE7D2BF8754868157DAC72EE5125221D502DCF0B8E8FF5CA87B601357785E7C95CBFC369B31D747ADACFB95E614507A5622ACAA3541B4FE02AEEC2DD588D3D7860A50C78EF460C39E250851140155052F18419F37D551FC3F5224764A17A2C47F9CEDC63780E3AF48C421D682FD3A68A2E12EB28737DB0F785137FC01282D0D82220E2D147E4E2D261046D3C5842B55C1C2F6BA51727AF57C502242F397ACEC341F2C6C6E739E629A144602C9994C88B4F8B4F7150C087C143D9FEC23A686E5E46A5541A071869089BECC05B186FC3D8F95668A671D7088462D61423BAEB73B41CDA5B69E22D6EE3A64BB523B1522F2433BA8AD98A7500EB5C5859469F45C15E91AC1DA9D9473B3C2B37C38D038F99122E157166B89C1EA941A683A73C3F7C0762E79E9C1E28A306042D8683C26995F7AA1B5CC1B985BB0A9DEE6471E9BCEF977A2BE84BD90CE3025FA76B8B546725D85C37543B69604D3F0822DBA3067E9CF9BF2F0DC676E0D718C963C71DBD7A278BAF2A2FFA65BDB8E60FCDD0D0BA841E37284FB6174047D1EC974730A77A7E808C5F27BF1FF0818AD7B0596C538ECFF2068BD5EED5E90102918E2F224EBFFDB2C8366A5C819A00BF6DDF823BD861331F4BF2323ECA284B90C96AB6C7CDBB200163AEA8FD9EC18BA5ACAA8B8B4BDA532A04AD179D402F09E69F5CE0A179EBEF9A99E8B0C5BC8A9C3CA71C820508E33C79A98B9C31F856F53D1369AD7D9C668BC9160D6C7F3612842BDCDB42F5AE6860E93B2B203CAE26C93A7640640D403BC107DDA031CAD54DC63FFF73861D25DE26B9147C328B3940F2CFB44E82112DD6FA514CB8FD5DD6E6FF4D4EFF430B06AC970D8D75F5BD6A015558ED8D82C5121115DC3657BE88356348C0F8B8EADFD5506C0C046984BB1F12F3EEFD32FED4C8684ABD252BF3CA56092D4A752CF51E13755568C3BF25CFCA0F7AF9279CA593305C27645022DD2DD0F7FFCAC92EDEF04B9DCAE7FD55E2C69C76CF061F1ECD724850FCA574543954105B9A3824B849DDD75DEB57B382054AAB4A1FE467D235FB77C220730ED7D9B79A575831395AAE0C4C0B0D3E7EC17511C3DE9A86AD1C68BFF861FA0151020E43A1C6B4F4D6273D586B1D291AEF45DF454463F39BACA2FF07AA5E24A7EA850189F8C39BA8E88FEB21C1647EF910898B02492C49599111D3558F05A4CFD0FDBF33E802798FF2C437FCD65AAC1024FB29D08DCD7DB7E08279C3EB4B64E58747096641D1886145EC9E5ADDC8BBC81BE0DC77C3F3A017311050B921B5506F13AF30BA04AFAA210F0359E710C01319DE7BFF165A3615E8DDFC6E3FC167BA39B332B42E5207CA4934EABDAE2D057FA661DEB3EBC1A4AFD4F3E014918EC");
+
+  string decoded;
+  StringSource source(imported, true, new HexDecoder(new StringSink(decoded))); // StringSource
+
+  SecTpmFile tpm;
+
+  Name keyName("/TestSecTpmFile/ImportKey/ksk-" + boost::lexical_cast<string>(time::now()));
+
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+  
+  BOOST_REQUIRE_NO_THROW(tpm.importPrivateKeyPkcs8IntoTpm(keyName, reinterpret_cast<const uint8_t*>(decoded.c_str()), decoded.size(), true, "1234"));
+
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == true);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == true);
+
+  shared_ptr<PublicKey> pubkeyPtr = tpm.getPublicKeyFromTpm(keyName);
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock = tpm.signInTpm(content, sizeof(content), keyName, DIGEST_ALGORITHM_SHA256);
+
+  {
+    using namespace CryptoPP;
+    
+    RSA::PublicKey publicKey;
+    ByteQueue queue;
+    queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
+    publicKey.Load(queue);
+
+    RSASS<PKCS1v15, SHA256>::Verifier verifier (publicKey);
+    bool result = verifier.VerifyMessage(content, sizeof(content),
+  					 sigBlock.value(), sigBlock.value_size());
+  
+    BOOST_REQUIRE_EQUAL(result, true);
+  }
+
+  ConstBufferPtr exported = tpm.exportPrivateKeyPkcs8FromTpm(keyName, true, "5678");
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+
+  BOOST_REQUIRE(tpm.importPrivateKeyPkcs8IntoTpm(keyName, exported->buf(), exported->size(), true, "5678"));
+  
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == true);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == true);
+  
+  const uint8_t content2[] = {0x05, 0x06, 0x07, 0x08};
+  Block sigBlock2 = tpm.signInTpm(content2, sizeof(content2), keyName, DIGEST_ALGORITHM_SHA256);
+
+  {
+    using namespace CryptoPP;
+    
+    RSA::PublicKey publicKey;
+    ByteQueue queue;
+    queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
+    publicKey.Load(queue);
+
+    RSASS<PKCS1v15, SHA256>::Verifier verifier (publicKey);
+    bool result = verifier.VerifyMessage(content2, sizeof(content2),
+  					 sigBlock2.value(), sigBlock2.value_size());
+  
+    BOOST_REQUIRE_EQUAL(result, true);
+  }
+  
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // namespace ndn
diff --git a/tests/security/test-sec-tpm-osx.cpp b/tests/security/test-sec-tpm-osx.cpp
index a0a3bb9..f801018 100644
--- a/tests/security/test-sec-tpm-osx.cpp
+++ b/tests/security/test-sec-tpm-osx.cpp
@@ -85,6 +85,57 @@
   BOOST_CHECK_CLOSE(dev / 256, 0.001, 100);
 
 }
+
+BOOST_AUTO_TEST_CASE (ExportImportKey)
+{
+  using namespace CryptoPP;
+
+  SecTpmOsx tpm;
+
+  Name keyName("/TestSecTpmFile/ExportImportKey/ksk-" + boost::lexical_cast<string>(time::now()));
+  
+  BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, KEY_TYPE_RSA, 2048));
+
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == true);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == true);
+
+  ConstBufferPtr exported = tpm.exportPrivateKeyPkcs8FromTpm(keyName, true, "1234");
+  shared_ptr<PublicKey> pubkeyPtr = tpm.getPublicKeyFromTpm(keyName);
+
+  tpm.deleteKeyPairInTpm(keyName);
+
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+
+  BOOST_REQUIRE(tpm.importPrivateKeyPkcs8IntoTpm(keyName, exported->buf(), exported->size(), true, "1234"));
+  
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == true);
+  BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == true);
+
+  const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
+  Block sigBlock = tpm.signInTpm(content, sizeof(content), keyName, DIGEST_ALGORITHM_SHA256);
+
+  {
+    using namespace CryptoPP;
+    
+    RSA::PublicKey publicKey;
+    ByteQueue queue;
+    queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
+    publicKey.Load(queue);
+
+    RSASS<PKCS1v15, SHA256>::Verifier verifier (publicKey);
+    bool result = verifier.VerifyMessage(content, sizeof(content),
+  					 sigBlock.value(), sigBlock.value_size());
+  
+    BOOST_REQUIRE_EQUAL(result, true);
+  }
+  
+  tpm.deleteKeyPairInTpm(keyName);
+  // This is some problem related to Mac OS Key chain, and we will fix it later.
+  // BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
+  // BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // namespace ndn