security: Update Signature abstraction to match 0.1.1 spec

This commit removes intermediate SignatureWithPublicKey data
structure.  All uses of such data structure should be replaced with just
Signature and check that KeyLocator is present (hasKeyLocator()).

Change-Id: I1157e05c6a717ea28df91c4bfd76c7145b520a15
Refs: #1750
diff --git a/src/security/conf/checker.hpp b/src/security/conf/checker.hpp
index 11f4da1..9284191 100644
--- a/src/security/conf/checker.hpp
+++ b/src/security/conf/checker.hpp
@@ -166,20 +166,17 @@
     if (signature.getType() == Tlv::DigestSha256)
       return 0;
 
-    shared_ptr<SignatureWithPublicKey> publicKeySig;
-
     try
       {
         switch (signature.getType())
           {
           case Tlv::SignatureSha256WithRsa:
-            {
-              publicKeySig = make_shared<SignatureSha256WithRsa>(signature);
-              break;
-            }
           case Tlv::SignatureSha256WithEcdsa:
             {
-              publicKeySig = make_shared<SignatureSha256WithEcdsa>(signature);
+              if (!signature.hasKeyLocator()) {
+                onValidationFailed(packet.shared_from_this(),
+                                   "Missing KeyLocator in SignatureInfo");
+              }
               break;
             }
           default:
@@ -205,7 +202,7 @@
       }
 
     std::string failInfo;
-    if (m_keyLocatorChecker->check(packet, publicKeySig->getKeyLocator(), failInfo))
+    if (m_keyLocatorChecker->check(packet, signature.getKeyLocator(), failInfo))
       return 0;
     else
       {
@@ -308,20 +305,17 @@
         return -1;
       }
 
-    shared_ptr<SignatureWithPublicKey> publicKeySig;
-
     try
       {
         switch (signature.getType())
           {
           case Tlv::SignatureSha256WithRsa:
-            {
-              publicKeySig = make_shared<SignatureSha256WithRsa>(signature);
-              break;
-            }
           case Tlv::SignatureSha256WithEcdsa:
             {
-              publicKeySig = make_shared<SignatureSha256WithEcdsa>(signature);
+              if (!signature.hasKeyLocator()) {
+                onValidationFailed(packet.shared_from_this(),
+                                   "Missing KeyLocator in SignatureInfo");
+              }
               break;
             }
           default:
@@ -333,7 +327,7 @@
             }
           }
 
-        const Name& keyLocatorName = publicKeySig->getKeyLocator().getName();
+        const Name& keyLocatorName = signature.getKeyLocator().getName();
 
         if (m_signers.find(keyLocatorName) == m_signers.end())
           {
@@ -343,7 +337,7 @@
             return -1;
           }
 
-        if (Validator::verifySignature(packet, *publicKeySig,
+        if (Validator::verifySignature(packet, signature,
                                        m_signers[keyLocatorName]->getPublicKeyInfo()))
           {
             onValidated(packet.shared_from_this());
diff --git a/src/security/digest-sha256.cpp b/src/security/digest-sha256.cpp
new file mode 100644
index 0000000..6d450a2
--- /dev/null
+++ b/src/security/digest-sha256.cpp
@@ -0,0 +1,38 @@
+/* -*- 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 "digest-sha256.hpp"
+
+namespace ndn {
+
+DigestSha256::DigestSha256()
+  : Signature(SignatureInfo(Tlv::DigestSha256))
+{
+}
+
+DigestSha256::DigestSha256(const Signature& signature)
+  : Signature(signature)
+{
+  if (getType() != Tlv::DigestSha256)
+    throw Error("Incorrect signature type");
+}
+
+} // namespace ndn
diff --git a/src/security/digest-sha256.hpp b/src/security/digest-sha256.hpp
index 6221ee6..d3a15de 100644
--- a/src/security/digest-sha256.hpp
+++ b/src/security/digest-sha256.hpp
@@ -43,21 +43,11 @@
     }
   };
 
-  DigestSha256()
-  {
-    m_info = Block(Tlv::SignatureInfo);
-
-    m_type = Tlv::DigestSha256;
-    m_info.push_back(nonNegativeIntegerBlock(Tlv::SignatureType, Tlv::DigestSha256));
-  }
+  DigestSha256();
 
   explicit
-  DigestSha256(const Signature& signature)
-    : Signature(signature)
-  {
-    if (getType() != Tlv::DigestSha256)
-      throw Error("Incorrect signature type");
-  }
+  DigestSha256(const Signature& signature);
+
 };
 
 } // namespace ndn
diff --git a/src/security/key-chain.cpp b/src/security/key-chain.cpp
index 1d9f100..180d37d 100644
--- a/src/security/key-chain.cpp
+++ b/src/security/key-chain.cpp
@@ -297,13 +297,14 @@
 {
   shared_ptr<IdentityCertificate> certificate = m_pib->getCertificate(certificateName);
 
-  shared_ptr<SignatureWithPublicKey> sig =
-    determineSignatureWithPublicKey(certificate->getPublicKeyInfo().getKeyType());
+  KeyLocator keyLocator(certificate->getName().getPrefix(-1));
+  shared_ptr<Signature> sig =
+    determineSignatureWithPublicKey(keyLocator, certificate->getPublicKeyInfo().getKeyType());
 
   if (!static_cast<bool>(sig))
     throw SecTpm::Error("unknown key type");
 
-  sig->setKeyLocator(certificate->getName().getPrefix(-1));
+
   // For temporary usage, we support SHA256 only, but will support more.
   sig->setValue(m_tpm->signInTpm(buffer, bufferLength,
                                  certificate->getPublicKeyName(),
@@ -349,13 +350,14 @@
   if (!m_tpm->doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
     throw SecTpm::Error("Private key does not exist");
 
-  shared_ptr<SignatureWithPublicKey> sig =
-    determineSignatureWithPublicKey(cert.getPublicKeyInfo().getKeyType());
+
+  KeyLocator keyLocator(cert.getName().getPrefix(-1));
+  shared_ptr<Signature> sig =
+    determineSignatureWithPublicKey(keyLocator, cert.getPublicKeyInfo().getKeyType());
 
   if (!static_cast<bool>(sig))
     throw SecTpm::Error("unknown key type");
 
-  sig->setKeyLocator(cert.getName().getPrefix(-1)); // implicit conversion should take care
   signPacketWrapper(cert, *sig, keyName, DIGEST_ALGORITHM_SHA256);
 }
 
@@ -419,8 +421,9 @@
   m_pib->addCertificateAsIdentityDefault(securedBag.getCertificate());
 }
 
-shared_ptr<SignatureWithPublicKey>
-KeyChain::determineSignatureWithPublicKey(KeyType keyType, DigestAlgorithm digestAlgorithm)
+shared_ptr<Signature>
+KeyChain::determineSignatureWithPublicKey(const KeyLocator& keyLocator,
+                                          KeyType keyType, DigestAlgorithm digestAlgorithm)
 {
   switch (keyType)
     {
@@ -428,20 +431,20 @@
       {
         // For temporary usage, we support SHA256 only, but will support more.
         if (digestAlgorithm != DIGEST_ALGORITHM_SHA256)
-          return shared_ptr<SignatureWithPublicKey>();
+          return shared_ptr<Signature>();
 
-        return make_shared<SignatureSha256WithRsa>();
+        return make_shared<SignatureSha256WithRsa>(keyLocator);
       }
     case KEY_TYPE_ECDSA:
       {
         // For temporary usage, we support SHA256 only, but will support more.
         if (digestAlgorithm != DIGEST_ALGORITHM_SHA256)
-          return shared_ptr<SignatureWithPublicKey>();
+          return shared_ptr<Signature>();
 
-        return make_shared<SignatureSha256WithEcdsa>();
+        return make_shared<SignatureSha256WithEcdsa>(keyLocator);
       }
     default:
-      return shared_ptr<SignatureWithPublicKey>();
+      return shared_ptr<Signature>();
     }
 }
 
diff --git a/src/security/key-chain.hpp b/src/security/key-chain.hpp
index bb04f5c..0cc3cb3 100644
--- a/src/security/key-chain.hpp
+++ b/src/security/key-chain.hpp
@@ -642,8 +642,9 @@
    *
    * An empty pointer will be returned if there is no valid signature.
    */
-  shared_ptr<SignatureWithPublicKey>
-  determineSignatureWithPublicKey(KeyType keyType,
+  shared_ptr<Signature>
+  determineSignatureWithPublicKey(const KeyLocator& keyLocator,
+                                  KeyType keyType,
                                   DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256);
 
   /**
@@ -773,15 +774,14 @@
 void
 KeyChain::sign(T& packet, const IdentityCertificate& certificate)
 {
+  KeyLocator keyLocator(certificate.getName().getPrefix(-1));
 
-  shared_ptr<SignatureWithPublicKey> signature =
-    determineSignatureWithPublicKey(certificate.getPublicKeyInfo().getKeyType());
+  shared_ptr<Signature> signature =
+    determineSignatureWithPublicKey(keyLocator, certificate.getPublicKeyInfo().getKeyType());
 
   if (!static_cast<bool>(signature))
     throw SecPublicInfo::Error("unknown key type!");
 
-  signature->setKeyLocator(certificate.getName().getPrefix(-1));
-
   signPacketWrapper(packet, *signature,
                     certificate.getPublicKeyName(),
                     DIGEST_ALGORITHM_SHA256);
diff --git a/src/security/sec-public-info-sqlite3.cpp b/src/security/sec-public-info-sqlite3.cpp
index 354c5aa..b2bd512 100644
--- a/src/security/sec-public-info-sqlite3.cpp
+++ b/src/security/sec-public-info-sqlite3.cpp
@@ -481,29 +481,14 @@
     {
       // this will throw an exception if the signature is not the standard one
       // or there is no key locator present
-      switch (certificate.getSignature().getType())
-        {
-        case Tlv::SignatureSha256WithRsa:
-          {
-            SignatureSha256WithRsa signature(certificate.getSignature());
-            std::string signerName = signature.getKeyLocator().getName().toUri();
-
-            sqlite3_bind_text(statement, 2, signerName, SQLITE_STATIC);
-            break;
-          }
-        case Tlv::SignatureSha256WithEcdsa:
-          {
-            SignatureSha256WithEcdsa signature(certificate.getSignature());
-            std::string signerName = signature.getKeyLocator().getName().toUri();
-
-            sqlite3_bind_text(statement, 2, signerName, SQLITE_STATIC);
-            break;
-          }
-        default:
-          return;
-        }
+      std::string signerName = certificate.getSignature().getKeyLocator().getName().toUri();
+      sqlite3_bind_text(statement, 2, signerName, SQLITE_STATIC);
     }
-  catch (std::runtime_error& e)
+  catch (Tlv::Error& e)
+    {
+      return;
+    }
+  catch (KeyLocator::Error& e)
     {
       return;
     }
diff --git a/src/security/sec-rule-relative.cpp b/src/security/sec-rule-relative.cpp
index 6350fd5..42272bc 100644
--- a/src/security/sec-rule-relative.cpp
+++ b/src/security/sec-rule-relative.cpp
@@ -59,8 +59,14 @@
   Name dataName = data.getName();
   try
     {
-      SignatureWithPublicKey sig(data.getSignature());
-      Name signerName = sig.getKeyLocator().getName();
+      if (!data.getSignature().hasKeyLocator())
+        return false;
+
+      const KeyLocator& keyLocator = data.getSignature().getKeyLocator();
+      if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
+        return false;
+
+      const Name& signerName = keyLocator.getName();
       return satisfy(dataName, signerName);
     }
   catch (Tlv::Error& e)
@@ -104,8 +110,14 @@
 {
   try
     {
-      SignatureWithPublicKey sig(data.getSignature());
-      Name signerName = sig.getKeyLocator().getName();
+      if (!data.getSignature().hasKeyLocator())
+        return false;
+
+      const KeyLocator& keyLocator = data.getSignature().getKeyLocator();
+      if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
+        return false;
+
+      const Name& signerName = keyLocator.getName();
       return m_signerNameRegex.match(signerName);
     }
   catch (Tlv::Error& e)
diff --git a/src/security/sec-rule-specific.cpp b/src/security/sec-rule-specific.cpp
index 75f45b9..af89e91 100644
--- a/src/security/sec-rule-specific.cpp
+++ b/src/security/sec-rule-specific.cpp
@@ -66,8 +66,14 @@
 
   try
     {
-      SignatureWithPublicKey sig(data.getSignature());
-      Name signerName = sig.getKeyLocator().getName();
+      if (!data.getSignature().hasKeyLocator())
+        return false;
+
+      const KeyLocator& keyLocator = data.getSignature().getKeyLocator();
+      if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
+        return false;
+
+      const Name& signerName = keyLocator.getName();
       return m_signerRegex->match(signerName);
     }
   catch (Tlv::Error& e)
diff --git a/src/security/signature-sha256-with-ecdsa.cpp b/src/security/signature-sha256-with-ecdsa.cpp
new file mode 100644
index 0000000..1f67425
--- /dev/null
+++ b/src/security/signature-sha256-with-ecdsa.cpp
@@ -0,0 +1,42 @@
+/* -*- 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 "signature-sha256-with-ecdsa.hpp"
+
+namespace ndn {
+
+SignatureSha256WithEcdsa::SignatureSha256WithEcdsa(const KeyLocator& keyLocator)
+  : Signature(SignatureInfo(Tlv::SignatureSha256WithEcdsa, keyLocator))
+{
+}
+
+SignatureSha256WithEcdsa::SignatureSha256WithEcdsa(const Signature& signature)
+  : Signature(signature)
+{
+  if (getType() != Tlv::SignatureSha256WithEcdsa)
+    throw Error("Incorrect signature type");
+
+  if (!hasKeyLocator()) {
+    throw Error("KeyLocator is missing");
+  }
+}
+
+} // namespace ndn
diff --git a/src/security/signature-sha256-with-ecdsa.hpp b/src/security/signature-sha256-with-ecdsa.hpp
index 5bf0500..a20e6b0 100644
--- a/src/security/signature-sha256-with-ecdsa.hpp
+++ b/src/security/signature-sha256-with-ecdsa.hpp
@@ -22,38 +22,32 @@
 #ifndef NDN_SECURITY_SIGNATURE_SHA256_WITH_ECDSA_HPP
 #define NDN_SECURITY_SIGNATURE_SHA256_WITH_ECDSA_HPP
 
-#include "signature-with-public-key.hpp"
+#include "../signature.hpp"
 
 namespace ndn {
 
 /**
  * represents a Sha256WithEcdsa signature.
  */
-class SignatureSha256WithEcdsa : public SignatureWithPublicKey
+class SignatureSha256WithEcdsa : public Signature
 {
 public:
-  class Error : public SignatureWithPublicKey::Error
+  class Error : public Signature::Error
   {
   public:
     explicit
     Error(const std::string& what)
-      : SignatureWithPublicKey::Error(what)
+      : Signature::Error(what)
     {
     }
   };
 
-  SignatureSha256WithEcdsa()
-    : SignatureWithPublicKey(Tlv::SignatureSha256WithEcdsa)
-  {
-  }
+  explicit
+  SignatureSha256WithEcdsa(const KeyLocator& keyLocator = KeyLocator());
 
   explicit
-  SignatureSha256WithEcdsa(const Signature& signature)
-    : SignatureWithPublicKey(signature)
-  {
-    if (getType() != Tlv::SignatureSha256WithEcdsa)
-      throw Error("Incorrect signature type");
-  }
+  SignatureSha256WithEcdsa(const Signature& signature);
+
 };
 
 } // namespace ndn
diff --git a/src/security/signature-sha256-with-rsa.cpp b/src/security/signature-sha256-with-rsa.cpp
new file mode 100644
index 0000000..bc4fe65
--- /dev/null
+++ b/src/security/signature-sha256-with-rsa.cpp
@@ -0,0 +1,42 @@
+/* -*- 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 "signature-sha256-with-rsa.hpp"
+
+namespace ndn {
+
+SignatureSha256WithRsa::SignatureSha256WithRsa(const KeyLocator& keyLocator)
+  : Signature(SignatureInfo(Tlv::SignatureSha256WithRsa, keyLocator))
+{
+}
+
+SignatureSha256WithRsa::SignatureSha256WithRsa(const Signature& signature)
+  : Signature(signature)
+{
+  if (getType() != Tlv::SignatureSha256WithRsa)
+    throw Error("Incorrect signature type");
+
+  if (!hasKeyLocator()) {
+    throw Error("KeyLocator is missing");
+  }
+}
+
+} // namespace ndn
diff --git a/src/security/signature-sha256-with-rsa.hpp b/src/security/signature-sha256-with-rsa.hpp
index fc60248..94f9e30 100644
--- a/src/security/signature-sha256-with-rsa.hpp
+++ b/src/security/signature-sha256-with-rsa.hpp
@@ -22,38 +22,31 @@
 #ifndef NDN_SECURITY_SIGNATURE_SHA256_WITH_RSA_HPP
 #define NDN_SECURITY_SIGNATURE_SHA256_WITH_RSA_HPP
 
-#include "signature-with-public-key.hpp"
+#include "../signature.hpp"
 
 namespace ndn {
 
 /**
  * Represent a SHA256-with-RSA signature.
  */
-class SignatureSha256WithRsa : public SignatureWithPublicKey
+class SignatureSha256WithRsa : public Signature
 {
 public:
-  class Error : public SignatureWithPublicKey::Error
+  class Error : public Signature::Error
   {
   public:
     explicit
     Error(const std::string& what)
-      : SignatureWithPublicKey::Error(what)
+      : Signature::Error(what)
     {
     }
   };
 
-  SignatureSha256WithRsa()
-    : SignatureWithPublicKey(Tlv::SignatureSha256WithRsa)
-  {
-  }
+  explicit
+  SignatureSha256WithRsa(const KeyLocator& keyLocator = KeyLocator());
 
   explicit
-  SignatureSha256WithRsa(const Signature& signature)
-    : SignatureWithPublicKey(signature)
-  {
-    if (getType() != Tlv::SignatureSha256WithRsa)
-      throw Error("Incorrect signature type");
-  }
+  SignatureSha256WithRsa(const Signature& signature);
 };
 
 } // namespace ndn
diff --git a/src/security/signature-with-public-key.hpp b/src/security/signature-with-public-key.hpp
deleted file mode 100644
index abaa85a..0000000
--- a/src/security/signature-with-public-key.hpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- 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.
- */
-
-#ifndef NDN_SECURITY_SIGNATURE_WITH_PUBLIC_KEY_HPP
-#define NDN_SECURITY_SIGNATURE_WITH_PUBLIC_KEY_HPP
-
-#include "../data.hpp"
-#include "../encoding/tlv.hpp"
-
-namespace ndn {
-
-/**
- * Base class of public key signature.
- */
-class SignatureWithPublicKey : public Signature
-{
-public:
-  class Error : public Signature::Error
-  {
-  public:
-    explicit
-    Error(const std::string& what)
-      : Signature::Error(what)
-    {
-    }
-  };
-
-  explicit
-  SignatureWithPublicKey(const Tlv::SignatureTypeValue& signatureType)
-  {
-    m_info = Block(Tlv::SignatureInfo);
-
-    m_type = signatureType;
-    m_info.push_back(nonNegativeIntegerBlock(Tlv::SignatureType, signatureType));
-    m_info.push_back(m_keyLocator.wireEncode());
-  }
-
-  explicit
-  SignatureWithPublicKey(const Signature& signature)
-    : Signature(signature)
-  {
-    m_info.parse();
-    Block::element_const_iterator i = m_info.find(Tlv::KeyLocator);
-    if (i != m_info.elements_end())
-      {
-        m_keyLocator.wireDecode(*i);
-      }
-  }
-
-  const KeyLocator&
-  getKeyLocator() const
-  {
-    return m_keyLocator;
-  }
-
-  void
-  setKeyLocator(const KeyLocator& keyLocator)
-  {
-    m_keyLocator = keyLocator;
-
-    m_info.remove(ndn::Tlv::KeyLocator);
-    m_info.push_back(m_keyLocator.wireEncode());
-  }
-
-private:
-  KeyLocator m_keyLocator;
-};
-
-} // namespace ndn
-
-#endif //NDN_SECURITY_SIGNATURE_WITH_PUBLIC_KEY_HPP
diff --git a/src/security/validator-config.cpp b/src/security/validator-config.cpp
index b9b1bed..387cfe0 100644
--- a/src/security/validator-config.cpp
+++ b/src/security/validator-config.cpp
@@ -490,9 +490,11 @@
       Signature signature(interestName[signed_interest::POS_SIG_INFO].blockFromValue(),
                           interestName[signed_interest::POS_SIG_VALUE].blockFromValue());
 
-      SignatureWithPublicKey publicKeySig(signature);
+      if (!signature.hasKeyLocator())
+        return onValidationFailed(interest.shared_from_this(),
+                                  "No valid KeyLocator");
 
-      const KeyLocator& keyLocator = publicKeySig.getKeyLocator();
+      const KeyLocator& keyLocator = signature.getKeyLocator();
 
       if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
         return onValidationFailed(interest.shared_from_this(),
@@ -523,7 +525,7 @@
       if (checkResult == 0)
         {
           checkSignature<Interest, OnInterestValidated, OnInterestValidationFailed>
-            (interest, publicKeySig, nSteps,
+            (interest, signature, nSteps,
              bind(&ValidatorConfig::checkTimestamp, this, _1,
                   keyName, onValidated, onValidationFailed),
              onValidationFailed,
diff --git a/src/security/validator-config.hpp b/src/security/validator-config.hpp
index 4a2ce58..d3e4be4 100644
--- a/src/security/validator-config.hpp
+++ b/src/security/validator-config.hpp
@@ -304,18 +304,15 @@
                                   "Sha256 Signature cannot be verified!");
     }
 
-  shared_ptr<SignatureWithPublicKey> publicKeySig;
-
   try {
     switch (signature.getType()) {
     case Tlv::SignatureSha256WithRsa:
-      {
-        publicKeySig = make_shared<SignatureSha256WithRsa>(signature);
-        break;
-      }
     case Tlv::SignatureSha256WithEcdsa:
       {
-        publicKeySig = make_shared<SignatureSha256WithEcdsa>(signature);
+        if (!signature.hasKeyLocator()) {
+          return onValidationFailed(packet.shared_from_this(),
+                                    "Missing KeyLocator in SignatureInfo");
+        }
         break;
       }
     default:
@@ -332,8 +329,11 @@
                               "Cannot decode KeyLocator in public key signature");
   }
 
+  if (signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name) {
+    return onValidationFailed(packet.shared_from_this(), "Unsupported KeyLocator type");
+  }
 
-  Name keyLocatorName = publicKeySig->getKeyLocator().getName();
+  const Name& keyLocatorName = signature.getKeyLocator().getName();
 
   shared_ptr<const Certificate> trustedCert;
 
@@ -347,7 +347,7 @@
 
   if (static_cast<bool>(trustedCert))
     {
-      if (verifySignature(packet, *publicKeySig, trustedCert->getPublicKeyInfo()))
+      if (verifySignature(packet, signature, trustedCert->getPublicKeyInfo()))
         return onValidated(packet.shared_from_this());
       else
         return onValidationFailed(packet.shared_from_this(),
@@ -379,7 +379,7 @@
       return;
     }
 
-  return onValidationFailed(packet.shared_from_this(), "Unsupported Signature Type!");
+  return onValidationFailed(packet.shared_from_this(), "Unsupported Signature Type");
 }
 
 template<class Packet, class OnValidated, class OnFailed>
diff --git a/src/security/validator-regex.cpp b/src/security/validator-regex.cpp
index e998d8c..97f796c 100644
--- a/src/security/validator-regex.cpp
+++ b/src/security/validator-regex.cpp
@@ -108,9 +108,19 @@
         {
           try
             {
-              SignatureWithPublicKey sig(data.getSignature());
+              if (!data.getSignature().hasKeyLocator())
+                return onValidationFailed(data.shared_from_this(),
+                                          "Key Locator is missing in Data packet: " +
+                                          data.getName().toUri());
 
-              Name keyLocatorName = sig.getKeyLocator().getName();
+              const KeyLocator& keyLocator = data.getSignature().getKeyLocator();
+              if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
+                return onValidationFailed(data.shared_from_this(),
+                                          "Key Locator is not a name: " +
+                                          data.getName().toUri());
+
+
+              const Name& keyLocatorName = keyLocator.getName();
               shared_ptr<const Certificate> trustedCert;
               if (m_trustAnchors.end() == m_trustAnchors.find(keyLocatorName))
                 trustedCert = m_certificateCache->getCertificate(keyLocatorName);
@@ -119,7 +129,7 @@
 
               if (static_cast<bool>(trustedCert))
                 {
-                  if (verifySignature(data, sig, trustedCert->getPublicKeyInfo()))
+                  if (verifySignature(data, data.getSignature(), trustedCert->getPublicKeyInfo()))
                     return onValidated(data.shared_from_this());
                   else
                     return onValidationFailed(data.shared_from_this(),
@@ -138,7 +148,7 @@
                     bind(&ValidatorRegex::onCertificateValidationFailed, this, _1, _2,
                          data.shared_from_this(), onValidationFailed);
 
-                  Interest interest(sig.getKeyLocator().getName());
+                  Interest interest(keyLocatorName);
                   shared_ptr<ValidationRequest> nextStep =
                     make_shared<ValidationRequest>(interest,
                                                    onKeyValidated,
@@ -151,12 +161,6 @@
                   return;
                 }
             }
-          catch (SignatureWithPublicKey::Error& e)
-            {
-              return onValidationFailed(data.shared_from_this(),
-                                        "Require sub-class of SignatureWithPublicKey: " +
-                                        data.getName().toUri());
-            }
           catch (Tlv::Error& e)
             {
               return onValidationFailed(data.shared_from_this(),
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
index 5edb852..2bc9364 100644
--- a/src/security/validator.cpp
+++ b/src/security/validator.cpp
@@ -121,16 +121,13 @@
 bool
 Validator::verifySignature(const Data& data, const PublicKey& key)
 {
-  shared_ptr<SignatureWithPublicKey> publicKeySig =
-    determineSignatureWithPublicKey(data.getSignature());
-
-  if (!static_cast<bool>(publicKeySig))
+  if (!data.getSignature().hasKeyLocator())
     return false;
 
   return verifySignature(data.wireEncode().value(),
                          data.wireEncode().value_size() -
                          data.getSignature().getValue().size(),
-                         *publicKeySig, key);
+                         data.getSignature(), key);
 }
 
 bool
@@ -148,14 +145,12 @@
       Signature sig(interestName[-2].blockFromValue(),
                     interestName[-1].blockFromValue());
 
-      shared_ptr<SignatureWithPublicKey> publicKeySig = determineSignatureWithPublicKey(sig);
-
-      if (!static_cast<bool>(publicKeySig))
+      if (!sig.hasKeyLocator())
         return false;
 
       return verifySignature(nameBlock.value(),
                              nameBlock.value_size() - interestName[-1].size(),
-                             *publicKeySig, key);
+                             sig, key);
     }
   catch (Block::Error& e)
     {
@@ -166,7 +161,7 @@
 bool
 Validator::verifySignature(const uint8_t* buf,
                            const size_t size,
-                           const SignatureWithPublicKey& sig,
+                           const Signature& sig,
                            const PublicKey& key)
 {
   try
@@ -286,28 +281,6 @@
     }
 }
 
-shared_ptr<SignatureWithPublicKey>
-Validator::determineSignatureWithPublicKey(const Signature& signature)
-{
-  try {
-    switch (signature.getType())
-      {
-      case Tlv::SignatureSha256WithRsa:
-        return make_shared<SignatureSha256WithRsa>(signature);
-      case Tlv::SignatureSha256WithEcdsa:
-        return make_shared<SignatureSha256WithEcdsa>(signature);
-      default:
-        return shared_ptr<SignatureWithPublicKey>();
-      }
-  }
-  catch (Tlv::Error& e) {
-    return shared_ptr<SignatureWithPublicKey>();
-  }
-  catch (KeyLocator::Error& e) {
-    return shared_ptr<SignatureWithPublicKey>();
-  }
-}
-
 void
 Validator::onTimeout(const Interest& interest,
                      int remainingRetries,
diff --git a/src/security/validator.hpp b/src/security/validator.hpp
index e9bf37e..9a3b4a3 100644
--- a/src/security/validator.hpp
+++ b/src/security/validator.hpp
@@ -107,7 +107,7 @@
 
   /// @brief Verify the blob using the publicKey against the signature.
   static bool
-  verifySignature(const Buffer& blob, const SignatureWithPublicKey& sig, const PublicKey& publicKey)
+  verifySignature(const Buffer& blob, const Signature& sig, const PublicKey& publicKey)
   {
     return verifySignature(blob.buf(), blob.size(), sig, publicKey);
   }
@@ -115,7 +115,7 @@
   /// @brief Verify the data using the publicKey against the SHA256-RSA signature.
   static bool
   verifySignature(const Data& data,
-                  const SignatureWithPublicKey& sig,
+                  const Signature& sig,
                   const PublicKey& publicKey)
   {
     return verifySignature(data.wireEncode().value(),
@@ -129,7 +129,7 @@
    */
   static bool
   verifySignature(const Interest& interest,
-                  const SignatureWithPublicKey& sig,
+                  const Signature& sig,
                   const PublicKey& publicKey)
   {
     if (interest.getName().size() < 2)
@@ -146,7 +146,7 @@
   static bool
   verifySignature(const uint8_t* buf,
                   const size_t size,
-                  const SignatureWithPublicKey& sig,
+                  const Signature& sig,
                   const PublicKey& publicKey);
 
 
@@ -248,9 +248,6 @@
            const OnInterestValidationFailed& onValidationFailed,
            int nSteps);
 
-  static shared_ptr<SignatureWithPublicKey>
-  determineSignatureWithPublicKey(const Signature& signature);
-
   /// Hooks
 
   /**
diff --git a/src/signature-info.cpp b/src/signature-info.cpp
new file mode 100644
index 0000000..1b8203d
--- /dev/null
+++ b/src/signature-info.cpp
@@ -0,0 +1,186 @@
+/* -*- 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 "signature-info.hpp"
+
+namespace ndn {
+
+SignatureInfo::SignatureInfo()
+  : m_type(-1)
+  , m_hasKeyLocator(false)
+{
+}
+
+SignatureInfo::SignatureInfo(Tlv::SignatureTypeValue type)
+  : m_type(type)
+  , m_hasKeyLocator(false)
+{
+}
+
+SignatureInfo::SignatureInfo(Tlv::SignatureTypeValue type, const KeyLocator& keyLocator)
+  : m_type(type)
+  , m_hasKeyLocator(true)
+  , m_keyLocator(keyLocator)
+{
+}
+
+SignatureInfo::SignatureInfo(const Block& block)
+{
+  wireDecode(block);
+}
+
+void
+SignatureInfo::setSignatureType(Tlv::SignatureTypeValue type)
+{
+  m_wire.reset();
+  m_type = type;
+}
+
+void
+SignatureInfo::setKeyLocator(const KeyLocator& keyLocator)
+{
+  m_wire.reset();
+  m_keyLocator = keyLocator;
+  m_hasKeyLocator = true;
+}
+
+const KeyLocator&
+SignatureInfo::getKeyLocator() const
+{
+  if (m_hasKeyLocator)
+    return m_keyLocator;
+  else
+    throw Error("KeyLocator does not exist");
+}
+
+void
+SignatureInfo::appendTypeSpecificTlv(const Block& block)
+{
+  m_otherTlvs.push_back(block);
+}
+
+
+const Block&
+SignatureInfo::getTypeSpecificTlv(uint32_t type) const
+{
+  for (std::list<Block>::const_iterator i = m_otherTlvs.begin();
+       i != m_otherTlvs.end(); i++) {
+    if (i->type() == type)
+      return *i;
+  }
+
+  throw Error("(SignatureInfo::getTypeSpecificTlv) Requested a non-existed type [" +
+              boost::lexical_cast<std::string>(type) + "] from SignatureInfo");
+}
+
+template<bool T>
+size_t
+SignatureInfo::wireEncode(EncodingImpl<T>& block) const
+{
+  size_t totalLength = 0;
+
+  for (std::list<Block>::const_reverse_iterator i = m_otherTlvs.rbegin();
+       i != m_otherTlvs.rend(); i++) {
+    totalLength += block.appendBlock(*i);
+  }
+
+  if (m_hasKeyLocator)
+    totalLength += m_keyLocator.wireEncode(block);
+
+  totalLength += prependNonNegativeIntegerBlock(block, Tlv::SignatureType, m_type);
+
+  totalLength += block.prependVarNumber(totalLength);
+  totalLength += block.prependVarNumber(Tlv::SignatureInfo);
+  return totalLength;
+}
+
+template size_t
+SignatureInfo::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+SignatureInfo::wireEncode<false>(EncodingImpl<false>& block) const;
+
+
+const Block&
+SignatureInfo::wireEncode() const
+{
+  if (m_wire.hasWire())
+    return m_wire;
+
+  EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  m_wire = buffer.block();
+  return m_wire;
+}
+
+void
+SignatureInfo::wireDecode(const Block& wire)
+{
+  if (!wire.hasWire()) {
+    throw Error("The supplied block does not contain wire format");
+  }
+
+  m_hasKeyLocator = false;
+
+  m_wire = wire;
+  m_wire.parse();
+
+  if (m_wire.type() != Tlv::SignatureInfo)
+    throw Tlv::Error("Unexpected TLV type when decoding Name");
+
+  Block::element_const_iterator it = m_wire.elements_begin();
+
+  // the first block must be SignatureType
+  if (it != m_wire.elements_end() && it->type() == Tlv::SignatureType) {
+    m_type = readNonNegativeInteger(*it);
+    it++;
+  }
+  else
+    throw Error("SignatureInfo does not have sub-TLV or the first sub-TLV is not SignatureType");
+
+  // the second block could be KeyLocator
+  if (it != m_wire.elements_end() && it->type() == Tlv::KeyLocator) {
+    m_keyLocator.wireDecode(*it);
+    m_hasKeyLocator = true;
+    it++;
+  }
+
+  // Decode the rest of type-specific TLVs, if any
+  while (it != m_wire.elements_end()) {
+    appendTypeSpecificTlv(*it);
+    it++;
+  }
+}
+
+bool
+SignatureInfo::operator==(const SignatureInfo& rhs) const
+{
+  return (m_type == rhs.m_type &&
+          m_hasKeyLocator == rhs.m_hasKeyLocator &&
+          m_keyLocator == rhs.m_keyLocator &&
+          m_otherTlvs == rhs.m_otherTlvs);
+}
+
+} // namespace ndn
diff --git a/src/signature-info.hpp b/src/signature-info.hpp
new file mode 100644
index 0000000..9fd0f62
--- /dev/null
+++ b/src/signature-info.hpp
@@ -0,0 +1,134 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_SIGNATURE_INFO_HPP
+#define NDN_SIGNATURE_INFO_HPP
+
+#include "encoding/tlv.hpp"
+#include "key-locator.hpp"
+
+namespace ndn {
+
+class SignatureInfo
+{
+public:
+  class Error : public Tlv::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : Tlv::Error(what)
+    {
+    }
+  };
+
+  SignatureInfo();
+
+  explicit
+  SignatureInfo(Tlv::SignatureTypeValue type);
+
+  SignatureInfo(Tlv::SignatureTypeValue type, const KeyLocator& keyLocator);
+
+  /**
+   * @brief Generate SignatureInfo from a block
+   *
+   * @throws Tlv::Error if supplied block is not formatted correctly
+   */
+  explicit
+  SignatureInfo(const Block& block);
+
+  /// @brief Set SignatureType
+  void
+  setSignatureType(Tlv::SignatureTypeValue type);
+
+  /// @brief Get SignatureType
+  int32_t
+  getSignatureType() const
+  {
+    return m_type;
+  }
+
+  /// @brief Check if KeyLocator is set
+  bool
+  hasKeyLocator() const
+  {
+    return m_hasKeyLocator;
+  }
+
+  /// @brief Set KeyLocator
+  void
+  setKeyLocator(const KeyLocator& keyLocator);
+
+  /**
+   * @brief Get KeyLocator
+   *
+   * @throws SignatureInfo::Error if keyLocator does not exist
+   */
+  const KeyLocator&
+  getKeyLocator() const;
+
+  /// @brief Append signature type specific tlv block
+  void
+  appendTypeSpecificTlv(const Block& block);
+
+  /**
+   * @brief Get signature type specific tlv block
+   *
+   * @throws SignatureInfo::Error if the block does not exist
+   */
+  const Block&
+  getTypeSpecificTlv(uint32_t type) const;
+
+  /// @brief Encode to a wire format or estimate wire format
+  template<bool T>
+  size_t
+  wireEncode(EncodingImpl<T>& block) const;
+
+  /// @brief Encode to a wire format
+  const Block&
+  wireEncode() const;
+
+  /// @brief Decode from a wire format
+  void
+  wireDecode(const Block& wire);
+
+public: // EqualityComparable concept
+  bool
+  operator==(const SignatureInfo& rhs) const;
+
+  bool
+  operator!=(const SignatureInfo& rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+private:
+  int32_t m_type;
+  bool m_hasKeyLocator;
+  KeyLocator m_keyLocator;
+  std::list<Block> m_otherTlvs;
+
+  mutable Block m_wire;
+};
+
+} // namespace ndn
+
+#endif // NDN_SIGNATURE_INFO_HPP
diff --git a/src/signature.cpp b/src/signature.cpp
new file mode 100644
index 0000000..5ec68d5
--- /dev/null
+++ b/src/signature.cpp
@@ -0,0 +1,45 @@
+/* -*- 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 "signature.hpp"
+
+namespace ndn {
+
+Signature::Signature(const Block& info, const Block& value)
+  : m_info(info)
+  , m_value(value)
+{
+}
+
+
+Signature::Signature(const SignatureInfo& info, const Block& value)
+  : m_info(info)
+  , m_value(value)
+{
+}
+
+void
+Signature::setInfo(const Block& info)
+{
+  m_info = SignatureInfo(info);
+}
+
+} // namespace ndn
diff --git a/src/signature.hpp b/src/signature.hpp
index f7853dd..d6dd730 100644
--- a/src/signature.hpp
+++ b/src/signature.hpp
@@ -22,7 +22,7 @@
 #ifndef NDN_SIGNATURE_HPP
 #define NDN_SIGNATURE_HPP
 
-#include "encoding/tlv.hpp"
+#include "signature-info.hpp"
 
 namespace ndn {
 
@@ -50,49 +50,40 @@
   };
 
   Signature()
-    : m_type(-1)
   {
   }
 
   explicit
-  Signature(const Block& info, const Block& value = Block())
-    : m_value(value)
-  {
-    setInfo(info);
-  }
+  Signature(const Block& info, const Block& value = Block());
+
+  explicit
+  Signature(const SignatureInfo& info, const Block& value = Block());
 
   operator bool() const
   {
-    return m_type != -1;
+    return m_info.getSignatureType() != -1;
   }
 
-  uint32_t
-  getType() const
-  {
-    return m_type;
-  }
-
+  /// @brief Get SignatureInfo in the wire format
   const Block&
   getInfo() const
   {
-    m_info.encode(); // will do nothing if wire already exists
-    return m_info;
+    return m_info.wireEncode(); // will do nothing if wire already exists
   }
 
+  /**
+   * @brief Set SignatureInfo from a block
+   *
+   * @throws Tlv::Error if supplied block is not formatted correctly
+   */
   void
-  setInfo(const Block& info)
+  setInfo(const Block& info);
+
+  /// @brief Set SignatureInfo
+  void
+  setInfo(const SignatureInfo& info)
   {
     m_info = info;
-    if (m_info.hasWire() || m_info.hasValue())
-      {
-        m_info.parse();
-        const Block& signatureType = m_info.get(Tlv::SignatureType);
-        m_type = readNonNegativeInteger(signatureType);
-      }
-    else
-      {
-        m_type = -1;
-      }
   }
 
   const Block&
@@ -108,14 +99,30 @@
     m_value = value;
   }
 
-  void
-  reset()
+  uint32_t
+  getType() const
   {
-    m_type = -1;
-    m_info.reset();
-    m_value.reset();
+    return m_info.getSignatureType();
   }
 
+  bool
+  hasKeyLocator() const
+  {
+    return m_info.hasKeyLocator();
+  }
+
+  /**
+   * @brief Get KeyLocator
+   *
+   * @throws Signature::Error if keyLocator does not exist
+   */
+  const KeyLocator&
+  getKeyLocator() const
+  {
+    return m_info.getKeyLocator();
+  }
+
+
 public: // EqualityComparable concept
   bool
   operator==(const Signature& other) const
@@ -131,9 +138,7 @@
   }
 
 protected:
-  int32_t m_type;
-
-  mutable Block m_info;
+  SignatureInfo m_info;
   mutable Block m_value;
 };