Get rid of cryptopp dependency

Plus various code cleanups:
 * More 'auto' usage
 * Use 'nullptr' instead of 0
 * Rename NewApp class to ChronoChatApp
 * Print exception info with boost::diagnostic_information()
 * Disable -Wdeprecated-copy and -Wredundant-tags, they trigger
   too many warnings in Qt headers with gcc 9 and later

Change-Id: I2ea16c19be634f957b59280c704a956f083891f0
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 49216c8..bdae08c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -22,7 +22,6 @@
 
     steps:
     - uses: actions/checkout@v2
-
     - name: Run build script
       run: |
         ./.jenkins
@@ -33,16 +32,14 @@
 
     steps:
     - uses: actions/checkout@v2
-
     - name: Run build script
       run: |
-        sudo apt install -y software-properties-common
+        sudo apt-get -qy install software-properties-common
         sudo add-apt-repository ppa:named-data/ppa -y
-        sudo apt update
-        sudo apt-get install nfd libndn-cxx-dev libchronosync-dev
-        sudo apt-get install libcrypto++-dev libboost-all-dev qt5-default
+        sudo apt-get -qq update
+        sudo apt-get -qy install nfd libndn-cxx-dev libchronosync-dev libboost-all-dev libsqlite3-dev qt5-default
         ./waf --color=yes configure --debug
-        ./waf --color=yes build -j4
+        ./waf --color=yes build -j$(nproc)
 
   macos:
     runs-on: ${{ matrix.os }}
@@ -60,7 +57,6 @@
 
     steps:
     - uses: actions/checkout@v2
-
     - name: Run build script
       run: |
         sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
diff --git a/.jenkins.d/00-deps.sh b/.jenkins.d/00-deps.sh
index 34d006e..32278a1 100755
--- a/.jenkins.d/00-deps.sh
+++ b/.jenkins.d/00-deps.sh
@@ -8,20 +8,16 @@
     fi
 
     if [[ -n $GITHUB_ACTIONS ]]; then
-        # Homebrew doesn't have cryptopp packages, so build from source
-        git clone https://github.com/weidai11/cryptopp/
-        cd cryptopp
-        make -j4
-        make install
-        cd ..
-
-        # Travis images come with a large number of pre-installed
-        # brew packages, don't waste time upgrading all of them
+        # Don't waste time upgrading all pre-installed packages
         for FORMULA in "${FORMULAE[@]}"; do
             brew list --versions "$FORMULA" || brew install "$FORMULA"
         done
 
-        brew link qt --force
+        # Ensure /usr/local/opt/openssl exists
+        brew reinstall openssl
+
+        # Homebrew qt is keg-only, force symlinking it into /usr/local
+        brew link --force qt
     else
         brew update
         brew upgrade
@@ -31,7 +27,7 @@
 
 elif has Ubuntu $NODE_LABELS; then
     sudo apt-get -qq update
-    sudo apt-get -qy install g++ pkg-config python3-minimal \
+    sudo apt-get -qy install build-essential pkg-config python3-minimal \
                              libboost-all-dev libssl-dev libsqlite3-dev \
-                             libcrypto++-dev qt5-default
-fi
\ No newline at end of file
+                             qt5-default
+fi
diff --git a/.waf-tools/cryptopp.py b/.waf-tools/cryptopp.py
deleted file mode 100644
index b61c0bf..0000000
--- a/.waf-tools/cryptopp.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#! /usr/bin/env python
-# encoding: utf-8
-
-'''
-
-When using this tool, the wscript will look like:
-
-	def options(opt):
-	        opt.tool_options('cryptopp', tooldir=["waf-tools"])
-
-	def configure(conf):
-		conf.load('compiler_cxx cryptopp')
-
-	def build(bld):
-		bld(source='main.cpp', target='app', use='CRYPTOPP')
-
-Options are generated, in order to specify the location of cryptopp includes/libraries.
-
-
-'''
-import sys
-import re
-from waflib import Utils,Logs,Errors
-from waflib.Configure import conf
-CRYPTOPP_DIR=['/usr','/usr/local','/opt/local','/sw']
-CRYPTOPP_VERSION_FILE='config.h'
-CRYPTOPP_VERSION_CODE='''
-#include <iostream>
-#include <cryptopp/config.h>
-int main() { std::cout << CRYPTOPP_VERSION; }
-'''
-
-def options(opt):
-	opt.add_option('--cryptopp',type='string',default='',dest='cryptopp_dir',help='''path to where cryptopp is installed, e.g. /opt/local''')
-@conf
-def __cryptopp_get_version_file(self,dir):
-	try:
-		return self.root.find_dir(dir).find_node('%s/%s' % ('include/cryptopp', CRYPTOPP_VERSION_FILE))
-	except:
-		return None
-@conf
-def cryptopp_get_version(self,dir):
-	val=self.check_cxx(fragment=CRYPTOPP_VERSION_CODE,includes=['%s/%s' % (dir, 'include')], execute=True, define_ret = True, mandatory=True)
-	return val
-@conf
-def cryptopp_get_root(self,*k,**kw):
-	root=k and k[0]or kw.get('path',None)
-	# Logs.pprint ('RED', '   %s' %root)
-	if root and self.__cryptopp_get_version_file(root):
-		return root
-	for dir in CRYPTOPP_DIR:
-		if self.__cryptopp_get_version_file(dir):
-			return dir
-	if root:
-		self.fatal('CryptoPP not found in %s'%root)
-	else:
-		self.fatal('CryptoPP not found, please provide a --cryptopp argument (see help)')
-@conf
-def check_cryptopp(self,*k,**kw):
-	if not self.env['CXX']:
-		self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
-
-	var=kw.get('uselib_store','CRYPTOPP')
-	self.start_msg('Checking CRYPTOPP')
-	root = self.cryptopp_get_root(*k,**kw)
-	self.env.CRYPTOPP_VERSION=self.cryptopp_get_version(root)
-
-	self.env['INCLUDES_%s'%var]= '%s/%s' % (root, "include")
-	self.env['LIB_%s'%var] = "cryptopp"
-	self.env['LIBPATH_%s'%var] = '%s/%s' % (root, "lib")
-
-	self.end_msg(self.env.CRYPTOPP_VERSION)
-	if Logs.verbose:
-		Logs.pprint('CYAN','	CRYPTOPP include : %s'%self.env['INCLUDES_%s'%var])
-		Logs.pprint('CYAN','	CRYPTOPP lib     : %s'%self.env['LIB_%s'%var])
-		Logs.pprint('CYAN','	CRYPTOPP libpath : %s'%self.env['LIBPATH_%s'%var])
-
diff --git a/.waf-tools/default-compiler-flags.py b/.waf-tools/default-compiler-flags.py
index 7a317b1..d3246e1 100644
--- a/.waf-tools/default-compiler-flags.py
+++ b/.waf-tools/default-compiler-flags.py
@@ -151,12 +151,12 @@
                               '-Wextra',
                               '-Werror',
                               '-Wcatch-value=2',
-                              # '-Wextra-semi', # prevent noisy output with Qt5
+                              #'-Wextra-semi', # Qt5
                               '-Wnon-virtual-dtor',
                               '-Wno-error=deprecated-declarations', # Bug #3795
                               '-Wno-error=maybe-uninitialized', # Bug #1615
+                              '-Wno-deprecated-copy', # Qt5
                               '-Wno-unused-parameter',
-                              '-Wno-error=deprecated-copy', # Qt5
                               ]
         flags['LINKFLAGS'] += ['-Wl,-O1']
         return flags
@@ -169,8 +169,9 @@
                               '-Wall',
                               '-Wextra',
                               '-Wcatch-value=2',
-                              '-Wextra-semi',
+                              #'-Wextra-semi', # Qt5
                               '-Wnon-virtual-dtor',
+                              '-Wno-deprecated-copy', # Qt5
                               '-Wno-unused-parameter',
                               ]
         flags['LINKFLAGS'] += ['-Wl,-O1']
@@ -180,7 +181,7 @@
     def getDebugFlags(self, conf):
         flags = super(GccFlags, self).getDebugFlags(conf)
         flags['CXXFLAGS'] += ['-fdiagnostics-color',
-                              '-Wredundant-tags',
+                              #'-Wredundant-tags', # Qt5
                               ]
         if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
             flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
@@ -189,7 +190,7 @@
     def getOptimizedFlags(self, conf):
         flags = super(GccFlags, self).getOptimizedFlags(conf)
         flags['CXXFLAGS'] += ['-fdiagnostics-color',
-                              '-Wredundant-tags',
+                              #'-Wredundant-tags', # Qt5
                               ]
         if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
             flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
@@ -225,4 +226,4 @@
                               ]
         if self.getCompilerVersion(conf) < (6, 0, 0):
             flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
-        return flags
\ No newline at end of file
+        return flags
diff --git a/README.md b/README.md
index 3737987..f7a4779 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,4 @@
-ChronoChat
-==========
+# ChronoChat
 
 ChronoChat is a multiparty chat application that demostrates our synchronization primitive that we call ChronoSync.
 
@@ -12,10 +11,9 @@
 
 ## Compilation steps
 
-1. On Ubuntu, configure [NDN PPA repository](http://named-data.net/doc/NFD/current/FAQ.html#how-to-start-using-ndn-ppa-repository-on-ubuntu-linux) and install NFD and ChronoSYnc if you don't have it yet, then install dependencies
+1. On Ubuntu, configure the [NDN PPA repository](http://named-data.net/doc/NFD/current/FAQ.html#how-to-start-using-ndn-ppa-repository-on-ubuntu-linux) and install the necessary dependencies
 
-        sudo apt-get install nfd libndn-cxx-dev libchronosync-dev
-        sudo apt-get install libcrypto++-dev libboost-all-dev qt5-default
+        sudo apt install nfd libndn-cxx-dev libchronosync-dev libboost-all-dev libsqlite3-dev qt5-default
 
 2. Fetch source code
 
diff --git a/src/chat-dialog-backend.cpp b/src/chat-dialog-backend.cpp
index 53bfdb3..ff0a600 100644
--- a/src/chat-dialog-backend.cpp
+++ b/src/chat-dialog-backend.cpp
@@ -15,18 +15,16 @@
 
 #ifndef Q_MOC_RUN
 #include <boost/iostreams/stream.hpp>
-#include <ndn-cxx/util/io.hpp>
-#include "cryptopp.hpp"
-#endif
 
-using namespace CryptoPP;
+#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/util/string-helper.hpp>
+#endif
 
 namespace chronochat {
 
 static const time::milliseconds FRESHNESS_PERIOD(60000);
 static const time::seconds HELLO_INTERVAL(60);
-static const ndn::Name::Component ROUTING_HINT_SEPARATOR =
-  ndn::name::Component::fromEscapedString("%F0%2E");
+static const Name::Component ROUTING_HINT_SEPARATOR = Name::Component::fromEscapedString("%F0%2E");
 static const int IDENTITY_OFFSET = -3;
 static const int CONNECTION_RETRY_TIMER = 3;
 
@@ -49,10 +47,7 @@
   updatePrefixes();
 }
 
-
-ChatDialogBackend::~ChatDialogBackend()
-{
-}
+ChatDialogBackend::~ChatDialogBackend() = default;
 
 // protected methods:
 void
@@ -101,8 +96,6 @@
     close();
 
   } while (shouldResume);
-
-  std::cerr << "Bye!" << std::endl;
 }
 
 // private methods:
@@ -183,7 +176,6 @@
 
   std::vector<NodeInfo> nodeInfos;
 
-
   for (size_t i = 0; i < updates.size(); i++) {
     // update roster
     if (m_roster.find(updates[i].session) == m_roster.end()) {
@@ -214,13 +206,11 @@
 
   // reflect the changes on GUI
   emit syncTreeUpdated(nodeInfos,
-                       QString::fromStdString(getHexEncodedDigest(m_sock->getRootDigest())));
+                       QString::fromStdString(ndn::toHex(*m_sock->getRootDigest(), false)));
 }
 
 void
-ChatDialogBackend::processChatData(const ndn::Data& data,
-                                   bool needDisplay,
-                                   bool isValidated)
+ChatDialogBackend::processChatData(const ndn::Data& data, bool needDisplay, bool isValidated)
 {
   ChatMessage msg;
 
@@ -344,7 +334,7 @@
   nodeInfos.push_back(nodeInfo);
 
   emit syncTreeUpdated(nodeInfos,
-                       QString::fromStdString(getHexEncodedDigest(m_sock->getRootDigest())));
+                       QString::fromStdString(ndn::toHex(*m_sock->getRootDigest(), false)));
 
   emit messageReceived(QString::fromStdString(sessionName.toUri()),
                        QString::fromStdString(msg.getNick()),
@@ -432,16 +422,6 @@
   emit chatPrefixChanged(m_routableUserChatPrefix);
 }
 
-std::string
-ChatDialogBackend::getHexEncodedDigest(ndn::ConstBufferPtr digest)
-{
-  std::stringstream os;
-
-  CryptoPP::StringSource(digest->data(), digest->size(), true,
-                         new CryptoPP::HexEncoder(new CryptoPP::FileSink(os), false));
-  return os.str();
-}
-
 
 // public slots:
 void
diff --git a/src/chat-dialog-backend.hpp b/src/chat-dialog-backend.hpp
index 0c417c3..e0c8b0c 100644
--- a/src/chat-dialog-backend.hpp
+++ b/src/chat-dialog-backend.hpp
@@ -105,9 +105,6 @@
   void
   updatePrefixes();
 
-  std::string
-  getHexEncodedDigest(ndn::ConstBufferPtr digest);
-
 signals:
   void
   syncTreeUpdated(std::vector<chronochat::NodeInfo> updates, QString digest);
diff --git a/src/chatroom-discovery-backend.cpp b/src/chatroom-discovery-backend.cpp
index 3f92e01..8e2ad21 100644
--- a/src/chatroom-discovery-backend.cpp
+++ b/src/chatroom-discovery-backend.cpp
@@ -9,19 +9,15 @@
  */
 
 #include "chatroom-discovery-backend.hpp"
+
 #include <QStringList>
 
-#ifndef Q_MOC_RUN
-
-#endif
-
 namespace chronochat {
 
 static const time::milliseconds FRESHNESS_PERIOD(60000);
 static const time::seconds REFRESH_INTERVAL(60);
 static const time::seconds HELLO_INTERVAL(60);
-static const ndn::Name::Component ROUTING_HINT_SEPARATOR =
-  ndn::name::Component::fromEscapedString("%F0%2E");
+static const Name::Component ROUTING_HINT_SEPARATOR = Name::Component::fromEscapedString("%F0%2E");
 // a count enforced when a manager himself find another one publish chatroom data
 static const int MAXIMUM_COUNT = 3;
 static const int IDENTITY_OFFSET = -1;
@@ -93,8 +89,6 @@
     close();
 
   } while (shouldResume);
-
-  std::cerr << "DiscoveryBackend: Bye!" << std::endl;
 }
 
 void
diff --git a/src/contact-manager.cpp b/src/contact-manager.cpp
index 5a5f5bb..5a6b4b9 100644
--- a/src/contact-manager.cpp
+++ b/src/contact-manager.cpp
@@ -10,20 +10,24 @@
  */
 
 #include "contact-manager.hpp"
+
 #include <QStringList>
 #include <QFile>
 
 #ifndef Q_MOC_RUN
 #include <ndn-cxx/encoding/buffer-stream.hpp>
 #include <ndn-cxx/face.hpp>
+#include <ndn-cxx/security/signing-helpers.hpp>
+#include <ndn-cxx/security/transform/buffer-source.hpp>
+#include <ndn-cxx/security/transform/digest-filter.hpp>
+#include <ndn-cxx/security/transform/stream-sink.hpp>
 #include <ndn-cxx/security/validator.hpp>
 #include <ndn-cxx/security/validator-null.hpp>
-#include <ndn-cxx/security/signing-helpers.hpp>
 #include <ndn-cxx/security/verification-helpers.hpp>
-#include "cryptopp.hpp"
+
 #include <boost/asio.hpp>
-#include <boost/tokenizer.hpp>
 #include <boost/filesystem.hpp>
+#include <boost/tokenizer.hpp>
 #endif
 
 namespace fs = boost::filesystem;
@@ -82,10 +86,9 @@
 void
 ContactManager::fetchEndorseCertificateInternal(const Name& identity, size_t certIndex)
 {
-  shared_ptr<EndorseCollection> endorseCollection =
-    m_bufferedContacts[identity].m_endorseCollection;
+  auto endorseCollection = m_bufferedContacts[identity].m_endorseCollection;
 
-  if(certIndex >= endorseCollection->getCollectionEntries().size())
+  if (certIndex >= endorseCollection->getCollectionEntries().size())
     return prepareEndorseInfo(identity);
 
   Name interestName(endorseCollection->getCollectionEntries()[certIndex].certName);
@@ -114,15 +117,13 @@
   m_bufferedContacts[identity].m_endorseInfo = endorseInfo;
 
   map<string, size_t> endorseCount;
-  for (Profile::const_iterator pIt = profile.begin(); pIt != profile.end(); pIt++)
+  for (auto pIt = profile.begin(); pIt != profile.end(); pIt++)
     endorseCount[pIt->first] = 0;
 
   size_t endorseCertCount = 0;
 
-  vector<shared_ptr<EndorseCertificate> >::const_iterator cIt =
-    m_bufferedContacts[identity].m_endorseCertList.begin();
-  vector<shared_ptr<EndorseCertificate> >::const_iterator cEnd =
-    m_bufferedContacts[identity].m_endorseCertList.end();
+  auto cIt = m_bufferedContacts[identity].m_endorseCertList.cbegin();
+  auto cEnd = m_bufferedContacts[identity].m_endorseCertList.cend();
 
   for (; cIt != cEnd; cIt++, endorseCertCount++) {
     shared_ptr<Contact> contact = getContact((*cIt)->getSigner());
@@ -140,13 +141,13 @@
       continue;
 
     const Profile& tmpProfile = (*cIt)->getProfile();
-    const vector<string>& endorseList = (*cIt)->getEndorseList();
-    for (vector<string>::const_iterator eIt = endorseList.begin(); eIt != endorseList.end(); eIt++)
+    const auto& endorseList = (*cIt)->getEndorseList();
+    for (auto eIt = endorseList.begin(); eIt != endorseList.end(); eIt++)
       if (tmpProfile.get(*eIt) == profile.get(*eIt))
         endorseCount[*eIt] += 1;
   }
 
-  for (Profile::const_iterator pIt = profile.begin(); pIt != profile.end(); pIt++) {
+  for (auto pIt = profile.begin(); pIt != profile.end(); pIt++) {
     std::stringstream ss;
     ss << endorseCount[pIt->first] << "/" << endorseCertCount;
     endorseInfo->addEndorsement(pIt->first, pIt->second, ss.str());
@@ -232,23 +233,20 @@
 }
 
 void
-ContactManager::onEndorseCertificateInternal(const Interest& interest, const Data& data,
-                                             const Name& identity, size_t certIndex,
-                                             string hash)
+ContactManager::onEndorseCertificateInternal(const Interest&, const Data& data,
+                                             const Name& identity, size_t certIndex, string hash)
 {
-  std::stringstream ss;
+  std::ostringstream ss;
   {
-    using namespace CryptoPP;
-
-    SHA256 hash;
-    StringSource(data.wireEncode().wire(), data.wireEncode().size(), true,
-                 new HashFilter(hash, new FileSink(ss)));
+    using namespace ndn::security::transform;
+    bufferSource(data.wireEncode().wire(), data.wireEncode().size())
+        >> digestFilter(ndn::DigestAlgorithm::SHA256)
+        >> streamSink(ss);
   }
 
   if (ss.str() == hash) {
-    shared_ptr<EndorseCertificate> endorseCertificate =
-      make_shared<EndorseCertificate>(boost::cref(data));
-    m_bufferedContacts[identity].m_endorseCertList.push_back(endorseCertificate);
+    auto endorseCertificate = make_shared<EndorseCertificate>(data);
+    m_bufferedContacts[identity].m_endorseCertList.push_back(std::move(endorseCertificate));
   }
 
   fetchEndorseCertificateInternal(identity, certIndex+1);
@@ -269,7 +267,7 @@
     boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
     m_collectCount = m_contactList.size();
 
-    for (ContactList::iterator it  = m_contactList.begin(); it != m_contactList.end(); it++) {
+    for (auto it = m_contactList.begin(); it != m_contactList.end(); it++) {
       Name interestName = (*it)->getNameSpace();
       interestName.append("DNS").append(m_identity.wireEncode()).append("ENDORSEE");
 
@@ -384,8 +382,7 @@
     QStringList certNameList;
     QStringList nameList;
 
-    for(BufferedIdCerts::const_iterator it = m_bufferedIdCerts.begin();
-        it != m_bufferedIdCerts.end(); it++) {
+    for (auto it = m_bufferedIdCerts.begin(); it != m_bufferedIdCerts.end(); it++) {
       certNameList << QString::fromStdString(it->second->getName().toUri());
       Profile profile(*(it->second));
       nameList << QString::fromStdString(profile.get("name"));
@@ -402,7 +399,7 @@
   auto signCert = m_keyChain.getPib().getIdentity(m_identity)
                             .getDefaultKey().getDefaultCertificate();
   vector<string> endorseList;
-  for (Profile::const_iterator it = profile.begin(); it != profile.end(); it++)
+  for (auto it = profile.begin(); it != profile.end(); it++)
     endorseList.push_back(it->first);
 
   shared_ptr<EndorseCertificate> selfEndorseCertificate =
@@ -639,7 +636,7 @@
 {
   Name identityName(identity.toStdString());
 
-  BufferedContacts::const_iterator it = m_bufferedContacts.find(identityName);
+  auto it = m_bufferedContacts.find(identityName);
   if (it != m_bufferedContacts.end()) {
     Contact contact(*(it->second.m_selfEndorseCert));
 
@@ -750,8 +747,7 @@
   }
   m_bufferedIdCerts.clear();
 
-  for (vector<string>::const_iterator it = bufferedIdCertNames.begin();
-       it != bufferedIdCertNames.end(); it++) {
+  for (auto it = bufferedIdCertNames.begin(); it != bufferedIdCertNames.end(); it++) {
     Name certName(*it);
 
     Interest interest(certName);
@@ -785,7 +781,7 @@
   Name certName(qCertName.toStdString());
   Name identity = certName.getPrefix(-1);
 
-  BufferedIdCerts::const_iterator it = m_bufferedIdCerts.find(certName);
+  auto it = m_bufferedIdCerts.find(certName);
   if (it != m_bufferedIdCerts.end()) {
     Contact contact(*it->second);
     try {
@@ -811,7 +807,7 @@
 {
   QStringList aliasList;
   QStringList idList;
-  for (ContactList::const_iterator it = m_contactList.begin(); it != m_contactList.end(); it++) {
+  for (auto it = m_contactList.begin(); it != m_contactList.end(); it++) {
     aliasList << QString((*it)->getAlias().c_str());
     idList << QString((*it)->getNameSpace().toUri().c_str());
   }
@@ -823,7 +819,7 @@
 void
 ContactManager::onWaitForContactInfo(const QString& identity)
 {
-  for (ContactList::const_iterator it = m_contactList.begin(); it != m_contactList.end(); it++)
+  for (auto it = m_contactList.begin(); it != m_contactList.end(); it++)
     if ((*it)->getNameSpace().toUri() == identity.toStdString())
       emit contactInfoReady(QString((*it)->getNameSpace().toUri().c_str()),
                             QString((*it)->getName().c_str()),
diff --git a/src/contact-storage.cpp b/src/contact-storage.cpp
index 76ae31d..6703f41 100644
--- a/src/contact-storage.cpp
+++ b/src/contact-storage.cpp
@@ -10,7 +10,11 @@
  */
 
 #include "contact-storage.hpp"
-#include "cryptopp.hpp"
+
+#include <ndn-cxx/security/transform/buffer-source.hpp>
+#include <ndn-cxx/security/transform/digest-filter.hpp>
+#include <ndn-cxx/security/transform/hex-encode.hpp>
+#include <ndn-cxx/security/transform/stream-sink.hpp>
 
 #include <boost/filesystem.hpp>
 
@@ -184,13 +188,13 @@
 {
   string dbName("chronos-");
 
-  std::stringstream ss;
+  std::ostringstream ss;
   {
-    using namespace CryptoPP;
-
-    SHA256 hash;
-    StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
-                 new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
+    using namespace ndn::security::transform;
+    bufferSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size())
+        >> digestFilter(ndn::DigestAlgorithm::SHA256)
+        >> hexEncode(false)
+        >> streamSink(ss);
   }
   dbName.append(ss.str()).append(".db");
 
@@ -203,7 +207,7 @@
   sqlite3_stmt *stmt;
   sqlite3_prepare_v2(m_db,
                      "SELECT name FROM sqlite_master WHERE type='table' And name=?",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, tableName, SQLITE_TRANSIENT);
   int res = sqlite3_step(stmt);
 
@@ -213,9 +217,9 @@
   sqlite3_finalize(stmt);
 
   if (!tableExist) {
-    char *errmsg = 0;
+    char *errmsg = nullptr;
     res = sqlite3_exec(m_db, sqlCreateStmt.c_str (), nullptr, nullptr, &errmsg);
-    if (res != SQLITE_OK && errmsg != 0)
+    if (res != SQLITE_OK && errmsg != nullptr)
       NDN_THROW(Error("Init \"error\" in " + tableName));
   }
 }
@@ -225,7 +229,8 @@
 {
   shared_ptr<Profile> profile = make_shared<Profile>(m_identity);
   sqlite3_stmt *stmt;
-  sqlite3_prepare_v2(m_db, "SELECT profile_type, profile_value FROM SelfProfile", -1, &stmt, 0);
+  sqlite3_prepare_v2(m_db, "SELECT profile_type, profile_value FROM SelfProfile",
+                     -1, &stmt, nullptr);
 
   while (sqlite3_step(stmt) == SQLITE_ROW) {
     string profileType = sqlite3_column_string(stmt, 0);
@@ -243,7 +248,7 @@
   sqlite3_stmt *stmt;
   sqlite3_prepare_v2(m_db,
                      "INSERT OR REPLACE INTO SelfEndorse (identity, endorse_data) values (?, ?)",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, m_identity.toUri(), SQLITE_TRANSIENT);
   sqlite3_bind_block(stmt, 2, newEndorseCertificate.wireEncode(), SQLITE_TRANSIENT);
   sqlite3_step(stmt);
@@ -259,7 +264,7 @@
   sqlite3_stmt *stmt;
   sqlite3_prepare_v2(m_db,
                      "SELECT endorse_data FROM SelfEndorse where identity=?",
-                      -1, &stmt, 0);
+                      -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, m_identity.toUri(), SQLITE_TRANSIENT);
 
   if (sqlite3_step(stmt) == SQLITE_ROW) {
@@ -280,7 +285,7 @@
   sqlite3_prepare_v2(m_db,
                      "INSERT OR REPLACE INTO ProfileEndorse \
                       (identity, endorse_data) values (?, ?)",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
   sqlite3_bind_block(stmt, 2, endorseCertificate.wireEncode(), SQLITE_TRANSIENT);
   sqlite3_step(stmt);
@@ -299,7 +304,7 @@
                      "INSERT OR REPLACE INTO CollectEndorse \
                       (endorser, endorse_name, endorse_data) \
                       VALUES (?, ?, ?)",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, endorserName.toUri(), SQLITE_TRANSIENT);
   sqlite3_bind_string(stmt, 2, certName.toUri(), SQLITE_TRANSIENT);
   sqlite3_bind_block(stmt, 3, endorseCertificate.wireEncode(), SQLITE_TRANSIENT);
@@ -312,17 +317,17 @@
 ContactStorage::getCollectEndorse(EndorseCollection& endorseCollection)
 {
   sqlite3_stmt *stmt;
-  sqlite3_prepare_v2(m_db, "SELECT endorse_name, endorse_data FROM CollectEndorse", -1, &stmt, 0);
+  sqlite3_prepare_v2(m_db, "SELECT endorse_name, endorse_data FROM CollectEndorse",
+                     -1, &stmt, nullptr);
 
   while (sqlite3_step(stmt) == SQLITE_ROW) {
     string certName = sqlite3_column_string(stmt, 0);
-    std::stringstream ss;
+    std::ostringstream ss;
     {
-      using namespace CryptoPP;
-      SHA256 hash;
-
-      StringSource(sqlite3_column_text(stmt, 1), sqlite3_column_bytes (stmt, 1), true,
-                   new HashFilter(hash, new FileSink(ss)));
+      using namespace ndn::security::transform;
+      bufferSource(sqlite3_column_text(stmt, 1), sqlite3_column_bytes(stmt, 1))
+          >> digestFilter(ndn::DigestAlgorithm::SHA256)
+          >> streamSink(ss);
     }
     endorseCollection.addCollectionEntry(Name(certName), ss.str());
   }
@@ -338,7 +343,7 @@
   sqlite3_stmt *stmt;
   sqlite3_prepare_v2(m_db,
                      "SELECT endorse_name, endorse_data FROM CollectEndorse where endorse_name=?",
-                      -1, &stmt, 0);
+                      -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, name.toUri(), SQLITE_TRANSIENT);
 
   if (sqlite3_step(stmt) == SQLITE_ROW) {
@@ -358,7 +363,7 @@
   sqlite3_prepare_v2(m_db,
                      "SELECT profile_type FROM ContactProfile \
                       WHERE profile_identity=? AND endorse=1 ORDER BY profile_type",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
 
   while (sqlite3_step(stmt) == SQLITE_ROW) {
@@ -375,17 +380,17 @@
   string identity = identityName.toUri();
 
   sqlite3_stmt *stmt;
-  sqlite3_prepare_v2(m_db, "DELETE FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
+  sqlite3_prepare_v2(m_db, "DELETE FROM Contact WHERE contact_namespace=?", -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
   sqlite3_step(stmt);
   sqlite3_finalize(stmt);
 
-  sqlite3_prepare_v2(m_db, "DELETE FROM ContactProfile WHERE profile_identity=?", -1, &stmt, 0);
+  sqlite3_prepare_v2(m_db, "DELETE FROM ContactProfile WHERE profile_identity=?", -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
   sqlite3_step(stmt);
   sqlite3_finalize(stmt);
 
-  sqlite3_prepare_v2(m_db, "DELETE FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
+  sqlite3_prepare_v2(m_db, "DELETE FROM TrustScope WHERE contact_namespace=?", -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
   sqlite3_step(stmt);
   sqlite3_finalize(stmt);
@@ -405,7 +410,7 @@
                      "INSERT INTO Contact (contact_namespace, contact_alias, contact_keyName, \
                       contact_key, notBefore, notAfter, is_introducer) \
                       values (?, ?, ?, ?, ?, ?, ?)",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
 
   sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
   sqlite3_bind_string(stmt, 2, contact.getAlias(), SQLITE_TRANSIENT);
@@ -422,12 +427,12 @@
   sqlite3_finalize(stmt);
 
   const Profile& profile = contact.getProfile();
-  for (Profile::const_iterator it = profile.begin(); it != profile.end(); it++) {
+  for (auto it = profile.begin(); it != profile.end(); it++) {
     sqlite3_prepare_v2(m_db,
                        "INSERT INTO ContactProfile \
                         (profile_identity, profile_type, profile_value, endorse) \
                         values (?, ?, ?, 0)",
-                       -1, &stmt, 0);
+                       -1, &stmt, nullptr);
     sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
     sqlite3_bind_string(stmt, 2, it->first, SQLITE_TRANSIENT);
     sqlite3_bind_string(stmt, 3, it->second, SQLITE_TRANSIENT);
@@ -436,13 +441,13 @@
   }
 
   if (isIntroducer) {
-    Contact::const_iterator it  = contact.trustScopeBegin();
-    Contact::const_iterator end = contact.trustScopeEnd();
+    auto it  = contact.trustScopeBegin();
+    auto end = contact.trustScopeEnd();
 
     while (it != end) {
       sqlite3_prepare_v2(m_db,
                          "INSERT INTO TrustScope (contact_namespace, trust_scope) values (?, ?)",
-                         -1, &stmt, 0);
+                         -1, &stmt, nullptr);
       sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
       sqlite3_bind_string(stmt, 2, it->first.toUri(), SQLITE_TRANSIENT);
       sqlite3_step(stmt);
@@ -463,7 +468,7 @@
   sqlite3_prepare_v2(m_db,
                      "SELECT contact_alias, contact_keyName, contact_key, notBefore, notAfter, \
                       is_introducer FROM Contact where contact_namespace=?",
-                      -1, &stmt, 0);
+                      -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
 
   if (sqlite3_step(stmt) == SQLITE_ROW) {
@@ -487,7 +492,7 @@
   sqlite3_prepare_v2(m_db,
                      "SELECT profile_type, profile_value FROM ContactProfile \
                       where profile_identity=?",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
 
   while (sqlite3_step(stmt) == SQLITE_ROW) {
@@ -501,7 +506,7 @@
   if (contact->isIntroducer()) {
     sqlite3_prepare_v2(m_db,
                        "SELECT trust_scope FROM TrustScope WHERE contact_namespace=?",
-                       -1, &stmt, 0);
+                       -1, &stmt, nullptr);
     sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
 
     while (sqlite3_step(stmt) == SQLITE_ROW) {
@@ -520,7 +525,7 @@
 {
   sqlite3_stmt *stmt;
   sqlite3_prepare_v2(m_db, "UPDATE Contact SET is_introducer=? WHERE contact_namespace=?",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_int(stmt, 1, (isIntroducer ? 1 : 0));
   sqlite3_bind_string(stmt, 2, identity.toUri(), SQLITE_TRANSIENT);
   sqlite3_step(stmt);
@@ -533,7 +538,7 @@
 {
   sqlite3_stmt *stmt;
   sqlite3_prepare_v2(m_db, "UPDATE Contact SET contact_alias=? WHERE contact_namespace=?",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, alias, SQLITE_TRANSIENT);
   sqlite3_bind_string(stmt, 2, identity.toUri(), SQLITE_TRANSIENT);
   sqlite3_step(stmt);
@@ -547,13 +552,14 @@
   bool result = false;
 
   sqlite3_stmt *stmt;
-  sqlite3_prepare_v2(m_db, "SELECT count(*) FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
+  sqlite3_prepare_v2(m_db, "SELECT count(*) FROM Contact WHERE contact_namespace=?",
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, name.toUri(), SQLITE_TRANSIENT);
 
   int res = sqlite3_step(stmt);
 
   if (res == SQLITE_ROW) {
-    int countAll = sqlite3_column_int (stmt, 0);
+    int countAll = sqlite3_column_int(stmt, 0);
     if (countAll > 0)
       result = true;
   }
@@ -568,7 +574,7 @@
   vector<Name> contactNames;
 
   sqlite3_stmt *stmt;
-  sqlite3_prepare_v2(m_db, "SELECT contact_namespace FROM Contact", -1, &stmt, 0);
+  sqlite3_prepare_v2(m_db, "SELECT contact_namespace FROM Contact", -1, &stmt, nullptr);
 
   while (sqlite3_step(stmt) == SQLITE_ROW) {
     string identity = sqlite3_column_string(stmt, 0);
@@ -576,7 +582,7 @@
   }
   sqlite3_finalize(stmt);
 
-  for (vector<Name>::iterator it = contactNames.begin(); it != contactNames.end(); it++) {
+  for (auto it = contactNames.begin(); it != contactNames.end(); it++) {
     shared_ptr<Contact> contact = getContact(*it);
     if (static_cast<bool>(contact))
       contacts.push_back(contact);
@@ -591,7 +597,7 @@
   sqlite3_prepare_v2(m_db,
                      "INSERT OR REPLACE INTO DnsData (dns_name, dns_type, dns_value, data_name) \
                       VALUES (?, ?, ?, ?)",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, name, SQLITE_TRANSIENT);
   sqlite3_bind_string(stmt, 2, type, SQLITE_TRANSIENT);
   sqlite3_bind_block(stmt, 3, data, SQLITE_TRANSIENT);
@@ -607,7 +613,7 @@
   shared_ptr<Data> data;
 
   sqlite3_stmt *stmt;
-  sqlite3_prepare_v2(m_db, "SELECT dns_value FROM DnsData where data_name=?", -1, &stmt, 0);
+  sqlite3_prepare_v2(m_db, "SELECT dns_value FROM DnsData where data_name=?", -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, dataName.toUri(), SQLITE_TRANSIENT);
 
   if (sqlite3_step(stmt) == SQLITE_ROW) {
@@ -626,7 +632,7 @@
 
   sqlite3_stmt *stmt;
   sqlite3_prepare_v2(m_db, "SELECT dns_value FROM DnsData where dns_name=? and dns_type=?",
-                     -1, &stmt, 0);
+                     -1, &stmt, nullptr);
   sqlite3_bind_string(stmt, 1, name, SQLITE_TRANSIENT);
   sqlite3_bind_string(stmt, 2, type, SQLITE_TRANSIENT);
 
diff --git a/src/controller.cpp b/src/controller.cpp
index b8b2c97..9e794b9 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -10,7 +10,6 @@
  */
 
 #include "controller.hpp"
-#include "cryptopp.hpp"
 #include "conf.hpp"
 #include "endorse-info.hpp"
 
@@ -19,9 +18,14 @@
 #include <QDir>
 #include <QTimer>
 
-#include <boost/filesystem.hpp>
+#include <ndn-cxx/security/transform/buffer-source.hpp>
+#include <ndn-cxx/security/transform/digest-filter.hpp>
+#include <ndn-cxx/security/transform/hex-encode.hpp>
+#include <ndn-cxx/security/transform/stream-sink.hpp>
 #include <ndn-cxx/util/random.hpp>
 
+#include <boost/filesystem.hpp>
+
 Q_DECLARE_METATYPE(ndn::Name)
 Q_DECLARE_METATYPE(ndn::security::Certificate)
 Q_DECLARE_METATYPE(chronochat::EndorseInfo)
@@ -247,7 +251,19 @@
   saveConf();
 }
 
-// public methods
+static string
+getRandomString()
+{
+  uint32_t r = ndn::random::generateWord32();
+  std::ostringstream ss;
+  {
+    using namespace ndn::security::transform;
+    bufferSource(reinterpret_cast<const uint8_t*>(&r), sizeof(r))
+        >> hexEncode(false)
+        >> streamSink(ss);
+  }
+  return ss.str();
+}
 
 
 // private methods
@@ -256,13 +272,13 @@
 {
   string dbName("chronos-");
 
-  std::stringstream ss;
+  std::ostringstream ss;
   {
-    using namespace CryptoPP;
-
-    SHA256 hash;
-    StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
-                 new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
+    using namespace ndn::security::transform;
+    bufferSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size())
+        >> digestFilter(ndn::DigestAlgorithm::SHA256)
+        >> hexEncode(false)
+        >> streamSink(ss);
   }
   dbName.append(ss.str()).append(".db");
 
@@ -429,8 +445,8 @@
   menu->addAction(m_addContactAction);
   menu->addSeparator();
   {
-    ChatActionList::const_iterator it = m_chatActionList.begin();
-    ChatActionList::const_iterator end = m_chatActionList.end();
+    auto it = m_chatActionList.begin();
+    auto end = m_chatActionList.end();
     if (it != end) {
       for (; it != end; it++)
         menu->addAction(it->second);
@@ -442,8 +458,8 @@
   menu->addAction(m_minimizeAction);
   m_closeMenu = menu->addMenu("Close chatroom");
   {
-    ChatActionList::const_iterator it = m_closeActionList.begin();
-    ChatActionList::const_iterator end = m_closeActionList.end();
+    auto it = m_closeActionList.begin();
+    auto end = m_closeActionList.end();
     if (it == end)
       m_closeMenu->setEnabled(false);
     else
@@ -454,30 +470,6 @@
   menu->addAction(m_quitAction);
 }
 
-string
-Controller::getRandomString()
-{
-  uint32_t r = ndn::random::generateWord32();
-  std::stringstream ss;
-  {
-    using namespace CryptoPP;
-    StringSource(reinterpret_cast<uint8_t*>(&r), 4, true,
-                 new HexEncoder(new FileSink(ss), false));
-
-  }
-  // for (int i = 0; i < 8; i++)
-  //   {
-  //     uint32_t t = r & mask;
-  //     if (t < 10)
-  //       ss << static_cast<char>(t + 0x30);
-  //     else
-  //       ss << static_cast<char>(t + 0x57);
-  //     r = r >> 4;
-  //   }
-
-  return ss.str();
-}
-
 void
 Controller::addChatDialog(const QString& chatroomName, ChatDialog* chatDialog)
 {
@@ -529,7 +521,7 @@
 Controller::onIdentityUpdated(const QString& identity)
 {
   while (!m_chatDialogList.empty()) {
-    ChatDialogList::const_iterator it = m_chatDialogList.begin();
+    auto it = m_chatDialogList.begin();
     it->second->shutdown();
   }
 
@@ -646,8 +638,8 @@
   m_addContactPanel->hide();
   m_discoveryPanel->hide();
 
-  ChatDialogList::iterator it = m_chatDialogList.begin();
-  ChatDialogList::iterator end = m_chatDialogList.end();
+  auto it = m_chatDialogList.begin();
+  auto end = m_chatDialogList.end();
   for (; it != end; it++)
     it->second->hide();
 }
@@ -656,7 +648,7 @@
 Controller::onQuitAction()
 {
   while (!m_chatDialogList.empty()) {
-    ChatDialogList::const_iterator it = m_chatDialogList.begin();
+    auto it = m_chatDialogList.begin();
     it->second->shutdown();
   }
 
@@ -732,8 +724,7 @@
   QString chatroomName = QString::fromStdString(invitation.getChatroom());
   onStartChatroom(chatroomName, secured);
 
-  ChatDialogList::iterator it = m_chatDialogList.find(chatroomName.toStdString());
-
+  auto it = m_chatDialogList.find(chatroomName.toStdString());
   BOOST_ASSERT(it != m_chatDialogList.end());
   it->second->addSyncAnchor(invitation);
 }
@@ -759,7 +750,7 @@
 {
   emit removeChatroom(chatroomName);
 
-  ChatDialogList::iterator it = m_chatDialogList.find(chatroomName.toStdString());
+  auto it = m_chatDialogList.find(chatroomName.toStdString());
   if (it != m_chatDialogList.end()) {
     ChatDialog* deletedChat = it->second;
     if (deletedChat)
diff --git a/src/controller.hpp b/src/controller.hpp
index ca92c82..d0635bb 100644
--- a/src/controller.hpp
+++ b/src/controller.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
 /*
- * Copyright (c) 2013, Regents of the University of California
+ * Copyright (c) 2020, Regents of the University of California
  *                     Yingdi Yu
  *
  * BSD license, See the LICENSE file for more information
@@ -73,9 +73,6 @@
   void
   updateMenu();
 
-  std::string
-  getRandomString();
-
   void
   addChatDialog(const QString& chatroomName, ChatDialog* chatDialog);
 
diff --git a/src/cryptopp.hpp b/src/cryptopp.hpp
deleted file mode 100644
index 01fbfc2..0000000
--- a/src/cryptopp.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- 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 CHRONOCHAT_CRYPTOPP_HPP
-#define CHRONOCHAT_CRYPTOPP_HPP
-
-// suppress CryptoPP warnings
-#pragma GCC system_header
-#pragma clang system_header
-
-#include <cryptopp/hex.h>
-#include <cryptopp/files.h>
-#include <cryptopp/base64.h>
-#include <cryptopp/sha.h>
-#include <cryptopp/filters.h>
-
-#endif // CHRONOCHAT_CRYPTOPP_HPP
diff --git a/src/invitation.cpp b/src/invitation.cpp
index 9af3c4d..8ca4b06 100644
--- a/src/invitation.cpp
+++ b/src/invitation.cpp
@@ -10,12 +10,9 @@
 
 #include "invitation.hpp"
 
-#include <ndn-cxx/security/signature-sha256-with-rsa.hpp>
-
 namespace chronochat {
 
 using std::string;
-
 using ndn::security::Certificate;
 
 const size_t  Invitation::NAME_SIZE_MIN         = 7;
diff --git a/src/main.cpp b/src/main.cpp
index 039fa42..a9b4c38 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -11,40 +11,33 @@
 #include "controller.hpp"
 
 #include <QApplication>
-#include <QTextCodec>
 
+#include <boost/exception/diagnostic_information.hpp>
 #include <iostream>
-#include <ndn-cxx/face.hpp>
-#include <boost/thread/thread.hpp>
 
-class NewApp : public QApplication
+class ChronoChatApp : public QApplication
 {
 public:
-  NewApp(int& argc, char** argv)
-    : QApplication(argc, argv)
-  {
-  }
+  using QApplication::QApplication;
 
   bool
-  notify(QObject* receiver, QEvent* event)
+  notify(QObject* receiver, QEvent* event) final
   {
     try {
       return QApplication::notify(receiver, event);
     }
     catch (const std::exception& e) {
-      std::cerr << "Exception thrown:" << e.what() << std::endl;
+      std::cerr << boost::diagnostic_information(e) << std::endl;
       return false;
     }
-
   }
 };
 
-int main(int argc, char *argv[])
+int
+main(int argc, char *argv[])
 {
-  NewApp app(argc, argv);
-
+  ChronoChatApp app(argc, argv);
   chronochat::Controller controller;
-
   app.setQuitOnLastWindowClosed(false);
 
   return app.exec();
diff --git a/test/contact-storage.t.cpp b/test/contact-storage.t.cpp
index a9265e6..c554a58 100644
--- a/test/contact-storage.t.cpp
+++ b/test/contact-storage.t.cpp
@@ -6,7 +6,6 @@
  */
 
 #include "contact-storage.hpp"
-#include "cryptopp.hpp"
 
 #include <boost/test/unit_test.hpp>
 #include <boost/filesystem.hpp>
@@ -14,12 +13,11 @@
 namespace chronochat {
 namespace tests {
 
-using std::string;
 namespace fs = boost::filesystem;
 
 BOOST_AUTO_TEST_SUITE(TestContactStorage)
 
-const string dbName("chronos-20e9530008b27c661ad3429d1956fa1c509b652dce9273bfe81b7c91819c272c.db");
+const std::string dbName("chronos-20e9530008b27c661ad3429d1956fa1c509b652dce9273bfe81b7c91819c272c.db");
 
 BOOST_AUTO_TEST_CASE(InitializeTable)
 {
diff --git a/test/endorse-certificate.t.cpp b/test/endorse-certificate.t.cpp
index 6fef721..416972f 100644
--- a/test/endorse-certificate.t.cpp
+++ b/test/endorse-certificate.t.cpp
@@ -6,13 +6,15 @@
  */
 
 #include "endorse-certificate.hpp"
-#include "cryptopp.hpp"
 
 #include <boost/test/unit_test.hpp>
 #include <boost/filesystem.hpp>
 
-#include <ndn-cxx/security/key-chain.hpp>
 #include <ndn-cxx/encoding/buffer-stream.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/security/transform/base64-decode.hpp>
+#include <ndn-cxx/security/transform/buffer-source.hpp>
+#include <ndn-cxx/security/transform/stream-sink.hpp>
 #include <ndn-cxx/util/time.hpp>
 #include <ndn-cxx/util/io.hpp>
 
@@ -27,8 +29,9 @@
 
 BOOST_AUTO_TEST_SUITE(TestEndorseCertificate)
 
-std::string
-getTestFile(std::string path) {
+static std::string
+getTestFile(std::string path)
+{
   std::ifstream t(path);
   std::stringstream buffer;
   buffer << t.rdbuf();
@@ -83,8 +86,8 @@
   const std::string testIdKey = getTestFile("test/cert/testid.key");
   ndn::OBufferStream keyOs;
   {
-    using namespace CryptoPP;
-    StringSource(testIdKey, true, new Base64Decoder(new FileSink(keyOs)));
+    using namespace ndn::security::transform;
+    bufferSource(testIdKey) >> base64Decode() >> streamSink(keyOs);
   }
   BOOST_CHECK(idCert->getPublicKey() == *keyOs.buf());
 }
diff --git a/wscript b/wscript
index ca889e9..a2f88e4 100644
--- a/wscript
+++ b/wscript
@@ -1,39 +1,39 @@
 # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-VERSION='0.5'
-APPNAME='ChronoChat'
 
-from waflib import Configure, Utils, Logs, Context
+from waflib import Context, Logs, Utils
 import os
 
+VERSION = '0.5'
+APPNAME = 'ChronoChat'
+
 def options(opt):
+    opt.load(['compiler_cxx', 'gnu_dirs'])
+    opt.load(['default-compiler-flags',
+              'boost', 'qt5_custom',
+              'doxygen', 'sphinx_build'],
+             tooldir=['.waf-tools'])
 
-    opt.load(['compiler_c', 'compiler_cxx', 'gnu_dirs'])
-
-    opt.load(['default-compiler-flags', 'boost',
-              'doxygen', 'sphinx_build', 'qt5_custom', 'cryptopp'],
-              tooldir=['.waf-tools'])
-
-    opt = opt.add_option_group('ChronoChat Options')
-
-    opt.add_option('--with-tests', action='store_true', default=False, dest='with_tests',
-                   help='''build unit tests''')
+    optgrp = opt.add_option_group('ChronoChat Options')
+    optgrp.add_option('--with-tests', action='store_true', default=False,
+                      help='Build unit tests')
 
 def configure(conf):
-    conf.load(['compiler_c', 'compiler_cxx', 'qt5_custom',
-               'default-compiler-flags', 'boost', 'gnu_dirs',
-               'doxygen', 'sphinx_build', 'cryptopp'])
+    conf.load(['compiler_cxx', 'gnu_dirs',
+               'default-compiler-flags', 'boost', 'qt5_custom',
+               'doxygen', 'sphinx_build'])
 
-    conf.check_cfg(package='libndn-cxx', args=['--cflags', '--libs'],
-                   uselib_store='NDN_CXX', mandatory=True)
+    conf.env.WITH_TESTS = conf.options.with_tests
 
-    conf.check_cfg (package='ChronoSync', args=['ChronoSync >= 0.5', '--cflags', '--libs'],
-                    uselib_store='SYNC', mandatory=True)
+    pkg_config_path = os.environ.get('PKG_CONFIG_PATH', '%s/pkgconfig' % conf.env.LIBDIR)
+    conf.check_cfg(package='libndn-cxx', args=['--cflags', '--libs'], uselib_store='NDN_CXX',
+                   pkg_config_path=pkg_config_path)
+    conf.check_cfg(package='ChronoSync', args=['--cflags', '--libs'], uselib_store='SYNC',
+                   pkg_config_path=pkg_config_path)
 
-    boost_libs = 'system random thread filesystem'
-    if conf.options.with_tests:
-        conf.env['WITH_TESTS'] = 1
-        conf.define('WITH_TESTS', 1);
-        boost_libs += ' unit_test_framework'
+    boost_libs = ['system', 'random', 'thread', 'filesystem']
+    if conf.env.WITH_TESTS:
+        boost_libs.append('unit_test_framework')
+        conf.define('WITH_TESTS', 1)
 
     conf.check_boost(lib=boost_libs, mt=True)
     if conf.env.BOOST_VERSION_NUMBER < 105800:
@@ -45,29 +45,28 @@
                   'If you encounter any problems, please upgrade your distribution or manually install a newer version of Boost.\n'
                   'For more information, see https://redmine.named-data.net/projects/nfd/wiki/Boost')
 
-    conf.check_cryptopp()
     conf.check_compiler_flags()
     conf.write_config_header('src/config.h')
 
 def build (bld):
     feature_list = 'qt5 cxx'
-    if bld.env["WITH_TESTS"]:
+    if bld.env.WITH_TESTS:
         feature_list += ' cxxstlib'
     else:
         feature_list += ' cxxprogram'
 
-    qt = bld (
+    qt = bld(
         target = "ChronoChat",
         features = feature_list,
         defines = "WAF=1",
         source = bld.path.ant_glob(['src/*.cpp', 'src/*.ui', '*.qrc']),
         includes = "src .",
-        use = "QT5CORE QT5GUI QT5WIDGETS QT5SQL NDN_CXX BOOST SYNC CRYPTOPP",
+        use = "QT5CORE QT5GUI QT5WIDGETS QT5SQL NDN_CXX BOOST SYNC",
         )
 
     # Unit tests
-    if bld.env["WITH_TESTS"]:
-      unittests = bld.program (
+    if bld.env.WITH_TESTS:
+      unittests = bld.program(
           target="unit-tests",
           source = bld.path.ant_glob(['test/**/*.cpp']),
           features=['cxx', 'cxxprogram'],
@@ -87,7 +86,7 @@
                 install_path = None,
             )
 
-    if not bld.env["WITH_TESTS"]:
+    if not bld.env.WITH_TESTS:
         if Utils.unversioned_sys_platform () == "darwin":
             app_plist = '''<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
@@ -130,8 +129,6 @@
             bld.install_files("${DATAROOTDIR}/chronochat",
                               bld.path.ant_glob(['linux/Resources/*']))
 
-
-# docs
 def docs(bld):
     from waflib import Options
     Options.commands = ['doxygen', 'sphinx'] + Options.commands