security: Add configuration based validator

configuration file format can be found at: http://redmine.named-data.net/projects/ndn-cpp-dev/wiki/CommandValidatorConf

Change-Id: Icc2725f349aed7513f35f2cccdcd4463fadeef31
diff --git a/src/security/conf/checker.hpp b/src/security/conf/checker.hpp
new file mode 100644
index 0000000..1ec2323
--- /dev/null
+++ b/src/security/conf/checker.hpp
@@ -0,0 +1,481 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_SECURITY_CONF_CHECKER_HPP
+#define NDN_SECURITY_CONF_CHECKER_HPP
+
+#include "key-locator-checker.hpp"
+#include "../../util/io.hpp"
+#include <boost/algorithm/string.hpp>
+
+#include "common.hpp"
+
+namespace ndn {
+namespace security {
+namespace conf {
+
+class Checker
+{
+public:
+  typedef function<void(const shared_ptr<const Interest>&)> OnInterestChecked;
+  typedef function<void(const shared_ptr<const Interest>&, const std::string&)> OnInterestCheckFailed;
+  typedef function<void(const shared_ptr<const Data>&)> OnDataChecked;
+  typedef function<void(const shared_ptr<const Data>&, const std::string&)> OnDataCheckFailed;
+
+
+  virtual
+  ~Checker()
+  {
+  }
+
+  /**
+   * @brief check if data satisfies condition defined in the specific checker implementation
+   *
+   * @param data Data packet
+   * @param onValidated Callback function which is called when data is immediately valid
+   * @param onValidationFailed Call function which is called when data is immediately invalid
+   * @return -1 if data is immediately invalid (onValidationFailed has been called)
+   *          1 if data is immediately valid (onValidated has been called)
+   *          0 if further signature verification is needed.
+   */
+  virtual int8_t
+  check(const Data& data,
+        const OnDataChecked& onValidated,
+        const OnDataCheckFailed& onValidationFailed) = 0;
+
+  /**
+   * @brief check if interest satisfies condition defined in the specific checker implementation
+   *
+   * @param interest Interest packet
+   * @param onValidated Callback function which is called when interest is immediately valid
+   * @param onValidationFailed Call function which is called when interest is immediately invalid
+   * @return -1 if interest is immediately invalid (onValidationFailed has been called)
+   *          1 if interest is immediately valid (onValidated has been called)
+   *          0 if further signature verification is needed.
+   */
+  virtual int8_t
+  check(const Interest& interest,
+        const OnInterestChecked& onValidated,
+        const OnInterestCheckFailed& onValidationFailed) = 0;
+};
+
+class CustomizedChecker : public Checker
+{
+  enum
+    {
+      INTEREST_SIG_VALUE = -1,
+      INTEREST_SIG_INFO = -2,
+    };
+
+public:
+  CustomizedChecker(uint32_t sigType,
+                    shared_ptr<KeyLocatorChecker> keyLocatorChecker)
+    : m_sigType(sigType)
+    , m_keyLocatorChecker(keyLocatorChecker)
+  {
+    if (m_sigType == Signature::Sha256WithRsa && !static_cast<bool>(m_keyLocatorChecker))
+      throw Error("Strong signature requires KeyLocatorChecker");
+  }
+
+  virtual int8_t
+  check(const Data& data,
+        const OnDataChecked& onValidated,
+        const OnDataCheckFailed& onValidationFailed)
+  {
+    return check(data, data.getSignature(), onValidated, onValidationFailed);
+  }
+
+  virtual int8_t
+  check(const Interest& interest,
+        const OnInterestChecked& onValidated,
+        const OnInterestCheckFailed& onValidationFailed)
+  {
+    const Name& interestName = interest.getName();
+    Signature signature(interestName[INTEREST_SIG_INFO].blockFromValue(),
+                        interestName[INTEREST_SIG_VALUE].blockFromValue());
+    return check(interest, signature, onValidated, onValidationFailed);
+  }
+
+private:
+  template<class Packet, class OnValidated, class OnFailed>
+  int8_t
+  check(const Packet& packet, const Signature& signature,
+        const OnValidated& onValidated,
+        const OnFailed& onValidationFailed)
+  {
+    if (m_sigType != signature.getType())
+      {
+        onValidationFailed(packet.shared_from_this(),
+                           "Signature type does not match: " +
+                           boost::lexical_cast<std::string>(m_sigType) +
+                           "!=" +
+                           boost::lexical_cast<std::string>(signature.getType()));
+        return -1;
+      }
+
+    switch (signature.getType())
+      {
+      case Signature::Sha256WithRsa:
+        {
+          try
+            {
+              SignatureSha256WithRsa sig(signature);
+
+              std::string failInfo;
+              if (m_keyLocatorChecker->check(packet, sig.getKeyLocator(), failInfo))
+                return 0;
+              else
+                {
+                  onValidationFailed(packet.shared_from_this(), failInfo);
+                  return -1;
+                }
+            }
+          catch (const SignatureSha256WithRsa::Error& e)
+            {
+              onValidationFailed(packet.shared_from_this(),
+                                 "Cannot decode Sha256WithRsa signature!");
+              return -1;
+            }
+        }
+      case Signature::Sha256:
+        return 0;
+      default:
+        {
+          onValidationFailed(packet.shared_from_this(),
+                             "Unsupported signature type: " +
+                             boost::lexical_cast<std::string>(signature.getType()));
+          return -1;
+        }
+      }
+  }
+
+private:
+  uint32_t m_sigType;
+  shared_ptr<KeyLocatorChecker> m_keyLocatorChecker;
+};
+
+class HierarchicalChecker : public CustomizedChecker
+{
+public:
+  HierarchicalChecker(uint32_t sigType)
+    : CustomizedChecker(sigType,
+        make_shared<HyperKeyLocatorNameChecker>("^(<>*)$", "\\1",
+                                                "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
+                                                "\\1\\2",
+                                                KeyLocatorChecker::RELATION_IS_PREFIX_OF))
+  {
+  }
+};
+
+class FixedSignerChecker : public Checker
+{
+  enum
+    {
+      INTEREST_SIG_VALUE = -1,
+      INTEREST_SIG_INFO = -2,
+    };
+public:
+  FixedSignerChecker(uint32_t sigType,
+                     const std::vector<shared_ptr<IdentityCertificate> >& signers)
+    : m_sigType(sigType)
+  {
+    for (std::vector<shared_ptr<IdentityCertificate> >::const_iterator it = signers.begin();
+         it != signers.end(); it++)
+      m_signers[(*it)->getName().getPrefix(-1)] = (*it);
+  }
+
+  virtual int8_t
+  check(const Data& data,
+        const OnDataChecked& onValidated,
+        const OnDataCheckFailed& onValidationFailed)
+  {
+    return check(data, data.getSignature(), onValidated, onValidationFailed);
+  }
+
+  virtual int8_t
+  check(const Interest& interest,
+        const OnInterestChecked& onValidated,
+        const OnInterestCheckFailed& onValidationFailed)
+  {
+    const Name& interestName = interest.getName();
+    Signature signature(interestName[INTEREST_SIG_INFO].blockFromValue(),
+                        interestName[INTEREST_SIG_VALUE].blockFromValue());
+    return check(interest, signature, onValidated, onValidationFailed);
+  }
+
+private:
+  template<class Packet, class OnValidated, class OnFailed>
+  int8_t
+  check(const Packet& packet, const Signature& signature,
+        const OnValidated& onValidated,
+        const OnFailed& onValidationFailed)
+  {
+    if (m_sigType != signature.getType())
+      {
+        onValidationFailed(packet.shared_from_this(),
+                           "Signature type does not match: "
+                           + boost::lexical_cast<std::string>(m_sigType)
+                           + "!="
+                           + boost::lexical_cast<std::string>(signature.getType()));
+        return -1;
+      }
+
+    switch(signature.getType())
+      {
+      case Signature::Sha256WithRsa:
+        {
+          try
+            {
+              SignatureSha256WithRsa sig(signature);
+
+              const Name& keyLocatorName = sig.getKeyLocator().getName();
+              if (m_signers.find(keyLocatorName) == m_signers.end())
+                {
+                  onValidationFailed(packet.shared_from_this(),
+                                     "Signer is not in the fixed signer list: "
+                                     + keyLocatorName.toUri());
+                  return -1;
+                }
+
+              if (Validator::verifySignature(packet, sig,
+                                             m_signers[keyLocatorName]->getPublicKeyInfo()))
+                {
+                  onValidated(packet.shared_from_this());
+                  return 1;
+                }
+              else
+                {
+                  onValidationFailed(packet.shared_from_this(),
+                                     "Signature cannot be validated!");
+                  return -1;
+                }
+            }
+          catch (const KeyLocator::Error& e)
+            {
+              onValidationFailed(packet.shared_from_this(),
+                                 "KeyLocator does not have name!");
+              return -1;
+            }
+          catch (const SignatureSha256WithRsa::Error& e)
+            {
+              onValidationFailed(packet.shared_from_this(),
+                                 "Cannot decode signature!");
+              return -1;
+            }
+        }
+      case Signature::Sha256:
+        {
+          onValidationFailed(packet.shared_from_this(),
+                             "FixedSigner does not allow Sha256 signature type!");
+          return -1;
+        }
+      default:
+        {
+          onValidationFailed(packet.shared_from_this(),
+                             "Unsupported signature type: "
+                             + boost::lexical_cast<std::string>(signature.getType()));
+          return -1;
+        }
+      }
+  }
+
+private:
+  typedef std::map<Name, shared_ptr<IdentityCertificate> > SignerList;
+
+  uint32_t m_sigType;
+  SignerList m_signers;
+};
+
+class CheckerFactory
+{
+public:
+  /**
+   * @brief create a checker from configuration file.
+   *
+   * @param configSection The section containing the definition of checker.
+   * @param configFilename The configuration file name.
+   * @return a shared pointer to the created checker.
+   */
+  static shared_ptr<Checker>
+  create(const ConfigSection& configSection, const std::string& configFilename)
+  {
+    ConfigSection::const_iterator propertyIt = configSection.begin();
+
+    // Get checker.type
+    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+      throw Error("Expect <checker.type>!");
+
+    std::string type = propertyIt->second.data();
+
+    if (boost::iequals(type, "customized"))
+      return createCustomizedChecker(configSection, configFilename);
+    else if (boost::iequals(type, "hierarchical"))
+      return createHierarchicalChecker(configSection, configFilename);
+    else if (boost::iequals(type, "fixed-signer"))
+      return createFixedSignerChecker(configSection, configFilename);
+    else
+      throw Error("Unsupported checker type: " + type);
+  }
+
+private:
+  static shared_ptr<Checker>
+  createCustomizedChecker(const ConfigSection& configSection,
+                          const std::string& configFilename)
+  {
+    ConfigSection::const_iterator propertyIt = configSection.begin();
+    propertyIt++;
+
+    // Get checker.sig-type
+    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
+      throw Error("Expect <checker.sig-type>!");
+
+    std::string sigType = propertyIt->second.data();
+    propertyIt++;
+
+    // Get checker.key-locator
+    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator"))
+      throw Error("Expect <checker.key-locator>!");
+
+    shared_ptr<KeyLocatorChecker> keyLocatorChecker =
+      KeyLocatorCheckerFactory::create(propertyIt->second, configFilename);
+    propertyIt++;
+
+    if (propertyIt != configSection.end())
+      throw Error("Expect the end of checker!");
+
+    return make_shared<CustomizedChecker>(boost::cref(getSigType(sigType)),
+                                          boost::cref(keyLocatorChecker));
+  }
+
+  static shared_ptr<Checker>
+  createHierarchicalChecker(const ConfigSection& configSection,
+                            const std::string& configFilename)
+  {
+    ConfigSection::const_iterator propertyIt = configSection.begin();
+    propertyIt++;
+
+    // Get checker.sig-type
+    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
+      throw Error("Expect <checker.sig-type>!");
+
+    std::string sigType = propertyIt->second.data();
+    propertyIt++;
+
+    if (propertyIt != configSection.end())
+      throw Error("Expect the end of checker!");
+
+    return make_shared<HierarchicalChecker>(boost::cref(getSigType(sigType)));
+  }
+
+  static shared_ptr<Checker>
+  createFixedSignerChecker(const ConfigSection& configSection,
+                           const std::string& configFilename)
+  {
+    ConfigSection::const_iterator propertyIt = configSection.begin();
+    propertyIt++;
+
+    // Get checker.sig-type
+    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
+      throw Error("Expect <checker.sig-type>!");
+
+    std::string sigType = propertyIt->second.data();
+    propertyIt++;
+
+    std::vector<shared_ptr<IdentityCertificate> > signers;
+    for (; propertyIt != configSection.end(); propertyIt++)
+      {
+        if (!boost::iequals(propertyIt->first, "signer"))
+          throw Error("Expect <checker.signer> but get <checker."
+                      + propertyIt->first + ">");
+
+        signers.push_back(getSigner(propertyIt->second, configFilename));
+      }
+
+    if (propertyIt != configSection.end())
+      throw Error("Expect the end of checker!");
+
+    return shared_ptr<FixedSignerChecker>(new FixedSignerChecker(getSigType(sigType),
+                                                                 signers));
+  }
+
+  static shared_ptr<IdentityCertificate>
+  getSigner(const ConfigSection& configSection, const std::string& configFilename)
+  {
+    using namespace boost::filesystem;
+
+    ConfigSection::const_iterator propertyIt = configSection.begin();
+
+    // Get checker.signer.type
+    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+      throw Error("Expect <checker.signer.type>!");
+
+    std::string type = propertyIt->second.data();
+    propertyIt++;
+
+    if (boost::iequals(type, "file"))
+      {
+        // Get checker.signer.file-name
+        if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name"))
+          throw Error("Expect <checker.signer.file-name>!");
+
+        path certfilePath = absolute(propertyIt->second.data(),
+                                     path(configFilename).parent_path());
+        propertyIt++;
+
+        if (propertyIt != configSection.end())
+          throw Error("Expect the end of checker.signer");
+
+        shared_ptr<IdentityCertificate> idCert
+          = io::load<IdentityCertificate>(certfilePath.c_str());
+
+        if (static_cast<bool>(idCert))
+          return idCert;
+        else
+          throw Error("Cannot read certificate from file: "
+                      + certfilePath.native());
+      }
+    else if (boost::iequals(type, "base64"))
+      {
+        // Get checker.signer.base64-string
+        if (propertyIt == configSection.end() ||
+            !boost::iequals(propertyIt->first, "base64-string"))
+          throw Error("Expect <checker.signer.base64-string>!");
+
+        std::stringstream ss(propertyIt->second.data());
+        propertyIt++;
+
+        if (propertyIt != configSection.end())
+          throw Error("Expect the end of checker.signer");
+
+        shared_ptr<IdentityCertificate> idCert = io::load<IdentityCertificate>(ss);
+
+        if (static_cast<bool>(idCert))
+          return idCert;
+        else
+          throw Error("Cannot decode certificate from string");
+      }
+    else
+      throw Error("Unsupported checker.signer type: " + type);
+  }
+
+  static int32_t
+  getSigType(const std::string& sigType)
+  {
+    if (boost::iequals(sigType, "rsa-sha256"))
+      return Signature::Sha256WithRsa;
+    else if (boost::iequals(sigType, "sha256"))
+      return Signature::Sha256;
+    else
+      return -1;
+  }
+};
+
+} // namespace conf
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_SEC_CONF_RULE_SIGNER_HPP
diff --git a/src/security/conf/common.hpp b/src/security/conf/common.hpp
new file mode 100644
index 0000000..ba68e2a
--- /dev/null
+++ b/src/security/conf/common.hpp
@@ -0,0 +1,34 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_SECURITY_CONF_COMMON_HPP
+#define NDN_SECURITY_CONF_COMMON_HPP
+
+#include <string>
+#include <boost/property_tree/ptree.hpp>
+
+namespace ndn {
+namespace security {
+namespace conf {
+
+typedef boost::property_tree::ptree ConfigSection;
+
+class Error : public std::runtime_error
+{
+public:
+  explicit
+  Error(const std::string& what)
+    : std::runtime_error(what)
+  {
+  }
+};
+
+} // namespace conf
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_CONF_COMMON_HPP
diff --git a/src/security/conf/filter.hpp b/src/security/conf/filter.hpp
new file mode 100644
index 0000000..1db7498
--- /dev/null
+++ b/src/security/conf/filter.hpp
@@ -0,0 +1,224 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_SECURITY_CONF_FILTER_HPP
+#define NDN_SECURITY_CONF_FILTER_HPP
+
+#include "../../common.hpp"
+#include "../../data.hpp"
+#include "../../interest.hpp"
+#include "../../util/regex.hpp"
+#include <boost/algorithm/string.hpp>
+
+#include "common.hpp"
+
+namespace ndn {
+namespace security {
+namespace conf {
+
+class Filter
+{
+public:
+  virtual
+  ~Filter()
+  {
+  }
+
+  virtual bool
+  match(const Data& data) = 0;
+
+  virtual bool
+  match(const Interest& interest) = 0;
+};
+
+class RelationNameFilter : public Filter
+{
+public:
+  enum Relation
+    {
+      RELATION_EQUAL,
+      RELATION_IS_PREFIX_OF,
+      RELATION_IS_STRICT_PREFIX_OF,
+    };
+
+  RelationNameFilter(const Name& name, Relation relation)
+    : m_name(name)
+    , m_relation(relation)
+  {
+  }
+
+  virtual
+  ~RelationNameFilter()
+  {
+  }
+
+  virtual bool
+  match(const Data& data)
+  {
+    return match(data.getName());
+  }
+
+  virtual bool
+  match(const Interest& interest)
+  {
+    if (interest.getName().size() < 2)
+      return false;
+
+    Name signedName = interest.getName().getPrefix(-2);
+    return match(signedName);
+  }
+
+private:
+  bool
+  match(const Name& name)
+  {
+    switch (m_relation)
+      {
+      case RELATION_EQUAL:
+        return (name == m_name);
+      case RELATION_IS_PREFIX_OF:
+        return m_name.isPrefixOf(name);
+      case RELATION_IS_STRICT_PREFIX_OF:
+        return (m_name.isPrefixOf(name) && m_name != name);
+      default:
+        return false;
+      }
+  }
+
+private:
+  Name m_name;
+  Relation m_relation;
+};
+
+class RegexNameFilter : public Filter
+{
+public:
+  explicit
+  RegexNameFilter(const Regex& regex)
+    : m_regex(regex)
+  {
+  }
+
+  virtual
+  ~RegexNameFilter()
+  {
+  }
+
+  virtual bool
+  match(const Data& data)
+  {
+    return m_regex.match(data.getName());
+  }
+
+  virtual bool
+  match(const Interest& interest)
+  {
+    if (interest.getName().size() < 2)
+      return false;
+
+    Name signedName = interest.getName().getPrefix(-2);
+    return m_regex.match(signedName);
+  }
+
+private:
+  Regex m_regex;
+};
+
+class FilterFactory
+{
+public:
+  static shared_ptr<Filter>
+  create(const ConfigSection& configSection)
+  {
+    ConfigSection::const_iterator propertyIt = configSection.begin();
+
+    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+      throw Error("Expect <filter.type>!");
+
+    std::string type = propertyIt->second.data();
+
+    if (boost::iequals(type, "name"))
+      return createNameFilter(configSection);
+    else
+      throw Error("Unsupported filter.type: " + type);
+  }
+private:
+  static shared_ptr<Filter>
+  createNameFilter(const ConfigSection& configSection)
+  {
+    ConfigSection::const_iterator propertyIt = configSection.begin();
+    propertyIt++;
+
+    if (propertyIt == configSection.end())
+      throw Error("Expect more properties for filter(name)");
+
+    if (boost::iequals(propertyIt->first, "name"))
+      {
+        // Get filter.name
+        Name name;
+        try
+          {
+            name = Name(propertyIt->second.data());
+          }
+        catch (Name::Error& e)
+          {
+            throw Error("Wrong filter.name: " + propertyIt->second.data());
+          }
+
+        propertyIt++;
+
+        // Get filter.relation
+        if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
+          throw Error("Expect <filter.relation>!");
+
+        std::string relationString = propertyIt->second.data();
+        propertyIt++;
+
+        RelationNameFilter::Relation relation;
+        if (boost::iequals(relationString, "equal"))
+          relation = RelationNameFilter::RELATION_EQUAL;
+        else if (boost::iequals(relationString, "is-prefix-of"))
+          relation = RelationNameFilter::RELATION_IS_PREFIX_OF;
+        else if (boost::iequals(relationString, "is-strict-prefix-of"))
+          relation = RelationNameFilter::RELATION_IS_STRICT_PREFIX_OF;
+        else
+          throw Error("Unsupported relation: " + relationString);
+
+
+        if (propertyIt != configSection.end())
+          throw Error("Expect the end of filter!");
+
+        return make_shared<RelationNameFilter>(boost::cref(name),
+                                               boost::cref(relation));
+      }
+    else if (boost::iequals(propertyIt->first, "regex"))
+      {
+        std::string regexString = propertyIt->second.data();
+        propertyIt++;
+
+        if (propertyIt != configSection.end())
+          throw Error("Expect the end of filter!");
+
+        try
+          {
+            return shared_ptr<RegexNameFilter>(new RegexNameFilter(regexString));
+          }
+        catch (const Regex::Error& e)
+          {
+            throw Error("Wrong filter.regex: " + regexString);
+          }
+      }
+    else
+      throw Error("Wrong filter(name) properties");
+  }
+};
+
+} // namespace conf
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_CONF_FILTER_HPP
diff --git a/src/security/conf/key-locator-checker.hpp b/src/security/conf/key-locator-checker.hpp
new file mode 100644
index 0000000..0f667f7
--- /dev/null
+++ b/src/security/conf/key-locator-checker.hpp
@@ -0,0 +1,362 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
+#define NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
+
+#include "../../common.hpp"
+#include "../../data.hpp"
+#include "../../interest.hpp"
+#include <boost/algorithm/string.hpp>
+
+#include "common.hpp"
+
+namespace ndn {
+namespace security {
+namespace conf {
+
+class KeyLocatorCheckerFactory;
+
+class KeyLocatorChecker
+{
+public:
+  enum Relation
+    {
+      RELATION_EQUAL,
+      RELATION_IS_PREFIX_OF,
+      RELATION_IS_STRICT_PREFIX_OF,
+    };
+
+  virtual
+  ~KeyLocatorChecker()
+  {
+  }
+
+  bool
+  check(const Data& data,
+        const KeyLocator& keyLocator,
+        std::string& failInfo)
+  {
+    return check(data.getName(), keyLocator, failInfo);
+  }
+
+  bool
+  check(const Interest& interest,
+        const KeyLocator& keyLocator,
+        std::string& failInfo)
+  {
+    if (interest.getName().size() < 2)
+      {
+        failInfo = "No Signature";
+        return false;
+      }
+
+    Name signedName = interest.getName().getPrefix(-2);
+    return check(signedName, keyLocator, failInfo);
+  }
+
+protected:
+
+  virtual bool
+  check(const Name& packetName,
+        const KeyLocator& keyLocator,
+        std::string& failInfo) = 0;
+
+  bool
+  checkRelation(const Relation& relation, const Name& name1, const Name& name2)
+  {
+    switch (relation)
+      {
+      case RELATION_EQUAL:
+        return (name1 == name2);
+      case RELATION_IS_PREFIX_OF:
+        return name1.isPrefixOf(name2);
+      case RELATION_IS_STRICT_PREFIX_OF:
+        return (name1.isPrefixOf(name2) && name1 != name2);
+      default:
+        return false;
+      }
+  }
+};
+
+class RelationKeyLocatorNameChecker : public KeyLocatorChecker
+{
+public:
+  RelationKeyLocatorNameChecker(const Name& name,
+                                const KeyLocatorChecker::Relation& relation)
+    : m_name(name)
+    , m_relation(relation)
+  {
+  }
+
+protected:
+  virtual bool
+  check(const Name& packetName,
+        const KeyLocator& keyLocator,
+        std::string& failInfo)
+  {
+    try
+      {
+        if (checkRelation(m_relation, m_name, keyLocator.getName()))
+          return true;
+
+        failInfo = "KeyLocatorChecker failed!";
+        return false;
+      }
+    catch (const KeyLocator::Error& e)
+      {
+        failInfo = "KeyLocator does not have name";
+        return false;
+      }
+  }
+
+private:
+  Name m_name;
+  KeyLocatorChecker::Relation m_relation;
+};
+
+class RegexKeyLocatorNameChecker : public KeyLocatorChecker
+{
+public:
+  RegexKeyLocatorNameChecker(const Regex& regex)
+    : m_regex(regex)
+  {
+  }
+
+protected:
+  virtual bool
+  check(const Name& packetName,
+        const KeyLocator& keyLocator,
+        std::string& failInfo)
+  {
+    try
+      {
+        if (m_regex.match(keyLocator.getName()))
+          return true;
+
+        failInfo = "KeyLocatorChecker failed!";
+        return false;
+      }
+    catch (const KeyLocator::Error& e)
+      {
+        failInfo = "KeyLocator does not have name";
+        return false;
+      }
+  }
+
+private:
+  Regex m_regex;
+};
+
+class HyperKeyLocatorNameChecker : public KeyLocatorChecker
+{
+public:
+  HyperKeyLocatorNameChecker(const std::string& pExpr, const std::string pExpand,
+                             const std::string& kExpr, const std::string kExpand,
+                             const Relation& hyperRelation)
+    : m_hyperPRegex(new Regex(pExpr, pExpand))
+    , m_hyperKRegex(new Regex(kExpr, kExpand))
+    , m_hyperRelation(hyperRelation)
+  {
+  }
+
+protected:
+  virtual bool
+  check(const Name& packetName,
+        const KeyLocator& keyLocator,
+        std::string& failInfo)
+  {
+    try
+      {
+        if (m_hyperPRegex->match(packetName) &&
+            m_hyperKRegex->match(keyLocator.getName()) &&
+            checkRelation(m_hyperRelation,
+                          m_hyperKRegex->expand(),
+                          m_hyperPRegex->expand()))
+          return true;
+
+        failInfo = "KeyLocatorChecker failed!";
+        return false;
+      }
+    catch (const KeyLocator::Error& e)
+      {
+        failInfo = "KeyLocator does not have name";
+        return false;
+      }
+
+  }
+
+private:
+  shared_ptr<Regex> m_hyperPRegex;
+  shared_ptr<Regex> m_hyperKRegex;
+  Relation m_hyperRelation;
+};
+
+
+class KeyLocatorCheckerFactory
+{
+public:
+  static shared_ptr<KeyLocatorChecker>
+  create(const ConfigSection& configSection, const std::string& filename)
+  {
+    ConfigSection::const_iterator propertyIt = configSection.begin();
+
+    // Get checker.key-locator.type
+    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+      throw Error("Expect <checker.key-locator.type>!");
+
+    std::string type = propertyIt->second.data();
+
+    if (boost::iequals(type, "name"))
+      return createKeyLocatorNameChecker(configSection, filename);
+    else
+      throw Error("Unsupported checker.key-locator.type: " + type);
+  }
+
+private:
+  static shared_ptr<KeyLocatorChecker>
+  createKeyLocatorNameChecker(const ConfigSection& configSection,
+                              const std::string& filename)
+  {
+    ConfigSection::const_iterator propertyIt = configSection.begin();
+    propertyIt++;
+
+    if (propertyIt == configSection.end())
+      throw Error("Expect more checker.key-locator properties");
+
+    if (boost::iequals(propertyIt->first, "name"))
+      {
+        Name name;
+        try
+          {
+            name = Name(propertyIt->second.data());
+          }
+        catch (Name::Error& e)
+          {
+            throw Error("Invalid checker.key-locator.name: "
+                        + propertyIt->second.data());
+          }
+        propertyIt++;
+
+        if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
+          throw Error("Expect <checker.key-locator.relation>!");
+
+        std::string relationString = propertyIt->second.data();
+        propertyIt++;
+
+        KeyLocatorChecker::Relation relation;
+        if (boost::iequals(relationString, "equal"))
+          relation = KeyLocatorChecker::RELATION_EQUAL;
+        else if (boost::iequals(relationString, "is-prefix-of"))
+          relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
+        else if (boost::iequals(relationString, "is-strict-prefix-of"))
+          relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
+        else
+          throw Error("Unsupported relation: " + relationString);
+
+        if (propertyIt != configSection.end())
+          throw Error("Expect the end of checker.key-locator!");
+
+        return shared_ptr<RelationKeyLocatorNameChecker>
+          (new RelationKeyLocatorNameChecker(name, relation));
+      }
+    else if (boost::iequals(propertyIt->first, "regex"))
+      {
+        std::string regexString = propertyIt->second.data();
+        propertyIt++;
+
+        if (propertyIt != configSection.end())
+          throw Error("Expect the end of checker.key-locator!");
+
+        try
+          {
+            return shared_ptr<RegexKeyLocatorNameChecker>
+              (new RegexKeyLocatorNameChecker(regexString));
+          }
+        catch (const Regex::Error& e)
+          {
+            throw Error("Invalid checker.key-locator.regex: " + regexString);
+          }
+      }
+    else if (boost::iequals(propertyIt->first, "hyper-relation"))
+      {
+        const ConfigSection& hSection = propertyIt->second;
+
+        ConfigSection::const_iterator hPropertyIt = hSection.begin();
+
+        // Get k-regex
+        if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-regex"))
+          throw Error("Expect <checker.key-locator.hyper-relation.k-regex>!");
+
+        std::string kRegex = hPropertyIt->second.data();
+        hPropertyIt++;
+
+        // Get k-expand
+        if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-expand"))
+          throw Error("Expect <checker.key-locator.hyper-relation.k-expand>!");
+
+        std::string kExpand = hPropertyIt->second.data();
+        hPropertyIt++;
+
+        // Get h-relation
+        if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "h-relation"))
+          throw Error("Expect <checker.key-locator.hyper-relation.h-relation>!");
+
+        std::string hRelation = hPropertyIt->second.data();
+        hPropertyIt++;
+
+        // Get p-regex
+        if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-regex"))
+          throw Error("Expect <checker.key-locator.hyper-relation.p-regex>!");
+
+        std::string pRegex = hPropertyIt->second.data();
+        hPropertyIt++;
+
+        // Get p-expand
+        if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-expand"))
+          throw Error("Expect <checker.key-locator.hyper-relation.p-expand>!");
+
+        std::string pExpand = hPropertyIt->second.data();
+        hPropertyIt++;
+
+        if (hPropertyIt != hSection.end())
+          throw Error("Expect the end of checker.key-locator.hyper-relation!");
+
+        KeyLocatorChecker::Relation relation;
+        if (boost::iequals(hRelation, "equal"))
+          relation = KeyLocatorChecker::RELATION_EQUAL;
+        else if (boost::iequals(hRelation, "is-prefix-of"))
+          relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
+        else if (boost::iequals(hRelation, "is-strict-prefix-of"))
+          relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
+        else
+          throw Error("Unsupported checker.key-locator.hyper-relation.h-relation: "
+                      + hRelation);
+
+        try
+          {
+            return shared_ptr<HyperKeyLocatorNameChecker>
+              (new HyperKeyLocatorNameChecker(pRegex, pExpand,
+                                              kRegex, kExpand,
+                                              relation));
+          }
+        catch (const Regex::Error& e)
+          {
+            throw Error("Invalid regex for key-locator.hyper-relation");
+          }
+      }
+    else
+      throw Error("Unsupported checker.key-locator");
+  }
+};
+
+
+} // namespace conf
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
diff --git a/src/security/conf/rule.hpp b/src/security/conf/rule.hpp
new file mode 100644
index 0000000..560c440
--- /dev/null
+++ b/src/security/conf/rule.hpp
@@ -0,0 +1,106 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_SECURITY_CONF_RULE_HPP
+#define NDN_SECURITY_CONF_RULE_HPP
+
+#include "filter.hpp"
+#include "checker.hpp"
+
+
+namespace ndn {
+namespace security {
+namespace conf {
+
+template<class Packet>
+class Rule
+{
+public:
+  Rule(const std::string& id)
+    : m_id(id)
+  {
+  }
+
+  virtual
+  ~Rule()
+  {
+  }
+
+  const std::string&
+  getId()
+  {
+    return m_id;
+  }
+
+  void
+  addFilter(const shared_ptr<Filter>& filter)
+  {
+    m_filters.push_back(filter);
+  }
+
+  void
+  addChecker(const shared_ptr<Checker>& checker)
+  {
+    m_checkers.push_back(checker);
+  }
+
+  bool
+  match(const Packet& packet)
+  {
+    if (m_filters.empty())
+      return true;
+
+    for (FilterList::iterator it = m_filters.begin();
+         it != m_filters.end(); it++)
+      {
+        if (!(*it)->match(packet))
+          return false;
+      }
+
+    return true;
+  }
+
+  /**
+   * @brief check if packet satisfies certain condition
+   *
+   * @param packet The packet
+   * @param onValidated Callback function which is called when packet is immediately valid
+   * @param onValidationFailed Call function which is called when packet is immediately invalid
+   * @return -1 if packet is immediately invalid (onValidationFailed has been called)
+   *          1 if packet is immediately valid (onValidated has been called)
+   *          0 if further signature verification is needed.
+   */
+  template<class ValidatedCallback, class ValidationFailureCallback>
+  int8_t
+  check(const Packet& packet,
+        const ValidatedCallback& onValidated,
+        const ValidationFailureCallback& onValidationFailed)
+  {
+    for (CheckerList::iterator it = m_checkers.begin();
+         it != m_checkers.end(); it++)
+      {
+        int8_t result = (*it)->check(packet, onValidated, onValidationFailed);
+        if (result >= 0)
+          return result;
+      }
+    return -1;
+  }
+
+private:
+  typedef std::vector<shared_ptr<Filter> > FilterList;
+  typedef std::vector<shared_ptr<Checker> > CheckerList;
+
+  std::string m_id;
+  FilterList m_filters;
+  CheckerList m_checkers;
+};
+
+} // namespace conf
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_CONF_RULE_HPP
diff --git a/src/security/validator-config.cpp b/src/security/validator-config.cpp
new file mode 100644
index 0000000..2085daf
--- /dev/null
+++ b/src/security/validator-config.cpp
@@ -0,0 +1,352 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "validator-config.hpp"
+#include "certificate-cache-ttl.hpp"
+#include "../util/io.hpp"
+
+#include <boost/filesystem.hpp>
+#include <boost/property_tree/info_parser.hpp>
+#include <boost/algorithm/string.hpp>
+
+namespace ndn {
+
+const shared_ptr<CertificateCache> ValidatorConfig::DEFAULT_CERTIFICATE_CACHE;
+
+ValidatorConfig::ValidatorConfig(shared_ptr<Face> face,
+                                 shared_ptr<CertificateCache> certificateCache,
+                                 const int stepLimit)
+  : Validator(face)
+  , m_stepLimit(stepLimit)
+  , m_certificateCache(certificateCache)
+{
+  if (!static_cast<bool>(face))
+    throw Error("Face is not set!");
+
+  if (!static_cast<bool>(m_certificateCache))
+    m_certificateCache = make_shared<CertificateCacheTtl>(m_face->ioService());
+}
+
+void
+ValidatorConfig::load(const std::string& filename)
+{
+  std::ifstream inputFile;
+  inputFile.open(filename.c_str());
+  if (!inputFile.good() || !inputFile.is_open())
+    {
+      std::string msg = "Failed to read configuration file: ";
+      msg += filename;
+      throw security::conf::Error(msg);
+    }
+  load(inputFile, filename);
+  inputFile.close();
+}
+
+void
+ValidatorConfig::load(const std::string& input, const std::string& filename)
+{
+  std::istringstream inputStream(input);
+  load(inputStream, filename);
+}
+
+
+void
+ValidatorConfig::load(std::istream& input, const std::string& filename)
+{
+  security::conf::ConfigSection tree;
+  try
+    {
+      boost::property_tree::read_info(input, tree);
+    }
+  catch (const boost::property_tree::info_parser_error& error)
+    {
+      std::stringstream msg;
+      msg << "Failed to parse configuration file";
+      msg << " " << filename;
+      msg << " " << error.message() << " line " << error.line();
+      throw security::conf::Error(msg.str());
+    }
+
+  process(tree, filename);
+}
+
+void
+ValidatorConfig::process(const security::conf::ConfigSection& configSection,
+                         const std::string& filename)
+{
+  BOOST_ASSERT(!filename.empty());
+
+  if (configSection.begin() == configSection.end())
+    {
+      std::string msg = "Error processing configuration file";
+      msg += ": ";
+      msg += filename;
+      msg += " no data";
+      throw security::conf::Error(msg);
+    }
+
+  for (security::conf::ConfigSection::const_iterator i = configSection.begin();
+       i != configSection.end(); ++i)
+    {
+      const std::string& sectionName = i->first;
+      const security::conf::ConfigSection& section = i->second;
+
+      if (boost::iequals(sectionName, "rule"))
+        {
+          onConfigRule(section, filename);
+        }
+      else if (boost::iequals(sectionName, "trust-anchor"))
+        {
+          onConfigTrustAnchor(section, filename);
+        }
+      else
+        {
+          std::string msg = "Error processing configuration file";
+          msg += " ";
+          msg += filename;
+          msg += " unrecognized section: " + sectionName;
+          throw security::conf::Error(msg);
+        }
+    }
+}
+
+void
+ValidatorConfig::onConfigRule(const security::conf::ConfigSection& configSection,
+                              const std::string& filename)
+{
+  using namespace ndn::security::conf;
+
+  ConfigSection::const_iterator propertyIt = configSection.begin();
+
+  // Get rule.id
+  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "id"))
+    throw Error("Expect <rule.id>!");
+
+  std::string ruleId = propertyIt->second.data();
+  propertyIt++;
+
+  // Get rule.for
+  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"for"))
+    throw Error("Expect <rule.for> in rule: " + ruleId + "!");
+
+  std::string usage = propertyIt->second.data();
+  propertyIt++;
+
+  bool isForData;
+  if (boost::iequals(usage, "data"))
+    isForData = true;
+  else if (boost::iequals(usage, "interest"))
+    isForData = false;
+  else
+    throw Error("Unrecognized <rule.for>: " + usage
+                + " in rule: " + ruleId);
+
+  // Get rule.filter(s)
+  std::vector<shared_ptr<Filter> > filters;
+  for (; propertyIt != configSection.end(); propertyIt++)
+    {
+      if (!boost::iequals(propertyIt->first, "filter"))
+        {
+          if (boost::iequals(propertyIt->first, "checker"))
+            break;
+          throw Error("Expect <rule.filter> in rule: " + ruleId);
+        }
+
+      filters.push_back(FilterFactory::create(propertyIt->second));
+      continue;
+    }
+
+  // Get rule.checker(s)
+  std::vector<shared_ptr<Checker> > checkers;
+  for (; propertyIt != configSection.end(); propertyIt++)
+    {
+      if (!boost::iequals(propertyIt->first, "checker"))
+        throw Error("Expect <rule.checker> in rule: " + ruleId);
+
+      checkers.push_back(CheckerFactory::create(propertyIt->second, filename));
+      continue;
+    }
+
+  // Check other stuff
+  if (propertyIt != configSection.end())
+    throw Error("Expect the end of rule: " + ruleId);
+
+  if (checkers.size() == 0)
+    throw Error("No <rule.checker> is specified in rule: " + ruleId);
+
+  if (isForData)
+    {
+      shared_ptr<DataRule> rule(new DataRule(ruleId));
+      for (size_t i = 0; i < filters.size(); i++)
+        rule->addFilter(filters[i]);
+      for (size_t i = 0; i < checkers.size(); i++)
+        rule->addChecker(checkers[i]);
+
+      m_dataRules.push_back(rule);
+    }
+  else
+    {
+      shared_ptr<InterestRule> rule(new InterestRule(ruleId));
+      for (size_t i = 0; i < filters.size(); i++)
+        rule->addFilter(filters[i]);
+      for (size_t i = 0; i < checkers.size(); i++)
+        rule->addChecker(checkers[i]);
+
+      m_interestRules.push_back(rule);
+    }
+}
+
+void
+ValidatorConfig::onConfigTrustAnchor(const security::conf::ConfigSection& configSection,
+                                     const std::string& filename)
+{
+  using namespace ndn::security::conf;
+  using namespace boost::filesystem;
+
+  ConfigSection::const_iterator propertyIt = configSection.begin();
+
+  // Get trust-anchor.type
+  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+    throw Error("Expect <trust-anchor.type>!");
+
+  std::string type = propertyIt->second.data();
+  propertyIt++;
+
+  if (boost::iequals(type, "file"))
+    {
+      // Get trust-anchor.file
+      if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"file-name"))
+        throw Error("Expect <trust-anchor.file-name>!");
+
+      std::string file = propertyIt->second.data();
+      propertyIt++;
+
+      // Check other stuff
+      if (propertyIt != configSection.end())
+        throw Error("Expect the end of trust-anchor!");
+
+      path certfilePath = absolute(file, path(filename).parent_path());
+      shared_ptr<IdentityCertificate> idCert =
+        io::load<IdentityCertificate>(certfilePath.string());
+
+      if (static_cast<bool>(idCert))
+        {
+          BOOST_ASSERT(idCert->getName().size() >= 1);
+          m_anchors[idCert->getName().getPrefix(-1)] = idCert;
+        }
+      else
+        throw Error("Cannot read certificate from file: " +
+                    certfilePath.native());
+
+      return;
+    }
+  else if (boost::iequals(type, "base64"))
+    {
+      // Get trust-anchor.base64-string
+      if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "base64-string"))
+        throw Error("Expect <trust-anchor.base64-string>!");
+
+      std::stringstream ss(propertyIt->second.data());
+      propertyIt++;
+
+      // Check other stuff
+      if (propertyIt != configSection.end())
+        throw Error("Expect the end of trust-anchor!");
+
+      shared_ptr<IdentityCertificate> idCert = io::load<IdentityCertificate>(ss);
+
+      if (static_cast<bool>(idCert))
+        {
+          BOOST_ASSERT(idCert->getName().size() >= 1);
+          m_anchors[idCert->getName().getPrefix(-1)] = idCert;
+        }
+      else
+        throw Error("Cannot decode certificate from base64-string");
+
+      return;
+    }
+  else
+    throw Error("Unsupported trust-anchor.type: " + type);
+}
+
+void
+ValidatorConfig::checkPolicy(const Data& data,
+                             int stepCount,
+                             const OnDataValidated& onValidated,
+                             const OnDataValidationFailed& onValidationFailed,
+                             std::vector<shared_ptr<ValidationRequest> >& nextSteps)
+{
+  if (m_stepLimit == stepCount)
+    return onValidationFailed(data.shared_from_this(),
+                              "Maximum steps of validation reached");
+
+  bool isMatched = false;
+  int8_t checkResult = -1;
+
+  for (DataRuleList::iterator it = m_dataRules.begin();
+       it != m_dataRules.end(); it++)
+    {
+      if ((*it)->match(data))
+        {
+          isMatched = true;
+          checkResult = (*it)->check(data, onValidated, onValidationFailed);
+          break;
+        }
+    }
+
+  if (!isMatched)
+    return onValidationFailed(data.shared_from_this(), "No rule matched!");
+
+  if (checkResult == 0)
+    {
+      const Signature& signature = data.getSignature();
+      checkSignature(data, signature, stepCount,
+                     onValidated, onValidationFailed, nextSteps);
+    }
+}
+
+void
+ValidatorConfig::checkPolicy(const Interest& interest,
+                             int stepCount,
+                             const OnInterestValidated& onValidated,
+                             const OnInterestValidationFailed& onValidationFailed,
+                             std::vector<shared_ptr<ValidationRequest> >& nextSteps)
+{
+  if (m_stepLimit == stepCount)
+    return onValidationFailed(interest.shared_from_this(),
+                              "Maximum steps of validation reached");
+
+  bool isMatched = false;
+  int8_t checkResult = -1;
+
+  for (InterestRuleList::iterator it = m_interestRules.begin();
+       it != m_interestRules.end(); it++)
+    {
+      if ((*it)->match(interest))
+        {
+          isMatched = true;
+          checkResult = (*it)->check(interest, onValidated, onValidationFailed);
+          break;
+        }
+    }
+
+  if (!isMatched)
+    return onValidationFailed(interest.shared_from_this(), "No rule matched!");
+
+  if (checkResult == 0)
+    {
+      const Name& interestName = interest.getName();
+      Name signedName = interestName.getPrefix(-2);
+      Signature signature(interestName[-2].blockFromValue(),
+                          interestName[-1].blockFromValue());
+
+      checkSignature(interest, signature, stepCount,
+                     onValidated, onValidationFailed, nextSteps);
+    }
+}
+
+
+} // namespace ndn
diff --git a/src/security/validator-config.hpp b/src/security/validator-config.hpp
new file mode 100644
index 0000000..acc85f5
--- /dev/null
+++ b/src/security/validator-config.hpp
@@ -0,0 +1,224 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_SECURITY_VALIDATOR_CONFIG_HPP
+#define NDN_SECURITY_VALIDATOR_CONFIG_HPP
+
+#include "validator.hpp"
+#include "certificate-cache.hpp"
+#include "conf/rule.hpp"
+#include "conf/common.hpp"
+
+namespace ndn {
+
+class ValidatorConfig : public Validator
+{
+public:
+  class Error : public Validator::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : Validator::Error(what)
+    {
+    }
+  };
+
+  static const shared_ptr<CertificateCache> DEFAULT_CERTIFICATE_CACHE;
+
+  ValidatorConfig(shared_ptr<Face> face,
+                  shared_ptr<CertificateCache> certificateCache = DEFAULT_CERTIFICATE_CACHE,
+                  const int stepLimit = 10);
+
+  virtual
+  ~ValidatorConfig()
+  {
+  }
+
+  void
+  load(const std::string& filename);
+
+  void
+  load(const std::string& input, const std::string& filename);
+
+  void
+  load(std::istream& input, const std::string& filename);
+
+protected:
+  virtual void
+  checkPolicy(const Data& data,
+              int stepCount,
+              const OnDataValidated& onValidated,
+              const OnDataValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps);
+
+  virtual void
+  checkPolicy(const Interest& interest,
+              int stepCount,
+              const OnInterestValidated& onValidated,
+              const OnInterestValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps);
+
+private:
+  template<class Packet, class OnValidated, class OnFailed>
+  void
+  checkSignature(const Packet& packet,
+                 const Signature& signature,
+                 int stepCount,
+                 const OnValidated& onValidated,
+                 const OnFailed& onValidationFailed,
+                 std::vector<shared_ptr<ValidationRequest> >& nextSteps);
+
+  template<class Packet, class OnValidated, class OnFailed>
+  void
+  onCertValidated(const shared_ptr<const Data>& signCertificate,
+                  const shared_ptr<const Packet>& packet,
+                  const OnValidated& onValidated,
+                  const OnFailed& onValidationFailed);
+
+  template<class Packet, class OnFailed>
+  void
+  onCertFailed(const shared_ptr<const Data>& signCertificate,
+               const std::string& failureInfo,
+               const shared_ptr<const Packet>& packet,
+               const OnFailed& onValidationFailed);
+
+  void
+  process(const security::conf::ConfigSection& configSection,
+          const std::string& filename);
+
+  void
+  onConfigRule(const security::conf::ConfigSection& section,
+               const std::string& filename);
+
+  void
+  onConfigTrustAnchor(const security::conf::ConfigSection& section,
+                      const std::string& filename);
+
+private:
+  typedef security::conf::Rule<Interest> InterestRule;
+  typedef security::conf::Rule<Data>     DataRule;
+  typedef std::vector<shared_ptr<InterestRule> > InterestRuleList;
+  typedef std::vector<shared_ptr<DataRule> >     DataRuleList;
+  typedef std::map<Name, shared_ptr<IdentityCertificate> > AnchorList;
+
+  int m_stepLimit;
+  shared_ptr<CertificateCache> m_certificateCache;
+
+  InterestRuleList m_interestRules;
+  DataRuleList m_dataRules;
+  AnchorList m_anchors;
+};
+
+template<class Packet, class OnValidated, class OnFailed>
+void
+ValidatorConfig::checkSignature(const Packet& packet,
+                                const Signature& signature,
+                                int stepCount,
+                                const OnValidated& onValidated,
+                                const OnFailed& onValidationFailed,
+                                std::vector<shared_ptr<ValidationRequest> >& nextSteps)
+{
+  if (signature.getType() == Signature::Sha256)
+    {
+      SignatureSha256 sigSha256(signature);
+
+      if (verifySignature(packet, sigSha256))
+        return onValidated(packet.shared_from_this());
+      else
+        return onValidationFailed(packet.shared_from_this(),
+                                  "Sha256 Signature cannot be verified!");
+    }
+
+  if (signature.getType() == Signature::Sha256WithRsa)
+    {
+      SignatureSha256WithRsa sigSha256Rsa(signature);
+      Name keyLocatorName = sigSha256Rsa.getKeyLocator().getName();
+
+      shared_ptr<const Certificate> trustedCert;
+
+      AnchorList::const_iterator it = m_anchors.find(keyLocatorName);
+      if (m_anchors.end() == it)
+        trustedCert = m_certificateCache->getCertificate(keyLocatorName);
+      else
+        trustedCert = it->second;
+
+      if (static_cast<bool>(trustedCert))
+        {
+          if (verifySignature(packet, sigSha256Rsa, trustedCert->getPublicKeyInfo()))
+            return onValidated(packet.shared_from_this());
+          else
+            return onValidationFailed(packet.shared_from_this(),
+                                      "Cannot verify signature");
+        }
+      else
+        {
+          OnDataValidated onCertValidated =
+            bind(&ValidatorConfig::onCertValidated<Packet, OnValidated, OnFailed>,
+                 this, _1, packet.shared_from_this(), onValidated, onValidationFailed);
+
+          OnDataValidationFailed onCertValidationFailed =
+            bind(&ValidatorConfig::onCertFailed<Packet, OnFailed>,
+                 this, _1, _2, packet.shared_from_this(), onValidationFailed);
+
+          Interest certInterest(keyLocatorName);
+
+          shared_ptr<ValidationRequest> nextStep =
+            make_shared<ValidationRequest>(boost::cref(certInterest),
+                                           onCertValidated,
+                                           onCertValidationFailed,
+                                           1, stepCount + 1);
+
+          nextSteps.push_back(nextStep);
+          return;
+        }
+    }
+  return onValidationFailed(packet.shared_from_this(), "Unsupported Signature Type!");
+}
+
+template<class Packet, class OnValidated, class OnFailed>
+void
+ValidatorConfig::onCertValidated(const shared_ptr<const Data>& signCertificate,
+                                 const shared_ptr<const Packet>& packet,
+                                 const OnValidated& onValidated,
+                                 const OnFailed& onValidationFailed)
+{
+  shared_ptr<IdentityCertificate> certificate =
+    make_shared<IdentityCertificate>(boost::cref(*signCertificate));
+
+  if (!certificate->isTooLate() && !certificate->isTooEarly())
+    {
+      m_certificateCache->insertCertificate(certificate);
+
+      if (verifySignature(*packet, certificate->getPublicKeyInfo()))
+        return onValidated(packet);
+      else
+        return onValidationFailed(packet,
+                                  "Cannot verify signature: " +
+                                  packet->getName().toUri());
+    }
+  else
+    {
+      return onValidationFailed(packet,
+                                "Signing certificate " +
+                                signCertificate->getName().toUri() +
+                                " is no longer valid.");
+    }
+}
+
+template<class Packet, class OnFailed>
+void
+ValidatorConfig::onCertFailed(const shared_ptr<const Data>& signCertificate,
+                              const std::string& failureInfo,
+                              const shared_ptr<const Packet>& packet,
+                              const OnFailed& onValidationFailed)
+{
+  onValidationFailed(packet, failureInfo);
+}
+
+} // namespace ndn
+
+#endif // NDN_SECURITY_VALIDATOR_CONFIG_HPP
diff --git a/src/security/validator-regex.cpp b/src/security/validator-regex.cpp
index ec22de8..0f09741 100644
--- a/src/security/validator-regex.cpp
+++ b/src/security/validator-regex.cpp
@@ -19,127 +19,147 @@
 
 namespace ndn {
 
-const shared_ptr<CertificateCache> ValidatorRegex::DefaultCertificateCache = shared_ptr<CertificateCache>();
+const shared_ptr<CertificateCache> ValidatorRegex::DEFAULT_CERTIFICATE_CACHE;
 
 ValidatorRegex::ValidatorRegex(shared_ptr<Face> face,
-                               shared_ptr<CertificateCache> certificateCache /* = DefaultCertificateCache */,
-                               const int stepLimit /* = 3 */)
+                               shared_ptr<CertificateCache> certificateCache,
+                               const int stepLimit)
   : Validator(face)
   , m_stepLimit(stepLimit)
   , m_certificateCache(certificateCache)
 {
-  if(!static_cast<bool>(face))
+  if (!static_cast<bool>(face))
     throw Error("Face is not set!");
 
-  if(!static_cast<bool>(m_certificateCache))
+  if (!static_cast<bool>(m_certificateCache))
     m_certificateCache = make_shared<CertificateCacheTtl>(m_face->ioService());
 }
 
 void
-ValidatorRegex::onCertificateValidated(const shared_ptr<const Data> &signCertificate, 
-                                       const shared_ptr<const Data> &data, 
-                                       const OnDataValidated &onValidated, 
-                                       const OnDataValidationFailed &onValidationFailed)
+ValidatorRegex::onCertificateValidated(const shared_ptr<const Data>& signCertificate,
+                                       const shared_ptr<const Data>& data,
+                                       const OnDataValidated& onValidated,
+                                       const OnDataValidationFailed& onValidationFailed)
 {
-  shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>(*signCertificate);
-  
-  if(!certificate->isTooLate() && !certificate->isTooEarly())
+  shared_ptr<IdentityCertificate> certificate =
+    make_shared<IdentityCertificate>(boost::cref(*signCertificate));
+
+  if (!certificate->isTooLate() && !certificate->isTooEarly())
     {
       m_certificateCache->insertCertificate(certificate);
-      
-      if(verifySignature(*data, certificate->getPublicKeyInfo()))
+
+      if (verifySignature(*data, certificate->getPublicKeyInfo()))
         return onValidated(data);
       else
-        return onValidationFailed(data, 
-                                  "Cannot verify signature: " + data->getName().toUri());
+        return onValidationFailed(data,
+                                  "Cannot verify signature: " +
+                                  data->getName().toUri());
     }
   else
     {
       _LOG_DEBUG("Wrong validity:");
-      return onValidationFailed(data, 
-                                "Signing certificate " + signCertificate->getName().toUri() + " is no longer valid.");
+      return onValidationFailed(data,
+                                "Signing certificate " +
+                                signCertificate->getName().toUri() +
+                                " is no longer valid.");
     }
 }
 
 void
-ValidatorRegex::onCertificateValidationFailed(const shared_ptr<const Data> &signCertificate, 
+ValidatorRegex::onCertificateValidationFailed(const shared_ptr<const Data>& signCertificate,
                                               const string& failureInfo,
-                                              const shared_ptr<const Data> &data, 
-                                              const OnDataValidationFailed &onValidationFailed)
-{ onValidationFailed(data, failureInfo); }
+                                              const shared_ptr<const Data>& data,
+                                              const OnDataValidationFailed& onValidationFailed)
+{
+  onValidationFailed(data, failureInfo);
+}
 
 void
-ValidatorRegex::checkPolicy(const Data& data, 
-                            int stepCount, 
-                            const OnDataValidated &onValidated, 
-                            const OnDataValidationFailed &onValidationFailed,
-                            vector<shared_ptr<ValidationRequest> > &nextSteps)
+ValidatorRegex::checkPolicy(const Data& data,
+                            int stepCount,
+                            const OnDataValidated& onValidated,
+                            const OnDataValidationFailed& onValidationFailed,
+                            vector<shared_ptr<ValidationRequest> >& nextSteps)
 {
-  if(m_stepLimit == stepCount)
-    return onValidationFailed(data.shared_from_this(), 
-                              "Maximum steps of validation reached: " + data.getName().toUri());
+  if (m_stepLimit == stepCount)
+    return onValidationFailed(data.shared_from_this(),
+                              "Maximum steps of validation reached: " +
+                              data.getName().toUri());
 
-  RuleList::iterator it = m_mustFailVerify.begin();
-  for(; it != m_mustFailVerify.end(); it++)
-    if((*it)->satisfy(data))
+  for (RuleList::iterator it = m_mustFailVerify.begin();
+       it != m_mustFailVerify.end();
+       it++)
+    if ((*it)->satisfy(data))
       return onValidationFailed(data.shared_from_this(),
-                                "Comply with mustFail policy: " + data.getName().toUri());
+                                "Comply with mustFail policy: " +
+                                data.getName().toUri());
 
-  it = m_verifyPolicies.begin();
-  for(; it != m_verifyPolicies.end(); it++)
+  for (RuleList::iterator it = m_verifyPolicies.begin();
+       it != m_verifyPolicies.end();
+       it++)
     {
-      if((*it)->satisfy(data))
+      if ((*it)->satisfy(data))
         {
           try
             {
-              SignatureSha256WithRsa sig(data.getSignature());                
-            
+              SignatureSha256WithRsa sig(data.getSignature());
+
               Name keyLocatorName = sig.getKeyLocator().getName();
               shared_ptr<const Certificate> trustedCert;
-              if(m_trustAnchors.end() == m_trustAnchors.find(keyLocatorName))
+              if (m_trustAnchors.end() == m_trustAnchors.find(keyLocatorName))
                 trustedCert = m_certificateCache->getCertificate(keyLocatorName);
               else
                 trustedCert = m_trustAnchors[keyLocatorName];
-            
-              if(static_cast<bool>(trustedCert)){
-                if(verifySignature(data, sig, trustedCert->getPublicKeyInfo()))
-                  return onValidated(data.shared_from_this());
-                else
-                  return onValidationFailed(data.shared_from_this(), 
-                                            "Cannot verify signature: " + data.getName().toUri());
-              }
-              else{
-                // _LOG_DEBUG("KeyLocator is not trust anchor");                
-                OnDataValidated onKeyValidated = bind(&ValidatorRegex::onCertificateValidated, this, 
-                                                      _1, data.shared_from_this(), onValidated, onValidationFailed);
-              
-                OnDataValidationFailed onKeyValidationFailed = bind(&ValidatorRegex::onCertificateValidationFailed, this, 
-                                                                    _1, _2, data.shared_from_this(), onValidationFailed);              
 
-                shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(Interest(boost::cref(sig.getKeyLocator().getName())), 
-                                                                                        onKeyValidated,
-                                                                                        onKeyValidationFailed,
-                                                                                        3,
-                                                                                        stepCount + 1);
-                nextSteps.push_back(nextStep);
+              if (static_cast<bool>(trustedCert))
+                {
+                  if (verifySignature(data, sig, trustedCert->getPublicKeyInfo()))
+                    return onValidated(data.shared_from_this());
+                  else
+                    return onValidationFailed(data.shared_from_this(),
+                                              "Cannot verify signature: " +
+                                              data.getName().toUri());
+                }
+              else
+                {
+                  // _LOG_DEBUG("KeyLocator is not trust anchor");
+                  OnDataValidated onKeyValidated =
+                    bind(&ValidatorRegex::onCertificateValidated, this, _1,
+                         data.shared_from_this(), onValidated, onValidationFailed);
 
-                return;
-              }
+                  OnDataValidationFailed onKeyValidationFailed =
+                    bind(&ValidatorRegex::onCertificateValidationFailed, this, _1, _2,
+                         data.shared_from_this(), onValidationFailed);
+
+                  Interest interest(sig.getKeyLocator().getName());
+                  shared_ptr<ValidationRequest> nextStep =
+                    make_shared<ValidationRequest>(boost::cref(interest),
+                                                   onKeyValidated,
+                                                   onKeyValidationFailed,
+                                                   3,
+                                                   stepCount + 1);
+
+                  nextSteps.push_back(nextStep);
+
+                  return;
+                }
             }
-          catch(SignatureSha256WithRsa::Error &e)
-            {
-              return onValidationFailed(data.shared_from_this(), 
-                                        "Not SignatureSha256WithRsa signature: " + data.getName().toUri());
-            }
-          catch(KeyLocator::Error &e)
+          catch (const SignatureSha256WithRsa::Error& e)
             {
               return onValidationFailed(data.shared_from_this(),
-                                        "Key Locator is not a name: " + data.getName().toUri());
+                                        "Not SignatureSha256WithRsa signature: " +
+                                        data.getName().toUri());
+            }
+          catch (const KeyLocator::Error& e)
+            {
+              return onValidationFailed(data.shared_from_this(),
+                                        "Key Locator is not a name: " +
+                                        data.getName().toUri());
             }
         }
     }
 
-  return onValidationFailed(data.shared_from_this(), 
+  return onValidationFailed(data.shared_from_this(),
                             "No policy found for data: " + data.getName().toUri());
 }
 
diff --git a/src/security/validator-regex.hpp b/src/security/validator-regex.hpp
index 9caa380..1124620 100644
--- a/src/security/validator-regex.hpp
+++ b/src/security/validator-regex.hpp
@@ -19,61 +19,73 @@
 class ValidatorRegex : public Validator
 {
 public:
-  struct Error : public Validator::Error { Error(const std::string &what) : Validator::Error(what) {} };
+  class Error : public Validator::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : Validator::Error(what)
+    {
+    }
+  };
 
-  static const shared_ptr<CertificateCache> DefaultCertificateCache;
-  
+  static const shared_ptr<CertificateCache> DEFAULT_CERTIFICATE_CACHE;
+
   ValidatorRegex(shared_ptr<Face> face,
-                 shared_ptr<CertificateCache> certificateCache = DefaultCertificateCache, 
+                 shared_ptr<CertificateCache> certificateCache = DEFAULT_CERTIFICATE_CACHE,
                  const int stepLimit = 3);
-  
-  virtual 
-  ~ValidatorRegex() {}
-  
+
+  virtual
+  ~ValidatorRegex()
+  {
+  }
+
   /**
    * @brief Add a rule for data verification.
    *
    * @param policy The verification rule
    */
   inline void
-  addDataVerificationRule (shared_ptr<SecRuleRelative> rule);
-    
+  addDataVerificationRule(shared_ptr<SecRuleRelative> rule);
+
   /**
    * @brief Add a trust anchor
    *
-   * @param certificate The trust anchor 
+   * @param certificate The trust anchor
    */
-  inline void 
+  inline void
   addTrustAnchor(shared_ptr<IdentityCertificate> certificate);
 
 protected:
   virtual void
-  checkPolicy (const Data& data, 
-               int stepCount, 
-               const OnDataValidated &onValidated, 
-               const OnDataValidationFailed &onValidationFailed,
-               std::vector<shared_ptr<ValidationRequest> > &nextSteps);
+  checkPolicy(const Data& data,
+              int stepCount,
+              const OnDataValidated& onValidated,
+              const OnDataValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps);
 
   virtual void
-  checkPolicy (const Interest& interest, 
-               int stepCount, 
-               const OnInterestValidated &onValidated, 
-               const OnInterestValidationFailed &onValidationFailed,
-               std::vector<shared_ptr<ValidationRequest> > &nextSteps)
-  { onValidationFailed(interest.shared_from_this(), "No policy for signed interest checking"); }
+  checkPolicy(const Interest& interest,
+              int stepCount,
+              const OnInterestValidated& onValidated,
+              const OnInterestValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps)
+  {
+    onValidationFailed(interest.shared_from_this(), "No policy for signed interest checking");
+  }
 
   void
-  onCertificateValidated(const shared_ptr<const Data> &signCertificate, 
-                         const shared_ptr<const Data> &data, 
-                         const OnDataValidated &onValidated, 
-                         const OnDataValidationFailed &onValidationFailed);
-  
+  onCertificateValidated(const shared_ptr<const Data>& signCertificate,
+                         const shared_ptr<const Data>& data,
+                         const OnDataValidated& onValidated,
+                         const OnDataValidationFailed& onValidationFailed);
+
   void
-  onCertificateValidationFailed(const shared_ptr<const Data> &signCertificate,
+  onCertificateValidationFailed(const shared_ptr<const Data>& signCertificate,
                                 const std::string& failureInfo,
-                                const shared_ptr<const Data> &data, 
-                                const OnDataValidationFailed &onValidationFailed);
-  
+                                const shared_ptr<const Data>& data,
+                                const OnDataValidationFailed& onValidationFailed);
+
 protected:
   typedef std::vector< shared_ptr<SecRuleRelative> > RuleList;
   typedef std::vector< shared_ptr<Regex> > RegexList;
@@ -85,13 +97,17 @@
   std::map<Name, shared_ptr<IdentityCertificate> > m_trustAnchors;
 };
 
-inline void 
-ValidatorRegex::addDataVerificationRule (shared_ptr<SecRuleRelative> rule)
-{ rule->isPositive() ? m_verifyPolicies.push_back(rule) : m_mustFailVerify.push_back(rule); }
-      
-inline void  
+inline void
+ValidatorRegex::addDataVerificationRule(shared_ptr<SecRuleRelative> rule)
+{
+  rule->isPositive() ? m_verifyPolicies.push_back(rule) : m_mustFailVerify.push_back(rule);
+}
+
+inline void
 ValidatorRegex::addTrustAnchor(shared_ptr<IdentityCertificate> certificate)
-{ m_trustAnchors[certificate->getName().getPrefix(-1)] = certificate; }
+{
+  m_trustAnchors[certificate->getName().getPrefix(-1)] = certificate;
+}
 
 } // namespace ndn
 
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
index f1d8035..cb5be23 100644
--- a/src/security/validator.cpp
+++ b/src/security/validator.cpp
@@ -21,47 +21,49 @@
 
 namespace ndn {
 
-const shared_ptr<Face> Validator::DefaultFace = shared_ptr<Face>();
+const shared_ptr<Face> Validator::DEFAULT_FACE;
 
-Validator::Validator(shared_ptr<Face> face /* = DefaultFace */)                   
+Validator::Validator(shared_ptr<Face> face /* = DefaultFace */)
   : m_face(face)
-{}
+{
+}
 
 void
-Validator::validate(const Interest& interest, 
-                    const OnInterestValidated &onValidated, 
-                    const OnInterestValidationFailed &onValidationFailed,
+Validator::validate(const Interest& interest,
+                    const OnInterestValidated& onValidated,
+                    const OnInterestValidationFailed& onValidationFailed,
                     int stepCount)
 {
   vector<shared_ptr<ValidationRequest> > nextSteps;
   checkPolicy(interest, stepCount, onValidated, onValidationFailed, nextSteps);
-  
+
   if (!nextSteps.empty())
     {
-      if(!static_cast<bool>(m_face))
-        throw Error("Face should be set prior to verify method to call");
-      
+      if (!static_cast<bool>(m_face))
+        throw Error("Face should be set before calling validate method");
+
       vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
       OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
-      for(; it != nextSteps.end(); it++)
+      for (; it != nextSteps.end(); it++)
         m_face->expressInterest((*it)->m_interest,
-                                bind(&Validator::onData, this, _1, _2, *it), 
-                                bind(&Validator::onTimeout, 
-                                     this, _1, (*it)->m_retry, 
-                                     onFailure, 
+                                bind(&Validator::onData, this, _1, _2, *it),
+                                bind(&Validator::onTimeout,
+                                     this, _1, (*it)->m_retry,
+                                     onFailure,
                                      *it));
     }
   else
     {
-      //If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
-      //No more further processes.
+      // If there is no nextStep,
+      // that means InterestPolicy has already been able to verify the Interest.
+      // No more further processes.
     }
 }
 
 void
-Validator::validate(const Data& data, 
-                    const OnDataValidated &onValidated, 
-                    const OnDataValidationFailed &onValidationFailed,
+Validator::validate(const Data& data,
+                    const OnDataValidated& onValidated,
+                    const OnDataValidationFailed& onValidationFailed,
                     int stepCount)
 {
   vector<shared_ptr<ValidationRequest> > nextSteps;
@@ -69,44 +71,45 @@
 
   if (!nextSteps.empty())
     {
-      if(!static_cast<bool>(m_face))
+      if (!static_cast<bool>(m_face))
         throw Error("Face should be set prior to verify method to call");
 
       vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
       OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
-      for(; it != nextSteps.end(); it++)
+      for (; it != nextSteps.end(); it++)
         m_face->expressInterest((*it)->m_interest,
-                                bind(&Validator::onData, this, _1, _2, *it), 
-                                bind(&Validator::onTimeout, 
-                                     this, _1, (*it)->m_retry, 
+                                bind(&Validator::onData, this, _1, _2, *it),
+                                bind(&Validator::onTimeout,
+                                     this, _1, (*it)->m_retry,
                                      onFailure,
                                      *it));
     }
   else
     {
-      //If there is no nextStep, that means InterestPolicy has already been able to verify the Interest.
-      //No more further processes.
+      // If there is no nextStep,
+      // that means Data Policy has already been able to verify the Interest.
+      // No more further processes.
     }
 }
 
 void
-Validator::onData(const Interest& interest, 
-                  Data& data, 
+Validator::onData(const Interest& interest,
+                  const Data& data,
                   const shared_ptr<ValidationRequest>& nextStep)
 {
   validate(data, nextStep->m_onValidated, nextStep->m_onDataValidated, nextStep->m_stepCount);
 }
 
 void
-Validator::onTimeout(const Interest& interest, 
-                     int retry, 
-                     const OnFailure &onFailure, 
+Validator::onTimeout(const Interest& interest,
+                     int retry,
+                     const OnFailure& onFailure,
                      const shared_ptr<ValidationRequest>& nextStep)
 {
   if (retry > 0)
     // Issue the same expressInterest except decrement retry.
-    m_face->expressInterest(interest, 
-                            bind(&Validator::onData, this, _1, _2, nextStep), 
+    m_face->expressInterest(interest,
+                            bind(&Validator::onData, this, _1, _2, nextStep),
                             bind(&Validator::onTimeout, this, _1, retry - 1, onFailure, nextStep));
   else
     onFailure("Cannot fetch cert: " + interest.getName().toUri());
@@ -117,20 +120,21 @@
 {
   try
     {
-      switch(data.getSignature().getType()){
-      case Signature::Sha256WithRsa:
+      switch (data.getSignature().getType())
         {
-          SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
-          return verifySignature(data, sigSha256Rsa, key);
+        case Signature::Sha256WithRsa:
+          {
+            SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
+            return verifySignature(data, sigSha256Rsa, key);
+          }
+        default:
+          {
+            _LOG_DEBUG("verifySignature: Unknown signature type: " << data.getSignature().getType());
+            return false;
+          }
         }
-      default:
-        {
-          _LOG_DEBUG("verifySignature: Unknown signature type: " << data.getSignature().getType());
-          return false;
-        }
-      }
     }
-  catch(Signature::Error &e)
+  catch (const Signature::Error& e)
     {
       _LOG_DEBUG("verifySignature: " << e.what());
       return false;
@@ -141,40 +145,41 @@
 bool
 Validator::verifySignature(const Interest& interest, const PublicKey& key)
 {
-  const Name &interestName = interest.getName();
+  const Name& interestName = interest.getName();
 
-  if(interestName.size() < 2)
+  if (interestName.size() < 2)
     return false;
 
   try
     {
       const Block& nameBlock = interestName.wireEncode();
 
-      Signature sig(interestName[-2].blockFromValue(), 
+      Signature sig(interestName[-2].blockFromValue(),
                     interestName[-1].blockFromValue());
 
-      switch(sig.getType()){
-      case Signature::Sha256WithRsa:
+      switch (sig.getType())
         {
-          SignatureSha256WithRsa sigSha256Rsa(sig);
+        case Signature::Sha256WithRsa:
+          {
+            SignatureSha256WithRsa sigSha256Rsa(sig);
 
-          return verifySignature(nameBlock.value(), 
-                                 nameBlock.value_size() - interestName[-1].size(), 
-                                 sigSha256Rsa, key);
+            return verifySignature(nameBlock.value(),
+                                   nameBlock.value_size() - interestName[-1].size(),
+                                   sigSha256Rsa, key);
+          }
+        default:
+          {
+            _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
+            return false;
+          }
         }
-      default:
-        {
-          _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
-          return false;
-        }
-      }
     }
-  catch(Signature::Error &e)
+  catch (const Signature::Error& e)
     {
       _LOG_DEBUG("verifySignature: " << e.what());
       return false;
     }
-  catch(Block::Error &e)
+  catch (const Block::Error& e)
     {
       _LOG_DEBUG("verifySignature: " << e.what());
       return false;
@@ -187,20 +192,21 @@
 {
   try
     {
-      switch(sig.getType()){
-      case Signature::Sha256WithRsa:
+      switch (sig.getType())
         {
-          SignatureSha256WithRsa sigSha256Rsa(sig);
-          return verifySignature(data, sigSha256Rsa, key);
+        case Signature::Sha256WithRsa:
+          {
+            SignatureSha256WithRsa sigSha256Rsa(sig);
+            return verifySignature(data, sigSha256Rsa, key);
+          }
+        default:
+          {
+            _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
+            return false;
+          }
         }
-      default:
-        {
-          _LOG_DEBUG("verifySignature: Unknown signature type: " << sig.getType());
-          return false;
-        }
-      }
     }
-  catch(Signature::Error &e)
+  catch (const Signature::Error& e)
     {
       _LOG_DEBUG("verifySignature: " << e.what());
       return false;
@@ -209,7 +215,10 @@
 }
 
 bool
-Validator::verifySignature(const uint8_t* buf, const size_t size, const SignatureSha256WithRsa& sig, const PublicKey& key)
+Validator::verifySignature(const uint8_t* buf,
+                           const size_t size,
+                           const SignatureSha256WithRsa& sig,
+                           const PublicKey& key)
 {
   try
     {
@@ -221,10 +230,12 @@
       queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
       publicKey.Load(queue);
 
-      RSASS<PKCS1v15, SHA256>::Verifier verifier (publicKey);
-      return verifier.VerifyMessage(buf, size, sig.getValue().value(), sig.getValue().value_size());
+      RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
+      return verifier.VerifyMessage(buf, size,
+                                    sig.getValue().value(),
+                                    sig.getValue().value_size());
     }
-  catch(CryptoPP::Exception& e)
+  catch (const CryptoPP::Exception& e)
     {
       _LOG_DEBUG("verifySignature: " << e.what());
       return false;
@@ -239,23 +250,20 @@
       ConstBufferPtr buffer = crypto::sha256(buf, size);
       const Block& sigValue = sig.getValue();
 
-      if(static_cast<bool>(buffer) 
-         && buffer->size() == sigValue.value_size()
-         && buffer->size() == crypto::SHA256_DIGEST_SIZE)
+      if (static_cast<bool>(buffer) &&
+          buffer->size() == sigValue.value_size() &&
+          buffer->size() == crypto::SHA256_DIGEST_SIZE)
         {
 
           const uint8_t* p1 = buffer->buf();
           const uint8_t* p2 = sigValue.value();
 
-          for(size_t i = 0; i < crypto::SHA256_DIGEST_SIZE; i++)
-            if(p1[i] != p2[i]) 
-              return false;
-          return true;
+          return 0 == memcmp(p1, p2, crypto::SHA256_DIGEST_SIZE);
         }
       else
         return false;
     }
-  catch(CryptoPP::Exception& e)
+  catch (const CryptoPP::Exception& e)
     {
       _LOG_DEBUG("verifySignature: " << e.what());
       return false;
diff --git a/src/security/validator.hpp b/src/security/validator.hpp
index 5147dd7..2b55782 100644
--- a/src/security/validator.hpp
+++ b/src/security/validator.hpp
@@ -20,39 +20,56 @@
 
 namespace ndn {
 /**
- * Validator is one of the main classes of the security library.
+ * @brief Validator is one of the main classes of the security library.
  *
  * The Validator class provides the interfaces for packet validation.
  */
 class Validator {
 public:
-  struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
 
-  static const shared_ptr<Face> DefaultFace;
+  static const shared_ptr<Face> DEFAULT_FACE;
 
-  Validator (shared_ptr<Face> face = DefaultFace);
+  explicit
+  Validator(shared_ptr<Face> face = DEFAULT_FACE);
 
   /**
-   * @brief Validate Data and call either onValidated or onValidationFailed. 
-   * 
+   * @brief Validate Data and call either onValidated or onValidationFailed.
+   *
    * @param data The Data with the signature to check.
    * @param onValidated If the Data is validated, this calls onValidated(data).
    * @param onValidationFailed If the Data validation fails, this calls onValidationFailed(data).
    */
   void
-  validate (const Data& data, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed)
-  { validate (data, onValidated, onValidationFailed, 0); }
+  validate(const Data& data,
+           const OnDataValidated& onValidated,
+           const OnDataValidationFailed& onValidationFailed)
+  {
+    validate(data, onValidated, onValidationFailed, 0);
+  }
 
   /**
-   * @brief Validate Interest and call either onValidated or onValidationFailed. 
-   * 
+   * @brief Validate Interest and call either onValidated or onValidationFailed.
+   *
    * @param interest The Interest with the signature to check.
    * @param onValidated If the Interest is validated, this calls onValidated(interest).
    * @param onValidationFailed If the Interest validation fails, this calls onValidationFailed(interest).
    */
   void
-  validate (const Interest& interest, const OnInterestValidated &onValidated, const OnInterestValidationFailed &onValidationFailed)
-  { validate (interest, onValidated, onValidationFailed, 0); }
+  validate(const Interest& interest,
+           const OnInterestValidated& onValidated,
+           const OnInterestValidationFailed& onValidationFailed)
+  {
+    validate(interest, onValidated, onValidationFailed, 0);
+  }
 
   /*****************************************
    *      verifySignature method set       *
@@ -60,53 +77,109 @@
 
   /// @brief Verify the data using the publicKey.
   static bool
-  verifySignature (const Data& data, const PublicKey& publicKey);
+  verifySignature(const Data& data, const PublicKey& publicKey);
 
-  /// @brief Verify the signed Interest using the publicKey.
+  /**
+   * @brief Verify the signed Interest using the publicKey.
+   *
+   * (Note the signature covers the first n-2 name components).
+   */
   static bool
-  verifySignature (const Interest& interest, const PublicKey& publicKey);
+  verifySignature(const Interest& interest, const PublicKey& publicKey);
 
   /// @brief Verify the blob using the publicKey against the signature.
   static bool
-  verifySignature (const Buffer& blob, const Signature& sig, const PublicKey& publicKey);
+  verifySignature(const Buffer& blob, const Signature& sig, const PublicKey& publicKey);
 
   /// @brief Verify the data using the publicKey against the SHA256-RSA signature.
   static bool
-  verifySignature (const Data& data, const SignatureSha256WithRsa& sig, const PublicKey& publicKey)
-  { return verifySignature (data.wireEncode().value(), 
-                            data.wireEncode().value_size() - data.getSignature().getValue().size(), 
-                            sig, publicKey); }
+  verifySignature(const Data& data,
+                  const SignatureSha256WithRsa& sig,
+                  const PublicKey& publicKey)
+  {
+    return verifySignature(data.wireEncode().value(),
+                           data.wireEncode().value_size() - data.getSignature().getValue().size(),
+                           sig, publicKey);
+  }
+
+  /** @brief Verify the interest using the publicKey against the SHA256-RSA signature.
+   *
+   * (Note the signature covers the first n-2 name components).
+   */
+  static bool
+  verifySignature(const Interest& interest,
+                  const SignatureSha256WithRsa& sig,
+                  const PublicKey& publicKey)
+  {
+    if (interest.getName().size() < 2)
+      return false;
+
+    Name signedName = interest.getName().getPrefix(-2);
+
+    return verifySignature(signedName.wireEncode().value(),
+                           signedName.wireEncode().value_size(),
+                           sig, publicKey);
+  }
 
   /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
   static bool
-  verifySignature (const Buffer& blob, const SignatureSha256WithRsa& sig, const PublicKey& publicKey)
-  { return verifySignature (blob.buf(), blob.size(), sig, publicKey); }
-  
+  verifySignature(const Buffer& blob,
+                  const SignatureSha256WithRsa& sig,
+                  const PublicKey& publicKey)
+  {
+    return verifySignature(blob.buf(), blob.size(), sig, publicKey);
+  }
+
   /// @brief Verify the blob using the publicKey against the SHA256-RSA signature.
   static bool
-  verifySignature (const uint8_t* buf, const size_t size, const SignatureSha256WithRsa &sig, const PublicKey &publicKey);
+  verifySignature(const uint8_t* buf,
+                  const size_t size,
+                  const SignatureSha256WithRsa& sig,
+                  const PublicKey& publicKey);
 
 
   /// @brief Verify the data against the SHA256 signature.
   static bool
-  verifySignature (const Data& data, const SignatureSha256& sig)
-  { return verifySignature (data.wireEncode().value(), 
-                            data.wireEncode().value_size() - data.getSignature().getValue().size(), 
-                            sig); }
+  verifySignature(const Data& data, const SignatureSha256& sig)
+  {
+    return verifySignature(data.wireEncode().value(),
+                           data.wireEncode().value_size() -
+                           data.getSignature().getValue().size(),
+                           sig);
+  }
+
+  /** @brief Verify the interest against the SHA256 signature.
+   *
+   * (Note the signature covers the first n-2 name components).
+   */
+  static bool
+  verifySignature(const Interest& interest, const SignatureSha256& sig)
+  {
+    if (interest.getName().size() < 2)
+      return false;
+
+    Name signedName = interest.getName().getPrefix(-2);
+
+    return verifySignature(signedName.wireEncode().value(),
+                           signedName.wireEncode().value_size(),
+                           sig);
+  }
 
   /// @brief Verify the blob against the SHA256 signature.
   static bool
-  verifySignature (const Buffer& blob, const SignatureSha256& sig)
-  { return verifySignature (blob.buf(), blob.size(), sig); }
-  
+  verifySignature(const Buffer& blob, const SignatureSha256& sig)
+  {
+    return verifySignature (blob.buf(), blob.size(), sig);
+  }
+
   /// @brief Verify the blob against the SHA256 signature.
   static bool
-  verifySignature (const uint8_t* buf, const size_t size, const SignatureSha256& sig);
+  verifySignature(const uint8_t* buf, const size_t size, const SignatureSha256& sig);
 
 
 protected:
   /**
-   * @brief Check the Data against validation policy and return the next validation step if necessary.
+   * @brief Check the Data against policy and return the next validation step if necessary.
    *
    * If there is no next validation step, that validation MUST have been done.
    * i.e., either onValidated or onValidationFailed callback is invoked.
@@ -118,11 +191,11 @@
    * @param nextSteps On return, contains the next validation step.
    */
   virtual void
-  checkPolicy (const Data& data, 
-               int stepCount, 
-               const OnDataValidated &onValidated, 
-               const OnDataValidationFailed &onValidationFailed,
-               std::vector<shared_ptr<ValidationRequest> > &nextSteps) = 0;
+  checkPolicy(const Data& data,
+              int stepCount,
+              const OnDataValidated& onValidated,
+              const OnDataValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
 
   /**
    * @brief Check the Interest against validation policy and return the next validation step if necessary.
@@ -137,39 +210,39 @@
    * @return the indication of next validation step, null if there is no further step.
    */
   virtual void
-  checkPolicy (const Interest& interest, 
-               int stepCount, 
-               const OnInterestValidated &onValidated, 
-               const OnInterestValidationFailed &onValidationFailed,
-               std::vector<shared_ptr<ValidationRequest> > &nextSteps) = 0;
+  checkPolicy(const Interest& interest,
+              int stepCount,
+              const OnInterestValidated& onValidated,
+              const OnInterestValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps) = 0;
 
 private:
   typedef function< void (const std::string&) > OnFailure;
-  
+
   /// @brief Process the received certificate.
   void
-  onData (const Interest& interest, 
-          Data& data, 
-          const shared_ptr<ValidationRequest>& nextStep);
-  
+  onData(const Interest& interest,
+         const Data& data,
+         const shared_ptr<ValidationRequest>& nextStep);
+
   /// @brief Re-express the interest if it times out.
   void
-  onTimeout (const Interest& interest, 
-             int retry, 
-             const OnFailure &onFailure, 
-             const shared_ptr<ValidationRequest>& nextStep);
+  onTimeout(const Interest& interest,
+            int retry,
+            const OnFailure& onFailure,
+            const shared_ptr<ValidationRequest>& nextStep);
 
   void
-  validate (const Data& data, 
-            const OnDataValidated &onValidated, 
-            const OnDataValidationFailed &onValidationFailed, 
-            int stepCount);
+  validate(const Data& data,
+           const OnDataValidated& onValidated,
+           const OnDataValidationFailed& onValidationFailed,
+           int stepCount);
 
   void
-  validate (const Interest& interest, 
-            const OnInterestValidated &onValidated, 
-            const OnInterestValidationFailed &onValidationFailed, 
-            int stepCount);
+  validate(const Interest& interest,
+           const OnInterestValidated& onValidated,
+           const OnInterestValidationFailed& onValidationFailed,
+           int stepCount);
 
 protected:
   shared_ptr<Face> m_face;
diff --git a/src/util/command-interest-validator.hpp b/src/util/command-interest-validator.hpp
index 257f476..ca65f27 100644
--- a/src/util/command-interest-validator.hpp
+++ b/src/util/command-interest-validator.hpp
@@ -4,8 +4,8 @@
  * See COPYING for copyright and distribution information.
  */
 
-#ifndef NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
-#define NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
+#ifndef NDN_UTIL_COMMAND_INTEREST_VALIDATOR_HPP
+#define NDN_UTIL_COMMAND_INTEREST_VALIDATOR_HPP
 
 #include "../security/validator.hpp"
 #include "../security/identity-certificate.hpp"
@@ -25,7 +25,8 @@
     GRACE_INTERVAL = 3000 // ms
   };
 
-  CommandInterestValidator(const time::milliseconds& graceInterval = time::milliseconds(static_cast<int>(GRACE_INTERVAL)))
+  CommandInterestValidator(const time::milliseconds& graceInterval =
+                           time::milliseconds(static_cast<int>(GRACE_INTERVAL)))
     : m_graceInterval(graceInterval < time::milliseconds::zero() ?
                       time::milliseconds(static_cast<int>(GRACE_INTERVAL)) : graceInterval)
   {
@@ -44,21 +45,21 @@
 
 protected:
   virtual void
-  checkPolicy (const Data& data,
-               int stepCount,
-               const OnDataValidated &onValidated,
-               const OnDataValidationFailed &onValidationFailed,
-               std::vector<shared_ptr<ValidationRequest> > &nextSteps)
+  checkPolicy(const Data& data,
+              int stepCount,
+              const OnDataValidated& onValidated,
+              const OnDataValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps)
   {
     onValidationFailed(data.shared_from_this(), "No policy for data checking");
   }
 
   virtual void
-  checkPolicy (const Interest& interest,
-               int stepCount,
-               const OnInterestValidated &onValidated,
-               const OnInterestValidationFailed &onValidationFailed,
-               std::vector<shared_ptr<ValidationRequest> > &nextSteps);
+  checkPolicy(const Interest& interest,
+              int stepCount,
+              const OnInterestValidated& onValidated,
+              const OnInterestValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps);
 private:
   time::milliseconds m_graceInterval; //ms
   std::map<Name, PublicKey> m_trustAnchorsForInterest;
@@ -69,14 +70,17 @@
 };
 
 inline void
-CommandInterestValidator::addInterestRule(const std::string& regex, const IdentityCertificate& certificate)
+CommandInterestValidator::addInterestRule(const std::string& regex,
+                                          const IdentityCertificate& certificate)
 {
   Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificate.getName());
   addInterestRule(regex, keyName, certificate.getPublicKeyInfo());
 }
 
 inline void
-CommandInterestValidator::addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey)
+CommandInterestValidator::addInterestRule(const std::string& regex,
+                                          const Name& keyName,
+                                          const PublicKey& publicKey)
 {
   m_trustAnchorsForInterest[keyName] = publicKey;
   shared_ptr<Regex> interestRegex = make_shared<Regex>(regex);
@@ -85,11 +89,11 @@
 }
 
 inline void
-CommandInterestValidator::checkPolicy (const Interest& interest,
-                                       int stepCount,
-                                       const OnInterestValidated &onValidated,
-                                       const OnInterestValidationFailed &onValidationFailed,
-                                       std::vector<shared_ptr<ValidationRequest> > &nextSteps)
+CommandInterestValidator::checkPolicy(const Interest& interest,
+                                      int stepCount,
+                                      const OnInterestValidated& onValidated,
+                                      const OnInterestValidationFailed& onValidationFailed,
+                                      std::vector<shared_ptr<ValidationRequest> >& nextSteps)
 {
   const Name& interestName = interest.getName();
 
@@ -106,24 +110,26 @@
   Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
 
   //Check if command is in the trusted scope
-  bool inScope = false;
-  for(std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
+  bool isInScope = false;
+  for (std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
       scopeIt != m_trustScopeForInterest.end();
       ++scopeIt)
     {
-      if(scopeIt->satisfy(interestName, keyName))
+      if (scopeIt->satisfy(interestName, keyName))
         {
-          inScope = true;
+          isInScope = true;
           break;
         }
     }
-  if(inScope == false)
+
+  if (isInScope == false)
     return onValidationFailed(interest.shared_from_this(),
                               "Signer cannot be authorized for the command: " + keyName.toUri());
 
   //Check if timestamp is valid
-  time::system_clock::TimePoint interestTime = time::fromUnixTimestamp(
-                                           time::milliseconds(interestName.get(POS_TIMESTAMP).toNumber()));
+  time::system_clock::TimePoint interestTime =
+    time::fromUnixTimestamp(time::milliseconds(interestName.get(POS_TIMESTAMP).toNumber()));
+
   time::system_clock::TimePoint currentTime = time::system_clock::now();
 
   LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
@@ -133,7 +139,8 @@
             interestTime <= currentTime + m_graceInterval))
         {
           return onValidationFailed(interest.shared_from_this(),
-                                    "The command is not in grace interval: " + interest.getName().toUri());
+                                    "The command is not in grace interval: " +
+                                    interest.getName().toUri());
         }
     }
   else
@@ -144,9 +151,10 @@
     }
 
   //Check signature
-  if(!Validator::verifySignature(interestName.wireEncode().value(),
-                                 interestName.wireEncode().value_size() - interestName[-1].size(),
-                                 sig, m_trustAnchorsForInterest[keyName]))
+  if (!Validator::verifySignature(interestName.wireEncode().value(),
+                                  interestName.wireEncode().value_size() -
+                                  interestName[-1].size(),
+                                  sig, m_trustAnchorsForInterest[keyName]))
     return onValidationFailed(interest.shared_from_this(),
                               "Signature cannot be validated: " + interest.getName().toUri());
 
@@ -165,4 +173,4 @@
 
 } // namespace ndn
 
-#endif // NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
+#endif // NDN_UTIL_COMMAND_INTEREST_VALIDATOR_HPP
diff --git a/src/util/regex/regex-top-matcher.hpp b/src/util/regex/regex-top-matcher.hpp
index 4d9c01e..f5b30c1 100644
--- a/src/util/regex/regex-top-matcher.hpp
+++ b/src/util/regex/regex-top-matcher.hpp
@@ -20,25 +20,25 @@
 class RegexTopMatcher: public RegexMatcher
 {
 public:
-  RegexTopMatcher(const std::string & expr, const std::string& expand = "");
-    
+  RegexTopMatcher(const std::string& expr, const std::string& expand = "");
+
   virtual
   ~RegexTopMatcher();
 
-  bool 
+  bool
   match(const Name& name);
 
   virtual bool
-  match (const Name& name, const int& offset, const int& len);
+  match(const Name& name, const int& offset, const int& length);
 
-  virtual Name 
-  expand (const std::string& expand = "");
+  virtual Name
+  expand(const std::string& expand = "");
 
   static shared_ptr<RegexTopMatcher>
   fromName(const Name& name, bool hasAnchor=false);
 
 protected:
-  virtual void 
+  virtual void
   compile();
 
 private:
diff --git a/tests-integrated/security/test-validator-config.cpp b/tests-integrated/security/test-validator-config.cpp
new file mode 100644
index 0000000..0e778db
--- /dev/null
+++ b/tests-integrated/security/test-validator-config.cpp
@@ -0,0 +1,848 @@
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi0@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "security/validator-config.hpp"
+
+#include <boost/test/unit_test.hpp>
+
+#include "security/key-chain.hpp"
+#include "util/io.hpp"
+
+
+using namespace std;
+
+namespace ndn {
+
+BOOST_AUTO_TEST_SUITE(TestValidatorConfig)
+
+void
+onValidated(const shared_ptr<const Data>& data)
+{
+  BOOST_CHECK(true);
+}
+
+void
+onValidationFailed(const shared_ptr<const Data>& data, const string& failureInfo)
+{
+  std::cerr << "Failure Info: " << failureInfo << std::endl;
+  BOOST_CHECK(false);
+}
+
+void
+onIntentionalFailureValidated(const shared_ptr<const Data>& data)
+{
+  BOOST_CHECK(false);
+}
+
+void
+onIntentionalFailureInvalidated(const shared_ptr<const Data>& data, const string& failureInfo)
+{
+  BOOST_CHECK(true);
+}
+
+void
+onValidated2(const shared_ptr<const Interest>& interest)
+{
+  BOOST_CHECK(true);
+}
+
+void
+onValidationFailed2(const shared_ptr<const Interest>& interest, const string& failureInfo)
+{
+  std::cerr << "Interest Name: " << interest->getName() << std::endl;
+  std::cerr << "Failure Info: " << failureInfo << std::endl;
+  BOOST_CHECK(false);
+}
+
+void
+onIntentionalFailureValidated2(const shared_ptr<const Interest>& interest)
+{
+  BOOST_CHECK(false);
+}
+
+void
+onIntentionalFailureInvalidated2(const shared_ptr<const Interest>& interest,
+                                 const string& failureInfo)
+{
+  BOOST_CHECK(true);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter)
+{
+  KeyChain keyChain;
+
+  Name identity("/TestValidatorConfig/NameFilter");
+  identity.appendVersion();
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+  Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+  shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+  io::save(*idCert, "trust-anchor-1.cert");
+
+  Name dataName1("/simple/equal");
+  shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+  Name dataName2("/simple/different");
+  shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+  std::string CONFIG_1 =
+    "rule\n"
+    "{\n"
+    "  id \"Simple Rule\"\n"
+    "  for data\n"
+    "  filter"
+    "  {\n"
+    "    type name\n"
+    "    name /simple/equal\n"
+    "    relation equal\n"
+    "  }\n"
+    "  checker\n"
+    "  {\n"
+    "    type customized\n"
+    "    sig-type rsa-sha256\n"
+    "    key-locator\n"
+    "    {\n"
+    "      type name\n"
+    "      name ";
+
+  std::string CONFIG_2 =
+    "\n"
+    "      relation equal\n"
+    "    }\n"
+    "  }\n"
+    "}\n"
+    "trust-anchor\n"
+    "{\n"
+    "  type file\n"
+    "  file-name \"trust-anchor-1.cert\"\n"
+    "}\n";
+  const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
+
+  const boost::filesystem::path CONFIG_PATH =
+    (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+  shared_ptr<Face> face = make_shared<Face>();
+  ValidatorConfig validator(face);
+  validator.load(CONFIG, CONFIG_PATH.native());
+
+  validator.validate(*data1,
+                     bind(&onValidated, _1),
+                     bind(&onValidationFailed, _1, _2));
+
+  validator.validate(*data2,
+                     bind(&onIntentionalFailureValidated, _1),
+                     bind(&onIntentionalFailureInvalidated, _1, _2));
+
+  keyChain.deleteIdentity(identity);
+
+  const boost::filesystem::path CERT_PATH =
+    (boost::filesystem::current_path() / std::string("trust-anchor-1.cert"));
+  boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter2)
+{
+  KeyChain keyChain;
+
+  Name identity("/TestValidatorConfig/NameFilter2");
+  identity.appendVersion();
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+  Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+  shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+  io::save(*idCert, "trust-anchor-2.cert");
+
+  Name dataName1("/simple/isPrefixOf");
+  shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+  Name dataName2("/simple/notPrefixOf");
+  shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+  Name dataName3("/simple/isPrefixOf/anotherLevel");
+  shared_ptr<Data> data3 = make_shared<Data>(dataName3);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data3, identity));
+
+  std::string CONFIG_1 =
+    "rule\n"
+    "{\n"
+    "  id \"Simple2 Rule\"\n"
+    "  for data\n"
+    "  filter"
+    "  {\n"
+    "    type name\n"
+    "    name /simple/isPrefixOf\n"
+    "    relation is-prefix-of\n"
+    "  }\n"
+    "  checker\n"
+    "  {\n"
+    "    type customized\n"
+    "    sig-type rsa-sha256\n"
+    "    key-locator\n"
+    "    {\n"
+    "      type name\n"
+    "      name ";
+
+  std::string CONFIG_2 =
+    "\n"
+    "      relation equal\n"
+    "    }\n"
+    "  }\n"
+    "}\n"
+    "trust-anchor\n"
+    "{\n"
+    "  type file\n"
+    "  file-name \"trust-anchor-2.cert\"\n"
+    "}\n";
+  const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
+
+  const boost::filesystem::path CONFIG_PATH =
+    (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+  shared_ptr<Face> face = make_shared<Face>();
+  ValidatorConfig validator(face);
+  validator.load(CONFIG, CONFIG_PATH.native());
+
+  validator.validate(*data1,
+                     bind(&onValidated, _1),
+                     bind(&onValidationFailed, _1, _2));
+
+  validator.validate(*data2,
+                     bind(&onIntentionalFailureValidated, _1),
+                     bind(&onIntentionalFailureInvalidated, _1, _2));
+
+  validator.validate(*data3,
+                     bind(&onValidated, _1),
+                     bind(&onValidationFailed, _1, _2));
+
+  keyChain.deleteIdentity(identity);
+
+  const boost::filesystem::path CERT_PATH =
+    (boost::filesystem::current_path() / std::string("trust-anchor-2.cert"));
+  boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter3)
+{
+  KeyChain keyChain;
+
+  Name identity("/TestValidatorConfig/NameFilter3");
+  identity.appendVersion();
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+  Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+  shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+  io::save(*idCert, "trust-anchor-3.cert");
+
+  Name dataName1("/simple/isStrictPrefixOf");
+  shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+  Name dataName2("/simple");
+  shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+  Name dataName3("/simple/isStrictPrefixOf/anotherLevel");
+  shared_ptr<Data> data3 = make_shared<Data>(dataName3);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data3, identity));
+
+  std::string CONFIG_1 =
+    "rule\n"
+    "{\n"
+    "  id \"Simple3 Rule\"\n"
+    "  for data\n"
+    "  filter"
+    "  {\n"
+    "    type name\n"
+    "    name /simple/isStrictPrefixOf\n"
+    "    relation is-strict-prefix-of\n"
+    "  }\n"
+    "  checker\n"
+    "  {\n"
+    "    type customized\n"
+    "    sig-type rsa-sha256\n"
+    "    key-locator\n"
+    "    {\n"
+    "      type name\n"
+    "      name ";
+
+  std::string CONFIG_2 =
+    "\n"
+    "      relation equal\n"
+    "    }\n"
+    "  }\n"
+    "}\n"
+    "trust-anchor\n"
+    "{\n"
+    "  type file\n"
+    "  file-name \"trust-anchor-3.cert\"\n"
+    "}\n";
+  const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
+
+  const boost::filesystem::path CONFIG_PATH =
+    (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+  shared_ptr<Face> face = make_shared<Face>();
+  ValidatorConfig validator(face);
+  validator.load(CONFIG, CONFIG_PATH.native());
+
+  validator.validate(*data1,
+                     bind(&onIntentionalFailureValidated, _1),
+                     bind(&onIntentionalFailureInvalidated, _1, _2));
+
+  validator.validate(*data2,
+                     bind(&onIntentionalFailureValidated, _1),
+                     bind(&onIntentionalFailureInvalidated, _1, _2));
+
+  validator.validate(*data3,
+                     bind(&onValidated, _1),
+                     bind(&onValidationFailed, _1, _2));
+
+  keyChain.deleteIdentity(identity);
+
+  const boost::filesystem::path CERT_PATH =
+    (boost::filesystem::current_path() / std::string("trust-anchor-3.cert"));
+  boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter4)
+{
+  KeyChain keyChain;
+
+  Name identity("/TestValidatorConfig/NameFilter4");
+  identity.appendVersion();
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+  Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+  shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+  io::save(*idCert, "trust-anchor-4.cert");
+
+  Name dataName1("/simple/regex");
+  shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+  Name dataName2("/simple/regex-wrong");
+  shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+  Name dataName3("/simple/regex/correct");
+  shared_ptr<Data> data3 = make_shared<Data>(dataName3);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data3, identity));
+
+  std::string CONFIG_1 =
+    "rule\n"
+    "{\n"
+    "  id \"Simple3 Rule\"\n"
+    "  for data\n"
+    "  filter"
+    "  {\n"
+    "    type name\n"
+    "    regex ^<simple><regex>\n"
+    "  }\n"
+    "  checker\n"
+    "  {\n"
+    "    type customized\n"
+    "    sig-type rsa-sha256\n"
+    "    key-locator\n"
+    "    {\n"
+    "      type name\n"
+    "      name ";
+
+  std::string CONFIG_2 =
+    "\n"
+    "      relation equal\n"
+    "    }\n"
+    "  }\n"
+    "}\n"
+    "trust-anchor\n"
+    "{\n"
+    "  type file\n"
+    "  file-name \"trust-anchor-4.cert\"\n"
+    "}\n";
+  const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
+
+  const boost::filesystem::path CONFIG_PATH =
+    (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+  shared_ptr<Face> face = make_shared<Face>();
+  ValidatorConfig validator(face);
+  validator.load(CONFIG, CONFIG_PATH.native());
+
+  validator.validate(*data1,
+                     bind(&onValidated, _1),
+                     bind(&onValidationFailed, _1, _2));
+
+  validator.validate(*data2,
+                     bind(&onIntentionalFailureValidated, _1),
+                     bind(&onIntentionalFailureInvalidated, _1, _2));
+
+  validator.validate(*data3,
+                     bind(&onValidated, _1),
+                     bind(&onValidationFailed, _1, _2));
+
+  keyChain.deleteIdentity(identity);
+
+  const boost::filesystem::path CERT_PATH =
+    (boost::filesystem::current_path() / std::string("trust-anchor-4.cert"));
+  boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(KeyLocatorNameChecker1)
+{
+  KeyChain keyChain;
+
+  Name identity("/TestValidatorConfig/KeyLocatorNameChecker1");
+  identity.appendVersion();
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity));
+  Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
+  shared_ptr<IdentityCertificate> idCert = keyChain.getCertificate(certName);
+  io::save(*idCert, "trust-anchor-5.cert");
+
+  Name dataName1 = identity;
+  dataName1.append("1");
+  shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity));
+
+  Name dataName2 = identity;
+  shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity));
+
+  Name dataName3("/TestValidatorConfig/KeyLocatorNameChecker1");
+  shared_ptr<Data> data3 = make_shared<Data>(dataName3);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data3, identity));
+
+  const std::string CONFIG =
+    "rule\n"
+    "{\n"
+    "  id \"Simple3 Rule\"\n"
+    "  for data\n"
+    "  checker\n"
+    "  {\n"
+    "    type customized\n"
+    "    sig-type rsa-sha256\n"
+    "    key-locator\n"
+    "    {\n"
+    "      type name\n"
+    "      hyper-relation\n"
+    "      {\n"
+    "        k-regex ^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$\n"
+    "        k-expand \\\\1\\\\2\n"
+    "        h-relation is-strict-prefix-of\n"
+    "        p-regex ^(<>*)$\n"
+    "        p-expand \\\\1\n"
+    "      }\n"
+    "    }\n"
+    "  }\n"
+    "}\n"
+    "trust-anchor\n"
+    "{\n"
+    "  type file\n"
+    "  file-name \"trust-anchor-5.cert\"\n"
+    "}\n";
+  const boost::filesystem::path CONFIG_PATH =
+    (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+  shared_ptr<Face> face = make_shared<Face>();
+  ValidatorConfig validator(face);
+  validator.load(CONFIG, CONFIG_PATH.native());
+
+  validator.validate(*data1,
+                     bind(&onValidated, _1),
+                     bind(&onValidationFailed, _1, _2));
+
+  validator.validate(*data2,
+                     bind(&onIntentionalFailureValidated, _1),
+                     bind(&onIntentionalFailureInvalidated, _1, _2));
+
+  validator.validate(*data3,
+                     bind(&onIntentionalFailureValidated, _1),
+                     bind(&onIntentionalFailureInvalidated, _1, _2));
+
+  keyChain.deleteIdentity(identity);
+
+  const boost::filesystem::path CERT_PATH =
+    (boost::filesystem::current_path() / std::string("trust-anchor-5.cert"));
+  boost::filesystem::remove(CERT_PATH);
+}
+
+struct FacesFixture
+{
+  FacesFixture()
+    : regPrefixId(0)
+    , regPrefixId2(0)
+  {}
+
+  void
+  onInterest(shared_ptr<Face> face, shared_ptr<Data> data)
+  {
+    face->put(*data);
+    face->unsetInterestFilter(regPrefixId);
+  }
+
+  void
+  onInterest2(shared_ptr<Face> face, shared_ptr<Data> data)
+  {
+    face->put(*data);
+    face->unsetInterestFilter(regPrefixId2);
+  }
+
+  void
+  onRegFailed()
+  {}
+
+  void
+  validate1(shared_ptr<ValidatorConfig> validator, shared_ptr<Data> data)
+  {
+    validator->validate(*data,
+                        bind(&onValidated, _1),
+                        bind(&onValidationFailed, _1, _2));
+  }
+
+  void
+  validate2(shared_ptr<ValidatorConfig> validator, shared_ptr<Data> data)
+  {
+    validator->validate(*data,
+                        bind(&onIntentionalFailureValidated, _1),
+                        bind(&onIntentionalFailureInvalidated, _1, _2));
+  }
+
+  void
+  validate3(shared_ptr<ValidatorConfig> validator, shared_ptr<Interest> interest)
+  {
+    validator->validate(*interest,
+                        bind(&onValidated2, _1),
+                        bind(&onValidationFailed2, _1, _2));
+  }
+
+  void
+  validate4(shared_ptr<ValidatorConfig> validator, shared_ptr<Interest> interest)
+  {
+    validator->validate(*interest,
+                        bind(&onIntentionalFailureValidated2, _1),
+                        bind(&onIntentionalFailureInvalidated2, _1, _2));
+  }
+
+  void
+  terminate(shared_ptr<Face> face)
+  {
+    face->ioService()->stop();
+  }
+
+  const RegisteredPrefixId* regPrefixId;
+  const RegisteredPrefixId* regPrefixId2;
+};
+
+BOOST_FIXTURE_TEST_CASE(HierarchicalChecker, FacesFixture)
+{
+  KeyChain keyChain;
+  std::vector<CertificateSubjectDescription> subjectDescription;
+
+  Name root("/TestValidatorConfig");
+  Name rootCertName = keyChain.createIdentity(root);
+  shared_ptr<IdentityCertificate> rootCert =
+    keyChain.getCertificate(rootCertName);
+  io::save(*rootCert, "trust-anchor-6.cert");
+
+
+  Name sld("/TestValidatorConfig/HierarchicalChecker");
+  Name sldKeyName = keyChain.generateRSAKeyPairAsDefault(sld, true);
+  shared_ptr<IdentityCertificate> sldCert =
+    keyChain.prepareUnsignedIdentityCertificate(sldKeyName,
+                                                root,
+                                                time::system_clock::now(),
+                                                time::system_clock::now() + time::days(7300),
+                                                subjectDescription);
+  keyChain.signByIdentity(*sldCert, root);
+  keyChain.addCertificateAsIdentityDefault(*sldCert);
+
+  Name nld("/TestValidatorConfig/HierarchicalChecker/NextLevel");
+  Name nldKeyName = keyChain.generateRSAKeyPairAsDefault(nld, true);
+  shared_ptr<IdentityCertificate> nldCert =
+    keyChain.prepareUnsignedIdentityCertificate(nldKeyName,
+                                                sld,
+                                                time::system_clock::now(),
+                                                time::system_clock::now() + time::days(7300),
+                                                subjectDescription);
+  keyChain.signByIdentity(*nldCert, sld);
+  keyChain.addCertificateAsIdentityDefault(*nldCert);
+
+  shared_ptr<Face> face = make_shared<Face>();
+  shared_ptr<Face> face2 = shared_ptr<Face>(new Face(face->ioService()));
+  Scheduler scheduler(*face->ioService());
+
+  scheduler.scheduleEvent(time::seconds(1),
+                          bind(&FacesFixture::terminate, this, face));
+
+  regPrefixId = face->setInterestFilter(sldCert->getName().getPrefix(-1),
+                                       bind(&FacesFixture::onInterest, this, face, sldCert),
+                                       bind(&FacesFixture::onRegFailed, this));
+
+  regPrefixId2 = face->setInterestFilter(nldCert->getName().getPrefix(-1),
+                                         bind(&FacesFixture::onInterest2, this, face, nldCert),
+                                         bind(&FacesFixture::onRegFailed, this));
+
+  Name dataName1 = nld;
+  dataName1.append("data1");
+  shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, nld));
+
+  Name dataName2("/ConfValidatorTest");
+  dataName2.append("data1");
+  shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, nld));
+
+
+  const std::string CONFIG =
+    "rule\n"
+    "{\n"
+    "  id \"Simple3 Rule\"\n"
+    "  for data\n"
+    "  checker\n"
+    "  {\n"
+    "    type hierarchical\n"
+    "    sig-type rsa-sha256\n"
+    "  }\n"
+    "}\n"
+    "trust-anchor\n"
+    "{\n"
+    "  type file\n"
+    "  file-name \"trust-anchor-6.cert\"\n"
+    "}\n";
+  const boost::filesystem::path CONFIG_PATH =
+    (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+  shared_ptr<ValidatorConfig> validator = shared_ptr<ValidatorConfig>(new ValidatorConfig(face2));
+  validator->load(CONFIG, CONFIG_PATH.native());
+
+  scheduler.scheduleEvent(time::milliseconds(200),
+                          bind(&FacesFixture::validate1, this,
+                               validator, data1));
+
+  scheduler.scheduleEvent(time::milliseconds(400),
+                          bind(&FacesFixture::validate2, this,
+                               validator, data2));
+
+  BOOST_REQUIRE_NO_THROW(face->processEvents());
+
+  keyChain.deleteIdentity(root);
+  keyChain.deleteIdentity(sld);
+  keyChain.deleteIdentity(nld);
+
+  const boost::filesystem::path CERT_PATH =
+    (boost::filesystem::current_path() / std::string("trust-anchor-6.cert"));
+  boost::filesystem::remove(CERT_PATH);
+}
+
+BOOST_AUTO_TEST_CASE(FixedSingerChecker)
+{
+  KeyChain keyChain;
+
+  Name identity("/TestValidatorConfig/FixedSingerChecker");
+
+  Name identity1 = identity;
+  identity1.append("1").appendVersion();
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity1));
+  Name certName1 = keyChain.getDefaultCertificateNameForIdentity(identity1);
+  shared_ptr<IdentityCertificate> idCert1 = keyChain.getCertificate(certName1);
+  io::save(*idCert1, "trust-anchor-7.cert");
+
+  Name identity2 = identity;
+  identity2.append("2").appendVersion();
+  BOOST_REQUIRE_NO_THROW(keyChain.createIdentity(identity2));
+
+  Name dataName1 = identity;
+  dataName1.append("data").appendVersion();
+  shared_ptr<Data> data1 = make_shared<Data>(dataName1);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data1, identity1));
+
+  Name dataName2 = identity;
+  dataName2.append("data").appendVersion();
+  shared_ptr<Data> data2 = make_shared<Data>(dataName2);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*data2, identity2));
+
+  const std::string CONFIG =
+    "rule\n"
+    "{\n"
+    "  id \"Simple3 Rule\"\n"
+    "  for data\n"
+    "  filter"
+    "  {\n"
+    "    type name\n"
+    "    name /TestValidatorConfig/FixedSingerChecker\n"
+    "    relation is-strict-prefix-of\n"
+    "  }\n"
+    "  checker\n"
+    "  {\n"
+    "    type fixed-signer\n"
+    "    sig-type rsa-sha256\n"
+    "    signer\n"
+    "    {\n"
+    "      type file\n"
+    "      file-name \"trust-anchor-7.cert\"\n"
+    "    }\n"
+    "  }\n"
+    "}\n";
+  const boost::filesystem::path CONFIG_PATH =
+    (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+  shared_ptr<Face> face = make_shared<Face>();
+  ValidatorConfig validator(face);
+  validator.load(CONFIG, CONFIG_PATH.native());
+
+  validator.validate(*data1,
+                     bind(&onValidated, _1),
+                     bind(&onValidationFailed, _1, _2));
+
+  validator.validate(*data2,
+                     bind(&onIntentionalFailureValidated, _1),
+                     bind(&onIntentionalFailureInvalidated, _1, _2));
+
+
+  keyChain.deleteIdentity(identity1);
+  keyChain.deleteIdentity(identity2);
+
+  const boost::filesystem::path CERT_PATH =
+    (boost::filesystem::current_path() / std::string("trust-anchor-7.cert"));
+  boost::filesystem::remove(CERT_PATH);
+}
+
+
+BOOST_FIXTURE_TEST_CASE(Nrd, FacesFixture)
+{
+  KeyChain keyChain;
+  std::vector<CertificateSubjectDescription> subjectDescription;
+
+  Name root("/TestValidatorConfig");
+  Name rootCertName = keyChain.createIdentity(root);
+  shared_ptr<IdentityCertificate> rootCert =
+    keyChain.getCertificate(rootCertName);
+  io::save(*rootCert, "trust-anchor-8.cert");
+
+
+  Name sld("/TestValidatorConfig/Nrd-1");
+  Name sldKeyName = keyChain.generateRSAKeyPairAsDefault(sld, true);
+  shared_ptr<IdentityCertificate> sldCert =
+    keyChain.prepareUnsignedIdentityCertificate(sldKeyName,
+                                                root,
+                                                time::system_clock::now(),
+                                                time::system_clock::now() + time::days(7300),
+                                                subjectDescription);
+  keyChain.signByIdentity(*sldCert, root);
+  keyChain.addCertificateAsIdentityDefault(*sldCert);
+
+  Name nld("/TestValidatorConfig/Nrd-1/Nrd-2");
+  Name nldKeyName = keyChain.generateRSAKeyPairAsDefault(nld, true);
+  shared_ptr<IdentityCertificate> nldCert =
+    keyChain.prepareUnsignedIdentityCertificate(nldKeyName,
+                                                sld,
+                                                time::system_clock::now(),
+                                                time::system_clock::now() + time::days(7300),
+                                                subjectDescription);
+  keyChain.signByIdentity(*nldCert, sld);
+  keyChain.addCertificateAsIdentityDefault(*nldCert);
+
+  shared_ptr<Face> face = make_shared<Face>();
+  shared_ptr<Face> face2 = shared_ptr<Face>(new Face(face->ioService()));
+  Scheduler scheduler(*face->ioService());
+
+  scheduler.scheduleEvent(time::seconds(1),
+                          bind(&FacesFixture::terminate, this, face));
+
+  regPrefixId = face->setInterestFilter(sldCert->getName().getPrefix(-1),
+                                       bind(&FacesFixture::onInterest, this, face, sldCert),
+                                       bind(&FacesFixture::onRegFailed, this));
+
+  regPrefixId2 = face->setInterestFilter(nldCert->getName().getPrefix(-1),
+                                         bind(&FacesFixture::onInterest2, this, face, nldCert),
+                                         bind(&FacesFixture::onRegFailed, this));
+
+  Name interestName1("/localhost/nrd/register/option/timestamp/nonce");
+  shared_ptr<Interest> interest1 = make_shared<Interest>(interestName1);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*interest1, nld));
+
+  Name interestName2("/localhost/nrd/non-register");
+  shared_ptr<Interest> interest2 = make_shared<Interest>(interestName2);
+  BOOST_CHECK_NO_THROW(keyChain.signByIdentity(*interest2, nld));
+
+
+  const std::string CONFIG =
+    "rule\n"
+    "{\n"
+    "  id \"NRD Prefix Registration Command Rule\"\n"
+    "  for interest\n"
+    "  filter\n"
+    "  {\n"
+    "    type name\n"
+    "    regex ^<localhost><nrd>[<register><unregister><advertise><withdraw>]<>{3}$\n"
+    "  }\n"
+    "  checker\n"
+    "  {\n"
+    "    type customized\n"
+    "    sig-type rsa-sha256\n"
+    "    key-locator\n"
+    "    {\n"
+    "      type name\n"
+    "      regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$\n"
+    "    }\n"
+    "  }\n"
+    "}\n"
+    "rule\n"
+    "{\n"
+    "  id \"Testbed Hierarchy Rule\"\n"
+    "  for data\n"
+    "  filter\n"
+    "  {\n"
+    "    type name\n"
+    "    regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$\n"
+    "  }\n"
+    "  checker\n"
+    "  {\n"
+    "    type hierarchical\n"
+    "    sig-type rsa-sha256\n"
+    "  }\n"
+    "}\n"
+    "trust-anchor\n"
+    "{\n"
+    "  type file\n"
+    "  file-name \"trust-anchor-8.cert\"\n"
+    "}\n";
+  const boost::filesystem::path CONFIG_PATH =
+    (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
+
+
+  shared_ptr<ValidatorConfig> validator = shared_ptr<ValidatorConfig>(new ValidatorConfig(face2));
+  validator->load(CONFIG, CONFIG_PATH.native());
+
+  scheduler.scheduleEvent(time::milliseconds(200),
+                          bind(&FacesFixture::validate3, this,
+                               validator, interest1));
+
+  scheduler.scheduleEvent(time::milliseconds(400),
+                          bind(&FacesFixture::validate4, this,
+                               validator, interest2));
+
+  BOOST_REQUIRE_NO_THROW(face->processEvents());
+
+  keyChain.deleteIdentity(root);
+  keyChain.deleteIdentity(sld);
+  keyChain.deleteIdentity(nld);
+
+  const boost::filesystem::path CERT_PATH =
+    (boost::filesystem::current_path() / std::string("trust-anchor-8.cert"));
+  boost::filesystem::remove(CERT_PATH);
+}
+
+
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace ndn