security: Reorganizing source code to prepare for support of two version of NDN certificates

This commit also removes unused ndn_digestSha256 function and deprecates
crypto::sha256 in favor of crypto::computeSha256Digest in util/crypto.hpp.

Change-Id: I24ee50ff073a96b868633bdf2cfade412d3605f3
Refs: #3098
diff --git a/src/security/v1/certificate-extension.cpp b/src/security/v1/certificate-extension.cpp
new file mode 100644
index 0000000..d871eac
--- /dev/null
+++ b/src/security/v1/certificate-extension.cpp
@@ -0,0 +1,77 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ */
+
+#include "certificate-extension.hpp"
+#include "cryptopp.hpp"
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+void
+CertificateExtension::encode(CryptoPP::BufferedTransformation& out) const
+{
+  using namespace CryptoPP;
+
+  // Extension ::= SEQUENCE {
+  //        extnID      OBJECT IDENTIFIER,
+  //        critical    BOOLEAN DEFAULT FALSE,
+  //        extnValue   OCTET STRING  }
+
+  DERSequenceEncoder extension(out);
+  {
+    m_extensionId.encode(extension);
+    DEREncodeUnsigned(extension, m_isCritical, BOOLEAN);
+    DEREncodeOctetString(extension, m_extensionValue.buf(), m_extensionValue.size());
+  }
+  extension.MessageEnd();
+}
+
+void
+CertificateExtension::decode(CryptoPP::BufferedTransformation& in)
+{
+  using namespace CryptoPP;
+
+  // Extension ::= SEQUENCE {
+  //        extnID      OBJECT IDENTIFIER,
+  //        critical    BOOLEAN DEFAULT FALSE,
+  //        extnValue   OCTET STRING  }
+
+  BERSequenceDecoder extension(in);
+  {
+    m_extensionId.decode(extension);
+    BERDecodeUnsigned(extension, m_isCritical, BOOLEAN);
+
+    // the extra copy operation can be optimized, but not trivial,
+    // since the length is not known in advance
+    SecByteBlock tmpBlock;
+    BERDecodeOctetString(extension, tmpBlock);
+    m_extensionValue.assign(tmpBlock.begin(), tmpBlock.end());
+  }
+  extension.MessageEnd();
+}
+
+} // namespace v1
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v1/certificate-extension.hpp b/src/security/v1/certificate-extension.hpp
new file mode 100644
index 0000000..c898835
--- /dev/null
+++ b/src/security/v1/certificate-extension.hpp
@@ -0,0 +1,128 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ * @author Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ */
+
+#ifndef NDN_SECURITY_V1_CERTIFICATE_EXTENSION_HPP
+#define NDN_SECURITY_V1_CERTIFICATE_EXTENSION_HPP
+
+#include "../../common.hpp"
+#include "../../encoding/buffer.hpp"
+#include "../../encoding/oid.hpp"
+
+namespace CryptoPP {
+class BufferedTransformation;
+} // namespace CryptoPP
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+/**
+ * A CertificateExtension represents the Extension entry in a certificate.
+ */
+class CertificateExtension
+{
+public:
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+  explicit
+  CertificateExtension(CryptoPP::BufferedTransformation& in)
+  {
+    decode(in);
+  }
+
+  /**
+   * Create a new CertificateExtension.
+   * @param oid The oid of subject description entry.
+   * @param isCritical If true, the extension must be handled.
+   * @param value The extension value.
+   */
+  CertificateExtension(const Oid& oid, const bool isCritical, const Buffer& value)
+    : m_extensionId(oid), m_isCritical(isCritical), m_extensionValue(value)
+  {
+  }
+
+  CertificateExtension(const Oid& oid, const bool isCritical,
+                       const uint8_t* value, size_t valueSize)
+    : m_extensionId(oid), m_isCritical(isCritical), m_extensionValue(value, valueSize)
+  {
+  }
+
+  /**
+   * The virtual destructor.
+   */
+  virtual
+  ~CertificateExtension()
+  {
+  }
+
+  void
+  encode(CryptoPP::BufferedTransformation& out) const;
+
+  void
+  decode(CryptoPP::BufferedTransformation& in);
+
+  inline const Oid&
+  getOid() const
+  {
+    return m_extensionId;
+  }
+
+  inline bool
+  getIsCritical() const
+  {
+    return m_isCritical;
+  }
+
+  inline const Buffer&
+  getValue() const
+  {
+    return m_extensionValue;
+  }
+
+protected:
+  Oid m_extensionId;
+  bool m_isCritical;
+  Buffer m_extensionValue;
+};
+
+} // namespace v1
+} // namespace security
+
+#ifdef NDN_CXX_KEEP_SECURITY_V1_ALIASES
+/// @deprecated When needed, use explicit namespace
+using security::v1::CertificateExtension;
+#endif // NDN_CXX_KEEP_SECURITY_V1_ALIASES
+
+} // namespace ndn
+
+#endif // NDN_SECURITY_V1_CERTIFICATE_EXTENSION_HPP
diff --git a/src/security/v1/certificate-subject-description.cpp b/src/security/v1/certificate-subject-description.cpp
new file mode 100644
index 0000000..1e910c2
--- /dev/null
+++ b/src/security/v1/certificate-subject-description.cpp
@@ -0,0 +1,84 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ * @author Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ */
+
+#include "certificate-subject-description.hpp"
+
+#include "cryptopp.hpp"
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+void
+CertificateSubjectDescription::encode(CryptoPP::BufferedTransformation& out) const
+{
+  using namespace CryptoPP;
+  // RelativeDistinguishedName ::=
+  //     SET OF AttributeTypeAndValue
+  //
+  // AttributeTypeAndValue ::= SEQUENCE {
+  //     type     AttributeType,
+  //     value    AttributeValue   }
+  //
+  // AttributeType ::= OBJECT IDENTIFIER
+  //
+  // AttributeValue ::= ANY DEFINED BY AttributeType
+  DERSequenceEncoder attributeTypeAndValue(out);
+  {
+    m_oid.encode(attributeTypeAndValue);
+    DEREncodeTextString(attributeTypeAndValue, m_value, PRINTABLE_STRING);
+  }
+  attributeTypeAndValue.MessageEnd();
+}
+
+void
+CertificateSubjectDescription::decode(CryptoPP::BufferedTransformation& in)
+{
+  using namespace CryptoPP;
+  // RelativeDistinguishedName ::=
+  //     SET OF AttributeTypeAndValue
+  //
+  // AttributeTypeAndValue ::= SEQUENCE {
+  //     type     AttributeType,
+  //     value    AttributeValue   }
+  //
+  // AttributeType ::= OBJECT IDENTIFIER
+  //
+  // AttributeValue ::= ANY DEFINED BY AttributeType
+
+  BERSequenceDecoder attributeTypeAndValue(in);
+  {
+    m_oid.decode(attributeTypeAndValue);
+
+    /// @todo May be add more intelligent processing, since the following
+    ///       may fail if somebody encoded attribute that uses non PRINTABLE_STRING as value
+    BERDecodeTextString(attributeTypeAndValue, m_value, PRINTABLE_STRING);
+  }
+  attributeTypeAndValue.MessageEnd();
+}
+
+} // namespace v1
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v1/certificate-subject-description.hpp b/src/security/v1/certificate-subject-description.hpp
new file mode 100644
index 0000000..00eab76
--- /dev/null
+++ b/src/security/v1/certificate-subject-description.hpp
@@ -0,0 +1,95 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ * @author Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ */
+
+#ifndef NDN_SECURITY_V1_CERTIFICATE_SUBJECT_DESCRIPTION_HPP
+#define NDN_SECURITY_V1_CERTIFICATE_SUBJECT_DESCRIPTION_HPP
+
+#include "../../common.hpp"
+#include "../../encoding/oid.hpp"
+
+namespace CryptoPP {
+class BufferedTransformation;
+} // namespace CryptoPP
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+/**
+ * A CertificateSubjectDescription represents the SubjectDescription entry in a Certificate.
+ */
+class CertificateSubjectDescription
+{
+public:
+  explicit
+  CertificateSubjectDescription(CryptoPP::BufferedTransformation& in)
+  {
+    decode(in);
+  }
+
+  /**
+   * Create a new CertificateSubjectDescription.
+   * @param oid The oid of the subject description entry.
+   * @param value The value of the subject description entry.
+   */
+  CertificateSubjectDescription(const Oid& oid, const std::string& value)
+  : m_oid(oid), m_value(value)
+  {
+  }
+
+  void
+  encode(CryptoPP::BufferedTransformation& out) const;
+
+  void
+  decode(CryptoPP::BufferedTransformation& in);
+
+  std::string
+  getOidString() const
+  {
+    return m_oid.toString();
+  }
+
+  const std::string&
+  getValue() const
+  {
+    return m_value;
+  }
+
+private:
+  Oid m_oid;
+  std::string m_value;
+};
+
+} // namespace v1
+} // namespace security
+
+#ifdef NDN_CXX_KEEP_SECURITY_V1_ALIASES
+/// @deprecated When needed, use explicit namespace
+using security::v1::CertificateSubjectDescription;
+#endif // NDN_CXX_KEEP_SECURITY_V1_ALIASES
+
+} // namespace ndn
+
+#endif // NDN_SECURITY_V1_CERTIFICATE_SUBJECT_DESCRIPTION_HPP
diff --git a/src/security/v1/certificate.cpp b/src/security/v1/certificate.cpp
new file mode 100644
index 0000000..823c994
--- /dev/null
+++ b/src/security/v1/certificate.cpp
@@ -0,0 +1,359 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ * @author Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ */
+
+#include "certificate.hpp"
+#include "../../util/time.hpp"
+#include "cryptopp.hpp"
+#include "../../encoding/cryptopp/asn_ext.hpp"
+#include "../../encoding/buffer-stream.hpp"
+#include "../../util/concepts.hpp"
+#include "../../util/indented-stream.hpp"
+
+#include <boost/algorithm/string/split.hpp>
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+BOOST_CONCEPT_ASSERT((WireEncodable<Certificate>));
+BOOST_CONCEPT_ASSERT((WireDecodable<Certificate>));
+static_assert(std::is_base_of<tlv::Error, Certificate::Error>::value,
+              "Certificate::Error must inherit from tlv::Error");
+
+Certificate::Certificate()
+  : m_notBefore(time::system_clock::TimePoint::max())
+  , m_notAfter(time::system_clock::TimePoint::min())
+{
+}
+
+Certificate::Certificate(const Data& data)
+  // Use the copy constructor.  It clones the signature object.
+  : Data(data)
+{
+  decode();
+}
+
+Certificate::Certificate(const Block& block)
+  : Data(block)
+{
+  decode();
+}
+
+Certificate::~Certificate()
+{
+}
+
+void
+Certificate::wireDecode(const Block& wire)
+{
+  Data::wireDecode(wire);
+  decode();
+}
+
+bool
+Certificate::isTooEarly()
+{
+  if (time::system_clock::now() < m_notBefore)
+    return true;
+  else
+    return false;
+}
+
+bool
+Certificate::isTooLate()
+{
+  if (time::system_clock::now() > m_notAfter)
+    return true;
+  else
+    return false;
+}
+
+void
+Certificate::encode()
+{
+  // Name
+  //    <key_name>/ID-CERT/<id#>
+  // Content
+  // DER encoded idCert:
+  //
+  //    idCert ::= SEQUENCE {
+  //        validity            Validity,
+  //        subject             Name,
+  //        subjectPubKeyInfo   SubjectPublicKeyInfo,
+  //        extension           Extensions OPTIONAL   }
+  //
+  //    Validity ::= SEQUENCE {
+  //        notBefore           Time,
+  //        notAfter            Time   }
+  //
+  //    Name ::= CHOICE {
+  //        RDNSequence   }
+  //
+  //    RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+  //
+  //    RelativeDistinguishedName ::=
+  //        SET OF AttributeTypeAndValue
+  //
+  //    SubjectPublicKeyInfo ::= SEQUENCE {
+  //        algorithm           AlgorithmIdentifier
+  //        keybits             BIT STRING   }
+  //
+  //    Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+  //
+  // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
+  //
+  // KeyLocator
+  //    issuer’s certificate name
+  // Signature
+
+  using namespace CryptoPP;
+
+  OBufferStream os;
+  CryptoPP::FileSink sink(os);
+
+  // idCert ::= SEQUENCE {
+  //     validity            Validity,
+  //     subject             Name,
+  //     subjectPubKeyInfo   SubjectPublicKeyInfo,
+  //     extension           Extensions OPTIONAL   }
+  DERSequenceEncoder idCert(sink);
+  {
+    // Validity ::= SEQUENCE {
+    //       notBefore           Time,
+    //       notAfter            Time   }
+    DERSequenceEncoder validity(idCert);
+    {
+      DEREncodeGeneralTime(validity, m_notBefore);
+      DEREncodeGeneralTime(validity, m_notAfter);
+    }
+    validity.MessageEnd();
+
+    // Name ::= CHOICE {
+    //     RDNSequence   }
+    //
+    // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+    DERSequenceEncoder name(idCert);
+    {
+      for (SubjectDescriptionList::iterator it = m_subjectDescriptionList.begin();
+           it != m_subjectDescriptionList.end(); ++it)
+        {
+          it->encode(name);
+        }
+    }
+    name.MessageEnd();
+
+    // SubjectPublicKeyInfo
+    m_key.encode(idCert);
+
+    // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+    //
+    // Extension ::= SEQUENCE {
+    //        extnID      OBJECT IDENTIFIER,
+    //        critical    BOOLEAN DEFAULT FALSE,
+    //        extnValue   OCTET STRING  }
+    if (!m_extensionList.empty())
+      {
+        DERSequenceEncoder extensions(idCert);
+        {
+          for (ExtensionList::iterator it = m_extensionList.begin();
+               it != m_extensionList.end(); ++it)
+            {
+              it->encode(extensions);
+            }
+        }
+        extensions.MessageEnd();
+      }
+  }
+
+  idCert.MessageEnd();
+
+  setContent(os.buf());
+  setContentType(tlv::ContentType_Key);
+}
+
+void
+Certificate::decode()
+{
+  using namespace CryptoPP;
+
+  try {
+    OBufferStream os;
+    StringSource source(getContent().value(), getContent().value_size(), true);
+
+    // idCert ::= SEQUENCE {
+    //     validity            Validity,
+    //     subject             Name,
+    //     subjectPubKeyInfo   SubjectPublicKeyInfo,
+    //     extension           Extensions OPTIONAL   }
+    BERSequenceDecoder idCert(source);
+    {
+      // Validity ::= SEQUENCE {
+      //       notBefore           Time,
+      //       notAfter            Time   }
+      BERSequenceDecoder validity(idCert);
+      {
+        BERDecodeTime(validity, m_notBefore);
+        BERDecodeTime(validity, m_notAfter);
+      }
+      validity.MessageEnd();
+
+      // Name ::= CHOICE {
+      //     RDNSequence   }
+      //
+      // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+      m_subjectDescriptionList.clear();
+      BERSequenceDecoder name(idCert);
+      {
+        while (!name.EndReached())
+          {
+            m_subjectDescriptionList.push_back(CertificateSubjectDescription(name));
+          }
+      }
+      name.MessageEnd();
+
+      // SubjectPublicKeyInfo ::= SEQUENCE {
+      //     algorithm           AlgorithmIdentifier
+      //     keybits             BIT STRING   }
+      m_key.decode(idCert);
+
+      // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+      //
+      // Extension ::= SEQUENCE {
+      //        extnID      OBJECT IDENTIFIER,
+      //        critical    BOOLEAN DEFAULT FALSE,
+      //        extnValue   OCTET STRING  }
+      m_extensionList.clear();
+      if (!idCert.EndReached())
+        {
+          BERSequenceDecoder extensions(idCert);
+          {
+            while (!extensions.EndReached())
+              {
+                m_extensionList.push_back(CertificateExtension(extensions));
+              }
+          }
+          extensions.MessageEnd();
+        }
+    }
+
+    idCert.MessageEnd();
+  }
+  catch (CryptoPP::BERDecodeErr&) {
+    BOOST_THROW_EXCEPTION(Error("Certificate Decoding Error"));
+  }
+}
+
+void
+Certificate::printCertificate(std::ostream& oss, const std::string& indent) const
+{
+  util::IndentedStream os(oss, indent);
+
+  os << "Certificate name:\n";
+  os << "  " << getName() << "\n";
+  os << "Validity:\n";
+  {
+    os << "  NotBefore: " << time::toIsoString(m_notBefore) << "\n";
+    os << "  NotAfter: "  << time::toIsoString(m_notAfter)  << "\n";
+  }
+
+  os << "Subject Description:\n";
+  for (const auto& description : m_subjectDescriptionList)
+    os << "  " << description.getOidString() << ": " << description.getValue() << "\n";
+
+  os << "Public key bits: ";
+  switch (m_key.getKeyType()) {
+  case KeyType::RSA:
+    os << "(RSA)";
+    break;
+  case KeyType::EC:
+    os << "(ECDSA)";
+    break;
+  default:
+    os << "(Unknown key type)";
+    break;
+  }
+  os << "\n";
+
+  {
+    util::IndentedStream os2(os, "  ");
+    CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os2), true, 64);
+    m_key.encode(encoder);
+  }
+
+  os << "Signature Information:\n";
+  {
+    os << "  Signature Type: ";
+    switch (getSignature().getType()) {
+    case tlv::SignatureTypeValue::DigestSha256:
+      os << "DigestSha256";
+      break;
+    case tlv::SignatureTypeValue::SignatureSha256WithRsa:
+      os << "SignatureSha256WithRsa";
+      break;
+    case tlv::SignatureTypeValue::SignatureSha256WithEcdsa:
+      os << "SignatureSha256WithEcdsa";
+      break;
+    default:
+      os << "Unknown Signature Type";
+    }
+    os << "\n";
+
+    if (getSignature().hasKeyLocator()) {
+      const KeyLocator& keyLocator = getSignature().getKeyLocator();
+      os << "  Key Locator: ";
+      switch (keyLocator.getType()) {
+      case KeyLocator::KeyLocator_Name:
+        {
+          const Name& signerName = keyLocator.getName();
+          if (signerName.isPrefixOf(getName()))
+            os << "(Self-Signed) " << keyLocator.getName();
+          else
+            os << "(Name) " << keyLocator.getName();
+          break;
+        }
+      case KeyLocator::KeyLocator_KeyDigest:
+        os << "(KeyDigest)";
+        break;
+      case KeyLocator::KeyLocator_None:
+        os << "None";
+        break;
+      default:
+        os << "Unknown";
+      }
+      os << "\n";
+    }
+  }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Certificate& cert)
+{
+  cert.printCertificate(os);
+  return os;
+}
+
+} // namespace v1
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v1/certificate.hpp b/src/security/v1/certificate.hpp
new file mode 100644
index 0000000..f2f70bf
--- /dev/null
+++ b/src/security/v1/certificate.hpp
@@ -0,0 +1,226 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ * @author Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ */
+
+#ifndef NDN_SECURITY_V1_CERTIFICATE_HPP
+#define NDN_SECURITY_V1_CERTIFICATE_HPP
+
+#include "../../common.hpp"
+#include "../../data.hpp"
+#include "certificate-subject-description.hpp"
+#include "certificate-extension.hpp"
+#include "public-key.hpp"
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+class Certificate : public Data
+{
+public:
+  class Error : public Data::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : Data::Error(what)
+    {
+    }
+  };
+
+  typedef std::vector<CertificateSubjectDescription> SubjectDescriptionList;
+  typedef std::vector<CertificateExtension> ExtensionList;
+
+  /**
+   * @brief The default constructor.
+   */
+  Certificate();
+
+  /**
+   * @brief Create a Certificate from the content in the data packet.
+   * @param data The data packet with the content to decode.
+   */
+  explicit
+  Certificate(const Data& data);
+
+  /**
+   * @brief Create a Certificate from the a block
+   * @param block The raw block of the certificate
+   */
+  explicit
+  Certificate(const Block& block);
+
+  virtual
+  ~Certificate();
+
+  void
+  wireDecode(const Block& wire);
+
+  /**
+   * @brief encode certificate info into content
+   */
+  void
+  encode();
+
+  /**
+   * @brief Add a subject description.
+   * @param description The description to be added.
+   */
+  void
+  addSubjectDescription(const CertificateSubjectDescription& description)
+  {
+    m_subjectDescriptionList.push_back(description);
+  }
+
+  const SubjectDescriptionList&
+  getSubjectDescriptionList() const
+  {
+    return m_subjectDescriptionList;
+  }
+
+  SubjectDescriptionList&
+  getSubjectDescriptionList()
+  {
+    return m_subjectDescriptionList;
+  }
+
+  /**
+   * @brief Add a certificate extension.
+   * @param extension the extension to be added
+   */
+  void
+  addExtension(const CertificateExtension& extension)
+  {
+    m_extensionList.push_back(extension);
+  }
+
+  const ExtensionList&
+  getExtensionList() const
+  {
+    return m_extensionList;
+  }
+
+  ExtensionList&
+  getExtensionList()
+  {
+    return m_extensionList;
+  }
+
+  void
+  setNotBefore(const time::system_clock::TimePoint& notBefore)
+  {
+    m_notBefore = notBefore;
+  }
+
+  time::system_clock::TimePoint&
+  getNotBefore()
+  {
+    return m_notBefore;
+  }
+
+  const time::system_clock::TimePoint&
+  getNotBefore() const
+  {
+    return m_notBefore;
+  }
+
+  void
+  setNotAfter(const time::system_clock::TimePoint& notAfter)
+  {
+    m_notAfter = notAfter;
+  }
+
+  time::system_clock::TimePoint&
+  getNotAfter()
+  {
+    return m_notAfter;
+  }
+
+  const time::system_clock::TimePoint&
+  getNotAfter() const
+  {
+    return m_notAfter;
+  }
+
+  void
+  setPublicKeyInfo(const PublicKey& key)
+  {
+    m_key = key;
+  }
+
+  PublicKey&
+  getPublicKeyInfo()
+  {
+    return m_key;
+  }
+
+  const PublicKey&
+  getPublicKeyInfo() const
+  {
+    return m_key;
+  }
+
+  /**
+   * @brief Check if the certificate is valid.
+   * @return True if the current time is earlier than notBefore.
+   */
+  bool
+  isTooEarly();
+
+  /**
+   * @brief Check if the certificate is valid.
+   * @return True if the current time is later than notAfter.
+   */
+  bool
+  isTooLate();
+
+  void
+  printCertificate(std::ostream& os, const std::string& indent = "") const;
+
+protected:
+  void
+  decode();
+
+protected:
+  SubjectDescriptionList m_subjectDescriptionList;
+  time::system_clock::TimePoint m_notBefore;
+  time::system_clock::TimePoint m_notAfter;
+  PublicKey m_key;
+  ExtensionList m_extensionList;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const Certificate& cert);
+
+} // namespace v1
+} // namespace security
+
+#ifdef NDN_CXX_KEEP_SECURITY_V1_ALIASES
+/// @deprecated When needed, use explicit namespace
+using security::v1::Certificate;
+#endif // NDN_CXX_KEEP_SECURITY_V1_ALIASES
+
+} // namespace ndn
+
+#endif // NDN_SECURITY_V1_CERTIFICATE_HPP
diff --git a/src/security/v1/cryptopp.hpp b/src/security/v1/cryptopp.hpp
new file mode 100644
index 0000000..4de66bb
--- /dev/null
+++ b/src/security/v1/cryptopp.hpp
@@ -0,0 +1,45 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_V1_CRYPTOPP_HPP
+#define NDN_SECURITY_V1_CRYPTOPP_HPP
+
+// suppress CryptoPP warnings
+#pragma GCC system_header
+#pragma clang system_header
+
+#include <cryptopp/asn.h>
+#include <cryptopp/base64.h>
+#include <cryptopp/des.h>
+#include <cryptopp/files.h>
+#include <cryptopp/filters.h>
+#include <cryptopp/hex.h>
+#include <cryptopp/modes.h>
+#include <cryptopp/osrng.h>
+#include <cryptopp/pssr.h>
+#include <cryptopp/pwdbased.h>
+#include <cryptopp/rsa.h>
+#include <cryptopp/sha.h>
+#include <cryptopp/eccrypto.h>
+#include <cryptopp/oids.h>
+#include <cryptopp/dsa.h>
+
+#endif // NDN_SECURITY_V1_CRYPTOPP_HPP
diff --git a/src/security/v1/identity-certificate.cpp b/src/security/v1/identity-certificate.cpp
new file mode 100644
index 0000000..ea8a946
--- /dev/null
+++ b/src/security/v1/identity-certificate.cpp
@@ -0,0 +1,148 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "identity-certificate.hpp"
+#include "../../util/concepts.hpp"
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+using std::string;
+
+BOOST_CONCEPT_ASSERT((WireEncodable<IdentityCertificate>));
+BOOST_CONCEPT_ASSERT((WireDecodable<IdentityCertificate>));
+static_assert(std::is_base_of<Certificate::Error, IdentityCertificate::Error>::value,
+              "IdentityCertificate::Error must inherit from Certificate::Error");
+
+IdentityCertificate::IdentityCertificate()
+{
+  this->setFreshnessPeriod(time::hours(1));
+}
+
+IdentityCertificate::IdentityCertificate(const Data& data)
+  : Certificate(data)
+{
+  setPublicKeyName();
+}
+
+IdentityCertificate::IdentityCertificate(const Block& block)
+  : Certificate(block)
+{
+  setPublicKeyName();
+}
+
+void
+IdentityCertificate::wireDecode(const Block& wire)
+{
+  Certificate::wireDecode(wire);
+  setPublicKeyName();
+}
+
+void
+IdentityCertificate::setName(const Name& name)
+{
+  Certificate::setName(name);
+  setPublicKeyName();
+}
+
+bool
+IdentityCertificate::isCorrectName(const Name& name)
+{
+  string idString("ID-CERT");
+  ssize_t i = name.size() - 1;
+  for (; i >= 0; i--) {
+    if (name.get(i).toUri() == idString)
+      break;
+  }
+
+  if (i < 0)
+    return false;
+
+  string keyString("KEY");
+  size_t keyIndex = 0;
+  for (; keyIndex < name.size(); keyIndex++) {
+    if (name.get(keyIndex).toUri() == keyString)
+      break;
+  }
+
+  if (keyIndex >= name.size())
+    return false;
+
+  return true;
+}
+
+void
+IdentityCertificate::setPublicKeyName()
+{
+  if (!isCorrectName(getName()))
+    BOOST_THROW_EXCEPTION(Error("Wrong Identity Certificate Name"));
+
+  m_publicKeyName = certificateNameToPublicKeyName(getName());
+}
+
+bool
+IdentityCertificate::isIdentityCertificate(const Certificate& certificate)
+{
+  return dynamic_cast<const IdentityCertificate*>(&certificate);
+}
+
+Name
+IdentityCertificate::certificateNameToPublicKeyName(const Name& certificateName)
+{
+  string idString("ID-CERT");
+  bool foundIdString = false;
+  size_t idCertComponentIndex = certificateName.size() - 1;
+  for (; idCertComponentIndex + 1 > 0; --idCertComponentIndex) {
+    if (certificateName.get(idCertComponentIndex).toUri() == idString)
+      {
+        foundIdString = true;
+        break;
+      }
+  }
+
+  if (!foundIdString)
+    BOOST_THROW_EXCEPTION(Error("Incorrect identity certificate name " + certificateName.toUri()));
+
+  Name tmpName = certificateName.getSubName(0, idCertComponentIndex);
+  string keyString("KEY");
+  bool foundKeyString = false;
+  size_t keyComponentIndex = 0;
+  for (; keyComponentIndex < tmpName.size(); keyComponentIndex++) {
+    if (tmpName.get(keyComponentIndex).toUri() == keyString)
+      {
+        foundKeyString = true;
+        break;
+      }
+  }
+
+  if (!foundKeyString)
+    BOOST_THROW_EXCEPTION(Error("Incorrect identity certificate name " + certificateName.toUri()));
+
+  return tmpName
+           .getSubName(0, keyComponentIndex)
+           .append(tmpName.getSubName(keyComponentIndex + 1,
+                                      tmpName.size() - keyComponentIndex - 1));
+}
+
+} // namespace v1
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v1/identity-certificate.hpp b/src/security/v1/identity-certificate.hpp
new file mode 100644
index 0000000..7ea4fe4
--- /dev/null
+++ b/src/security/v1/identity-certificate.hpp
@@ -0,0 +1,110 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ */
+
+#ifndef NDN_SECURITY_V1_IDENTITY_CERTIFICATE_HPP
+#define NDN_SECURITY_V1_IDENTITY_CERTIFICATE_HPP
+
+#include "../../common.hpp"
+#include "certificate.hpp"
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+class IdentityCertificate : public Certificate
+{
+public:
+  class Error : public Certificate::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : Certificate::Error(what)
+    {
+    }
+  };
+
+  /**
+   * @brief The default constructor.
+   */
+  IdentityCertificate();
+
+  /**
+   * @brief Create an IdentityCertificate from the content in the data packet.
+   * @param data The data packet with the content to decode.
+   */
+  explicit
+  IdentityCertificate(const Data& data);
+
+  /**
+   * @brief Create an IdentityCertificate from a block.
+   * @param block The raw block of the certificate.
+   */
+  explicit
+  IdentityCertificate(const Block& block);
+
+  void
+  wireDecode(const Block& wire);
+
+  void
+  setName(const Name& name);
+
+  const Name&
+  getPublicKeyName() const
+  {
+    return m_publicKeyName;
+  }
+
+  static bool
+  isIdentityCertificate(const Certificate& certificate);
+
+  /**
+   * @brief Get the public key name from the full certificate name.
+   * @param certificateName The full certificate name.
+   * @return The related public key name.
+   */
+  static Name
+  certificateNameToPublicKeyName(const Name& certificateName);
+
+private:
+  static bool
+  isCorrectName(const Name& name);
+
+  void
+  setPublicKeyName();
+
+protected:
+  Name m_publicKeyName;
+};
+
+} // namespace v1
+} // namespace security
+
+#ifdef NDN_CXX_KEEP_SECURITY_V1_ALIASES
+/// @deprecated When needed, use explicit namespace
+using security::v1::IdentityCertificate;
+#endif // NDN_CXX_KEEP_SECURITY_V1_ALIASES
+
+} // namespace ndn
+
+#endif // NDN_SECURITY_V1_IDENTITY_CERTIFICATE_HPP
diff --git a/src/security/v1/public-key.cpp b/src/security/v1/public-key.cpp
new file mode 100644
index 0000000..2721dee
--- /dev/null
+++ b/src/security/v1/public-key.cpp
@@ -0,0 +1,155 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ */
+
+#include "public-key.hpp"
+
+#include "../../encoding/oid.hpp"
+#include "../../util/crypto.hpp"
+#include "cryptopp.hpp"
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+PublicKey::PublicKey()
+  : m_type(KeyType::NONE)
+{
+}
+
+PublicKey::PublicKey(const uint8_t* keyDerBuf, size_t keyDerSize)
+  : m_type(KeyType::NONE)
+{
+  CryptoPP::StringSource src(keyDerBuf, keyDerSize, true);
+  decode(src);
+}
+
+const Block&
+PublicKey::computeDigest() const
+{
+  if (m_key.empty())
+    BOOST_THROW_EXCEPTION(Error("Public key is empty"));
+
+  if (m_digest.hasWire())
+    return m_digest;
+  else {
+    m_digest = Block(tlv::KeyDigest, crypto::computeSha256Digest(m_key.buf(), m_key.size()));
+    m_digest.encode();
+    return m_digest;
+  }
+}
+
+
+void
+PublicKey::encode(CryptoPP::BufferedTransformation& out) const
+{
+  // SubjectPublicKeyInfo ::= SEQUENCE {
+  //     algorithm           AlgorithmIdentifier
+  //     keybits             BIT STRING   }
+
+  out.Put(m_key.buf(), m_key.size());
+}
+
+void
+PublicKey::decode(CryptoPP::BufferedTransformation& in)
+{
+  // SubjectPublicKeyInfo ::= SEQUENCE {
+  //     algorithm           AlgorithmIdentifier
+  //     keybits             BIT STRING   }
+
+  using namespace CryptoPP;
+  try
+    {
+      std::string out;
+      StringSink sink(out);
+
+      ////////////////////////
+      // part 1: copy as is //
+      ////////////////////////
+      BERSequenceDecoder decoder(in);
+      {
+        assert(decoder.IsDefiniteLength());
+
+        DERSequenceEncoder encoder(sink);
+        decoder.TransferTo(encoder, decoder.RemainingLength());
+        encoder.MessageEnd();
+      }
+      decoder.MessageEnd();
+
+      ////////////////////////
+      // part 2: check if the key is RSA (since it is the only supported for now)
+      ////////////////////////
+      StringSource checkedSource(out, true);
+      BERSequenceDecoder subjectPublicKeyInfo(checkedSource);
+      {
+        BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
+        {
+          Oid algorithm;
+          algorithm.decode(algorithmInfo);
+
+          if (algorithm == oid::RSA)
+            m_type = KeyType::RSA;
+          else if (algorithm == oid::ECDSA)
+            m_type = KeyType::EC;
+          else
+            BOOST_THROW_EXCEPTION(Error("Only RSA/ECDSA public keys are supported for now (" +
+                                        algorithm.toString() + " requested)"));
+        }
+      }
+
+      m_key.assign(out.begin(), out.end());
+    }
+  catch (CryptoPP::BERDecodeErr& err)
+    {
+      m_type = KeyType::NONE;
+      BOOST_THROW_EXCEPTION(Error("PublicKey decoding error"));
+    }
+
+  m_digest.reset();
+}
+
+// Blob
+// PublicKey::getDigest(DigestAlgorithm digestAlgorithm) const
+// {
+//   if (digestAlgorithm == DigestAlgorithm::SHA256) {
+//     uint8_t digest[SHA256_DIGEST_LENGTH];
+//     ndn_digestSha256(keyDer_.buf(), keyDer_.size(), digest);
+
+//     return Blob(digest, sizeof(digest));
+//   }
+//   else
+//     throw UnrecognizedDigestAlgorithmException("Wrong format!");
+// }
+
+std::ostream&
+operator<<(std::ostream& os, const PublicKey& key)
+{
+  CryptoPP::StringSource(key.get().buf(), key.get().size(), true,
+                         new CryptoPP::Base64Encoder(new CryptoPP::FileSink(os), true, 64));
+
+  return os;
+}
+
+} // namespace v1
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v1/public-key.hpp b/src/security/v1/public-key.hpp
new file mode 100644
index 0000000..6b67535
--- /dev/null
+++ b/src/security/v1/public-key.hpp
@@ -0,0 +1,133 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ * @author Jeff Thompson <jefft0@remap.ucla.edu>
+ */
+
+#ifndef NDN_SECURITY_V1_PUBLIC_KEY_HPP
+#define NDN_SECURITY_V1_PUBLIC_KEY_HPP
+
+#include "../../common.hpp"
+
+#include "../../encoding/buffer.hpp"
+#include "../../encoding/block.hpp"
+#include "../security-common.hpp"
+
+namespace CryptoPP {
+class BufferedTransformation;
+} // namespace CryptoPP
+
+namespace ndn {
+namespace security {
+namespace v1 {
+
+class PublicKey
+{
+public:
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+  /**
+   * The default constructor.
+   */
+  PublicKey();
+
+  /**
+   * @brief Create a new PublicKey from @p keyDerBuf in DER buffer
+   *
+   * @param keyDerBuf The pointer to the first byte of buffer containing DER of public key
+   * @param keyDerSize Size of the buffer
+   *
+   * @throws PublicKey::Error If DER in buffer cannot be decoded
+   */
+  PublicKey(const uint8_t* keyDerBuf, size_t keyDerSize);
+
+  const Buffer&
+  get() const
+  {
+    return m_key;
+  }
+
+  void
+  set(const uint8_t* keyDerBuf, size_t keyDerSize)
+  {
+    Buffer buf(keyDerBuf, keyDerSize);
+    m_key.swap(buf);
+  }
+
+  KeyType
+  getKeyType() const
+  {
+    return m_type;
+  }
+
+  /**
+   * @return a KeyDigest block that matches this public key
+   */
+  const Block&
+  computeDigest() const;
+
+  void
+  encode(CryptoPP::BufferedTransformation& out) const;
+
+  void
+  decode(CryptoPP::BufferedTransformation& in);
+
+  bool
+  operator==(const PublicKey& key) const
+  {
+    return m_key == key.m_key;
+  }
+
+  bool
+  operator!=(const PublicKey& key) const
+  {
+    return m_key != key.m_key;
+  }
+
+private:
+  KeyType m_type;
+  Buffer m_key;
+  mutable Block m_digest;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const PublicKey& key);
+
+} // namespace v1
+} // namespace security
+
+#ifdef NDN_CXX_KEEP_SECURITY_V1_ALIASES
+/// @deprecated When needed, use explicit namespace
+using security::v1::PublicKey;
+#endif // NDN_CXX_KEEP_SECURITY_V1_ALIASES
+
+} // namespace ndn
+
+#endif // NDN_SECURITY_V1_PUBLIC_KEY_HPP