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/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