security: Add key type in PublicKey (in order to support multiple signature type)

Change-Id: Ic3cb7276a3bc6d1d1daf066dbe865503fe66c762
Refs: #1648
Refs: #1649
Refs: #1660
diff --git a/src/security/public-key.cpp b/src/security/public-key.cpp
index ff44dd2..212bc3a 100644
--- a/src/security/public-key.cpp
+++ b/src/security/public-key.cpp
@@ -33,12 +33,15 @@
 namespace ndn {
 
 static OID RSA_OID("1.2.840.113549.1.1.1");
+static OID ECDSA_OID("1.2.840.10045.2.1");
 
 PublicKey::PublicKey()
+  : m_type(KEY_TYPE_NULL)
 {
 }
 
 PublicKey::PublicKey(const uint8_t* keyDerBuf, size_t keyDerSize)
+  : m_type(KEY_TYPE_NULL)
 {
   StringSource src(keyDerBuf, keyDerSize, true);
   decode(src);
@@ -90,8 +93,12 @@
           OID algorithm;
           algorithm.decode(algorithmInfo);
 
-          if (algorithm != RSA_OID)
-            throw Error("Only RSA public keys are supported for now (" +
+          if (algorithm == RSA_OID)
+            m_type = KEY_TYPE_RSA;
+          else if (algorithm == ECDSA_OID)
+            m_type = KEY_TYPE_ECDSA;
+          else
+            throw Error("Only RSA/ECDSA public keys are supported for now (" +
                         algorithm.toString() + " requested)");
         }
       }
@@ -100,6 +107,7 @@
     }
   catch (CryptoPP::BERDecodeErr& err)
     {
+      m_type = KEY_TYPE_NULL;
       throw Error("PublicKey decoding error");
     }
 }
diff --git a/src/security/public-key.hpp b/src/security/public-key.hpp
index 8c2154f..243bccc 100644
--- a/src/security/public-key.hpp
+++ b/src/security/public-key.hpp
@@ -65,38 +65,45 @@
    */
   PublicKey(const uint8_t* keyDerBuf, size_t keyDerSize);
 
-  inline const Buffer&
+  const Buffer&
   get() const
   {
     return m_key;
   }
 
-  inline void
+  void
   set(const uint8_t* keyDerBuf, size_t keyDerSize)
   {
     Buffer buf(keyDerBuf, keyDerSize);
     m_key.swap(buf);
   }
 
+  KeyType
+  getKeyType() const
+  {
+    return m_type;
+  }
+
   void
   encode(CryptoPP::BufferedTransformation& out) const;
 
   void
   decode(CryptoPP::BufferedTransformation& in);
 
-  inline bool
+  bool
   operator==(const PublicKey& key) const
   {
     return m_key == key.m_key;
   }
 
-  inline bool
+  bool
   operator!=(const PublicKey& key) const
   {
     return m_key != key.m_key;
   }
 
 private:
+  KeyType m_type;
   Buffer m_key;
 };
 
diff --git a/src/security/security-common.hpp b/src/security/security-common.hpp
index 24c424b..072ea74 100644
--- a/src/security/security-common.hpp
+++ b/src/security/security-common.hpp
@@ -26,11 +26,13 @@
 
 enum KeyType {
   KEY_TYPE_RSA,
+  KEY_TYPE_ECDSA,
   // KEY_TYPE_DSA,
-  KEY_TYPE_AES
+  KEY_TYPE_AES,
   // KEY_TYPE_DES,
   // KEY_TYPE_RC4,
   // KEY_TYPE_RC2
+  KEY_TYPE_NULL
 };
 
 enum KeyClass {
diff --git a/tests/unit-tests/security/test-public-key.cpp b/tests/unit-tests/security/test-public-key.cpp
new file mode 100644
index 0000000..bf0a00c
--- /dev/null
+++ b/tests/unit-tests/security/test-public-key.cpp
@@ -0,0 +1,75 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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 "security/public-key.hpp"
+#include "security/cryptopp.hpp"
+#include "encoding/buffer-stream.hpp"
+
+#include "boost-test.hpp"
+
+
+namespace ndn {
+
+BOOST_AUTO_TEST_SUITE(SecurityTestPublicKey)
+
+const std::string RSA_DER("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuFoDcNtffwbfFix64fw0\
+hI2tKMkFrc6Ex7yw0YLMK9vGE8lXOyBl/qXabow6RCz+GldmFN6E2Qhm1+AX3Zm5\
+sj3H53/HPtzMefvMQ9X7U+lK8eNMWawpRzvBh4/36VrK/awlkNIVIQ9aXj6q6BVe\
+zL+zWT/WYemLq/8A1/hHWiwCtfOH1xQhGqWHJzeSgwIgOOrzxTbRaCjhAb1u2TeV\
+yx/I9H/DV+AqSHCaYbB92HDcDN0kqwSnUf5H1+osE9MR5DLBLhXdSiULSgxT3Or/\
+y2QgsgUK59WrjhlVMPEiHHRs15NZJbL1uQFXjgScdEarohcY3dilqotineFZCeN8\
+DwIDAQAB");
+const std::string ECDSA_DER("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENZpqkPJDj8uhSpffOiCbvSYMLsGB\
+1Eo/WU6mrexjGvduQXjqwon/eSHFI6EgHZk8L9KfiV5XVtVsk2g5wIpJVg==");
+
+BOOST_AUTO_TEST_CASE(RSA)
+{
+  using namespace CryptoPP;
+
+  OBufferStream os;
+  StringSource ss(reinterpret_cast<const uint8_t*>(RSA_DER.c_str()), RSA_DER.size(),
+                  true, new Base64Decoder(new FileSink(os)));
+
+  shared_ptr<PublicKey> publicKey;
+  BOOST_REQUIRE_NO_THROW(publicKey = shared_ptr<PublicKey>(new PublicKey(os.buf()->buf(),
+                                                                         os.buf()->size())));
+
+  BOOST_CHECK_EQUAL(publicKey->getKeyType(), KEY_TYPE_RSA);
+}
+
+BOOST_AUTO_TEST_CASE(ECDSA)
+{
+  using namespace CryptoPP;
+
+  OBufferStream os;
+  StringSource ss(reinterpret_cast<const uint8_t*>(ECDSA_DER.c_str()), ECDSA_DER.size(),
+                  true, new Base64Decoder(new FileSink(os)));
+
+  shared_ptr<PublicKey> publicKey;
+  BOOST_REQUIRE_NO_THROW(publicKey = shared_ptr<PublicKey>(new PublicKey(os.buf()->buf(),
+                                                                         os.buf()->size())));
+
+  BOOST_CHECK_EQUAL(publicKey->getKeyType(), KEY_TYPE_ECDSA);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace ndn