In Face.registerPrefix, need to pass keyChain, signerName, etc. so that it can sign the Data packet with the ForwardingEntry.
diff --git a/ndn-cpp/face.hpp b/ndn-cpp/face.hpp
index 2b202ef..6e47ff7 100644
--- a/ndn-cpp/face.hpp
+++ b/ndn-cpp/face.hpp
@@ -85,12 +85,21 @@
    * @param prefix A reference to a Name for the prefix to register.  This copies the Name.
    * @param onInterest A function object to call when a matching interest is received.  This copies the function object, so you may need to
    * use func_lib::ref() as appropriate.
+   * @param onRegisterFailed A function object to call if failed to retrieve the connected hub’s ID or failed to register the prefix.
+   * This calls onRegisterFailed(prefix) where prefix is the prefix given to registerPrefix.
+   * @param keyChain The KeyChain object whose signData is called to sign the Data packet with the ForwardingEntry to register the prefix.
+   * @param signerName The signing identity or certificate name, depending on byKeyName. This is used to sign the Data packet 
+   * with the ForwardingEntry to register the prefix.This copies the function object, so you may need to use func_lib::ref() as appropriate.
+   * @param byKeyName If true, the signerName is the key name, otherwise it is the certificate name. If omitted, the default is true.
    * @param flags The flags for finer control of which interests are forward to the application.
+   * @param wireFormat A WireFormat object used to encode the input. If omitted, use WireFormat getDefaultWireFormat().
    */
   void 
-  registerPrefix(const Name& prefix, const OnInterest& onInterest, int flags = 0)
+  registerPrefix
+    (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, KeyChain &keyChain,
+     const Name& signerName, bool byKeyName = true, int flags = 0, WireFormat& wireFormat = *WireFormat::getDefaultWireFormat())
   {
-    node_.registerPrefix(prefix, onInterest, flags);
+    node_.registerPrefix(prefix, onInterest, onRegisterFailed, keyChain, signerName, byKeyName, flags, wireFormat);
   }
   
   /**
diff --git a/ndn-cpp/node.cpp b/ndn-cpp/node.cpp
index e132970..4e34ec8 100644
--- a/ndn-cpp/node.cpp
+++ b/ndn-cpp/node.cpp
@@ -26,7 +26,7 @@
   return t.tv_sec * 1000.0 + t.tv_usec / 1000.0;
 }
 
-Node::Node(const ptr_lib::shared_ptr<Transport>& transport, const ptr_lib::shared_ptr<const Transport::ConnectionInfo>& connectionInfo)
+Node::Node(const shared_ptr<Transport>& transport, const shared_ptr<const Transport::ConnectionInfo>& connectionInfo)
 : transport_(transport), connectionInfo_(connectionInfo),
   ndndIdFetcherInterest_(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"), 4000.0)
 {
@@ -46,53 +46,60 @@
 }
 
 void 
-Node::registerPrefix(const Name& prefix, const OnInterest& onInterest, int flags)
+Node::registerPrefix
+  (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, KeyChain &keyChain,
+   const Name& signerName, bool byKeyName, int flags, WireFormat& wireFormat)
 {
   if (ndndId_.size() == 0) {
     // First fetch the ndndId of the connected hub.
-    NdndIdFetcher fetcher(make_shared<NdndIdFetcher::Info>(this, prefix, onInterest, flags));
+    NdndIdFetcher fetcher
+      (shared_ptr<NdndIdFetcher::Info>(new NdndIdFetcher::Info
+                             (this, prefix, onInterest, onRegisterFailed, keyChain, signerName, byKeyName, flags, wireFormat)));
     // It is OK for func_lib::function make a copy of the function object because the Info is in a shared_ptr.
     expressInterest(ndndIdFetcherInterest_, fetcher, fetcher);
   }
   else
-    registerPrefixHelper(prefix, onInterest, flags);
+    registerPrefixHelper
+      (make_shared<const Name>(prefix), onInterest, onRegisterFailed, keyChain, make_shared<const Name>(signerName), byKeyName, 
+       flags, wireFormat);
 }
 
 void 
-Node::NdndIdFetcher::operator()(const ptr_lib::shared_ptr<const Interest>& interest, const ptr_lib::shared_ptr<Data>& ndndIdData)
+Node::NdndIdFetcher::operator()(const shared_ptr<const Interest>& interest, const shared_ptr<Data>& ndndIdData)
 {
   Sha256WithRsaSignature *signature = dynamic_cast<Sha256WithRsaSignature*>(ndndIdData->getSignature());
   if (signature && signature->getPublisherPublicKeyDigest().getPublisherPublicKeyDigest().size() > 0) {
     // Set the ndndId_ and continue.
     // TODO: If there are multiple connected hubs, the NDN ID is really stored per connected hub.
     info_->node_.ndndId_ = signature->getPublisherPublicKeyDigest().getPublisherPublicKeyDigest();
-    info_->node_.registerPrefixHelper(info_->prefix_, info_->onInterest_, info_->flags_);
+    info_->node_.registerPrefixHelper
+      (info_->prefix_, info_->onInterest_, info_->onRegisterFailed_, info_->keyChain_, info_->signerName_,
+       info_->byKeyName_, info_->flags_, info_->wireFormat_);
   }
-  // TODO: else need to log not getting the ndndId.
+  else
+    info_->onRegisterFailed_(info_->prefix_);
 }
 
 void 
-Node::NdndIdFetcher::operator()(const ptr_lib::shared_ptr<const Interest>& timedOutInterest)
+Node::NdndIdFetcher::operator()(const shared_ptr<const Interest>& timedOutInterest)
 {
-  // TODO: Log the timeout.
+  info_->onRegisterFailed_(info_->prefix_);
 }
 
 void 
-Node::registerPrefixHelper(const Name& prefix, const OnInterest& onInterest, int flags)
+Node::registerPrefixHelper
+  (const shared_ptr<const Name>& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, 
+   KeyChain &keyChain, const shared_ptr<const Name>& signerName, bool byKeyName, int flags, WireFormat& wireFormat)
 {
   // Create a ForwardingEntry.
-  ForwardingEntry forwardingEntry("selfreg", prefix, PublisherPublicKeyDigest(), -1, 3, 2147483647);
+  ForwardingEntry forwardingEntry("selfreg", *prefix, PublisherPublicKeyDigest(), -1, 3, 2147483647);
   Blob content = forwardingEntry.wireEncode();
 
   // Set the ForwardingEntry as the content of a Data packet and sign.
   Data data;
   data.setContent(content);
   data.getMetaInfo().setTimestampMilliseconds(time(NULL) * 1000.0);
-#if 0
-  KeyChain::defaultSign(data);
-#else
-#warning "Should we have the application use KeyChain.signData?"
-#endif
+  keyChain.signData(data, *signerName, byKeyName, wireFormat);
   Blob encodedData = data.wireEncode();
   
   // Create an interest where the name has the encoded Data packet.
@@ -109,7 +116,7 @@
   Blob encodedInterest = interest.wireEncode();
   
   // Save the onInterest callback and send the registration interest.
-  registeredPrefixTable_.push_back(shared_ptr<PrefixEntry>(new PrefixEntry(shared_ptr<const Name>(new Name(prefix)), onInterest)));
+  registeredPrefixTable_.push_back(shared_ptr<PrefixEntry>(new PrefixEntry(prefix, onInterest)));
   
   transport_->send(*encodedInterest);
 }
@@ -152,7 +159,7 @@
     if (iPitEntry >= 0) {
       // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
       const OnData onData = pit_[iPitEntry]->getOnData();
-      const ptr_lib::shared_ptr<const Interest> interest = pit_[iPitEntry]->getInterest();
+      const shared_ptr<const Interest> interest = pit_[iPitEntry]->getInterest();
       pit_.erase(pit_.begin() + iPitEntry);
       onData(interest, data);
     }
@@ -209,7 +216,7 @@
     return 0;
 }
 
-Node::PitEntry::PitEntry(const ptr_lib::shared_ptr<const Interest>& interest, const OnData& onData, const OnTimeout& onTimeout)
+Node::PitEntry::PitEntry(const shared_ptr<const Interest>& interest, const OnData& onData, const OnTimeout& onTimeout)
 : interest_(interest), onData_(onData), onTimeout_(onTimeout)
 {
   // Set up timeoutTime_.
diff --git a/ndn-cpp/node.hpp b/ndn-cpp/node.hpp
index 80d32a4..256e3aa 100644
--- a/ndn-cpp/node.hpp
+++ b/ndn-cpp/node.hpp
@@ -31,8 +31,14 @@
 typedef func_lib::function<void
   (const ptr_lib::shared_ptr<const Name>&, const ptr_lib::shared_ptr<const Interest>&, Transport&)> OnInterest;
 
+/**
+ * An OnRegisterFailed function object is used to report when registerPrefix fails.
+ */
+typedef func_lib::function<void(const ptr_lib::shared_ptr<const Name>&)> OnRegisterFailed;
+
 class Face;
-  
+class KeyChain;
+    
 class Node : public ElementListener {
 public:
   /**
@@ -58,10 +64,19 @@
    * @param prefix A reference to a Name for the prefix to register.  This copies the Name.
    * @param onInterest A function object to call when a matching interest is received.  This copies the function object, so you may need to
    * use func_lib::ref() as appropriate.
+   * @param onRegisterFailed A function object to call if failed to retrieve the connected hub’s ID or failed to register the prefix.
+   * This calls onRegisterFailed(prefix) where prefix is the prefix given to registerPrefix.
+   * @param keyChain The KeyChain object whose signData is called to sign the Data packet with the ForwardingEntry to register the prefix.
+   * @param signerName The signing identity or certificate name, depending on byKeyName. This is used to sign the Data packet 
+   * with the ForwardingEntry to register the prefix.This copies the function object, so you may need to use func_lib::ref() as appropriate.
+   * @param byKeyName If true, the signerName is the key name, otherwise it is the certificate name. If omitted, the default is true.
    * @param flags The flags for finer control of which interests are forward to the application.
+   * @param wireFormat A WireFormat object used to encode the input. If omitted, use WireFormat getDefaultWireFormat().
    */
   void 
-  registerPrefix(const Name& prefix, const OnInterest& onInterest, int flags);
+  registerPrefix
+    (const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, KeyChain &keyChain, 
+     const Name& signerName, bool byKeyName, int flags, WireFormat& wireFormat);
 
   /**
    * Process any data to receive.  For each element received, call onReceivedElement.
@@ -188,15 +203,22 @@
     
     class Info {
     public:
-      Info(Node *node, const Name& prefix, const OnInterest& onInterest, int flags)
-      : node_(*node), prefix_(prefix), onInterest_(onInterest), flags_(flags)
+      Info(Node *node, const Name& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, 
+           KeyChain &keyChain, const Name& signerName, bool byKeyName, int flags, WireFormat& wireFormat)
+      : node_(*node), prefix_(new Name(prefix)), onInterest_(onInterest), onRegisterFailed_(onRegisterFailed), 
+        keyChain_(keyChain), signerName_(new Name(signerName)), byKeyName_(byKeyName), flags_(flags), wireFormat_(wireFormat)
       {      
       }
       
       Node& node_;
-      Name prefix_;
+      ptr_lib::shared_ptr<const Name> prefix_;
       const OnInterest onInterest_;
+      const OnRegisterFailed onRegisterFailed_;
+      KeyChain &keyChain_;
+      ptr_lib::shared_ptr<const Name> signerName_;
+      bool byKeyName_;
       int flags_;
+      WireFormat& wireFormat_;
     };
     
   private:
@@ -210,7 +232,7 @@
    * @return The index in pit_ of the pit entry, or -1 if not found.
    */
   int 
-          getEntryIndexForExpressedInterest(const Name& name);
+  getEntryIndexForExpressedInterest(const Name& name);
   
   /**
    * Find the first entry from the registeredPrefixTable_ where the entry prefix is the longest that matches name.
@@ -219,15 +241,22 @@
    */
   PrefixEntry*
   getEntryForRegisteredPrefix(const Name& name);
-  
+
   /**
    * Do the work of registerPrefix once we know we are connected with an ndndId_.
    * @param prefix
    * @param onInterest
+   * @param onRegisterFailed
+   * @param keyChain
+   * @param signerName
+   * @param byKeyName
    * @param flags
-   */
+   * @param wireFormat
+   */  
   void 
-  registerPrefixHelper(const Name& prefix, const OnInterest& onInterest, int flags);
+  registerPrefixHelper
+    (const ptr_lib::shared_ptr<const Name>& prefix, const OnInterest& onInterest, const OnRegisterFailed& onRegisterFailed, 
+     KeyChain &keyChain, const ptr_lib::shared_ptr<const Name>& signerName, bool byKeyName, int flags, WireFormat& wireFormat);
   
   ptr_lib::shared_ptr<Transport> transport_;
   ptr_lib::shared_ptr<const Transport::ConnectionInfo> connectionInfo_;