DER encoding: Implement DerNode and subclasses.
diff --git a/Makefile.am b/Makefile.am
index 54ee508..e781f48 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -116,7 +116,8 @@
   ndn-cpp/encoding/element-listener.cpp \
   ndn-cpp/encoding/oid.cpp \
   ndn-cpp/encoding/wire-format.cpp \
-  ndn-cpp/encoding/der/der.hpp \
+  ndn-cpp/encoding/der/der-exception.cpp ndn-cpp/encoding/der/der-exception.hpp \
+  ndn-cpp/encoding/der/der.cpp ndn-cpp/encoding/der/der.hpp \
   ndn-cpp/encoding/der/visitor/no-arguments-visitor.cpp ndn-cpp/encoding/der/visitor/no-arguments-visitor.hpp \
   ndn-cpp/encoding/der/visitor/simple-visitor.cpp ndn-cpp/encoding/der/visitor/simple-visitor.hpp \
   ndn-cpp/encoding/der/visitor/visitor.hpp \
diff --git a/Makefile.in b/Makefile.in
index 2d5d108..eca3905 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -182,6 +182,8 @@
 	ndn-cpp/encoding/binary-xml-wire-format.lo \
 	ndn-cpp/encoding/element-listener.lo ndn-cpp/encoding/oid.lo \
 	ndn-cpp/encoding/wire-format.lo \
+	ndn-cpp/encoding/der/der-exception.lo \
+	ndn-cpp/encoding/der/der.lo \
 	ndn-cpp/encoding/der/visitor/no-arguments-visitor.lo \
 	ndn-cpp/encoding/der/visitor/simple-visitor.lo \
 	ndn-cpp/encoding/der/visitor/void-visitor.lo \
@@ -660,7 +662,8 @@
   ndn-cpp/encoding/element-listener.cpp \
   ndn-cpp/encoding/oid.cpp \
   ndn-cpp/encoding/wire-format.cpp \
-  ndn-cpp/encoding/der/der.hpp \
+  ndn-cpp/encoding/der/der-exception.cpp ndn-cpp/encoding/der/der-exception.hpp \
+  ndn-cpp/encoding/der/der.cpp ndn-cpp/encoding/der/der.hpp \
   ndn-cpp/encoding/der/visitor/no-arguments-visitor.cpp ndn-cpp/encoding/der/visitor/no-arguments-visitor.hpp \
   ndn-cpp/encoding/der/visitor/simple-visitor.cpp ndn-cpp/encoding/der/visitor/simple-visitor.hpp \
   ndn-cpp/encoding/der/visitor/visitor.hpp \
@@ -889,6 +892,17 @@
 	ndn-cpp/encoding/$(DEPDIR)/$(am__dirstamp)
 ndn-cpp/encoding/wire-format.lo: ndn-cpp/encoding/$(am__dirstamp) \
 	ndn-cpp/encoding/$(DEPDIR)/$(am__dirstamp)
+ndn-cpp/encoding/der/$(am__dirstamp):
+	@$(MKDIR_P) ndn-cpp/encoding/der
+	@: > ndn-cpp/encoding/der/$(am__dirstamp)
+ndn-cpp/encoding/der/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) ndn-cpp/encoding/der/$(DEPDIR)
+	@: > ndn-cpp/encoding/der/$(DEPDIR)/$(am__dirstamp)
+ndn-cpp/encoding/der/der-exception.lo:  \
+	ndn-cpp/encoding/der/$(am__dirstamp) \
+	ndn-cpp/encoding/der/$(DEPDIR)/$(am__dirstamp)
+ndn-cpp/encoding/der/der.lo: ndn-cpp/encoding/der/$(am__dirstamp) \
+	ndn-cpp/encoding/der/$(DEPDIR)/$(am__dirstamp)
 ndn-cpp/encoding/der/visitor/$(am__dirstamp):
 	@$(MKDIR_P) ndn-cpp/encoding/der/visitor
 	@: > ndn-cpp/encoding/der/visitor/$(am__dirstamp)
@@ -1055,6 +1069,8 @@
 	-rm -f ndn-cpp/c/util/*.lo
 	-rm -f ndn-cpp/encoding/*.$(OBJEXT)
 	-rm -f ndn-cpp/encoding/*.lo
+	-rm -f ndn-cpp/encoding/der/*.$(OBJEXT)
+	-rm -f ndn-cpp/encoding/der/*.lo
 	-rm -f ndn-cpp/encoding/der/visitor/*.$(OBJEXT)
 	-rm -f ndn-cpp/encoding/der/visitor/*.lo
 	-rm -f ndn-cpp/security/*.$(OBJEXT)
@@ -1107,6 +1123,8 @@
 @AMDEP_TRUE@@am__include@ @am__quote@ndn-cpp/encoding/$(DEPDIR)/element-listener.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ndn-cpp/encoding/$(DEPDIR)/oid.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ndn-cpp/encoding/$(DEPDIR)/wire-format.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ndn-cpp/encoding/der/$(DEPDIR)/der-exception.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ndn-cpp/encoding/der/$(DEPDIR)/der.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ndn-cpp/encoding/der/visitor/$(DEPDIR)/no-arguments-visitor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ndn-cpp/encoding/der/visitor/$(DEPDIR)/simple-visitor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ndn-cpp/encoding/der/visitor/$(DEPDIR)/void-visitor.Plo@am__quote@
@@ -1195,6 +1213,7 @@
 	-rm -rf ndn-cpp/c/transport/.libs ndn-cpp/c/transport/_libs
 	-rm -rf ndn-cpp/c/util/.libs ndn-cpp/c/util/_libs
 	-rm -rf ndn-cpp/encoding/.libs ndn-cpp/encoding/_libs
+	-rm -rf ndn-cpp/encoding/der/.libs ndn-cpp/encoding/der/_libs
 	-rm -rf ndn-cpp/encoding/der/visitor/.libs ndn-cpp/encoding/der/visitor/_libs
 	-rm -rf ndn-cpp/security/.libs ndn-cpp/security/_libs
 	-rm -rf ndn-cpp/security/certificate/.libs ndn-cpp/security/certificate/_libs
@@ -1546,6 +1565,8 @@
 	-rm -f ndn-cpp/c/util/$(am__dirstamp)
 	-rm -f ndn-cpp/encoding/$(DEPDIR)/$(am__dirstamp)
 	-rm -f ndn-cpp/encoding/$(am__dirstamp)
+	-rm -f ndn-cpp/encoding/der/$(DEPDIR)/$(am__dirstamp)
+	-rm -f ndn-cpp/encoding/der/$(am__dirstamp)
 	-rm -f ndn-cpp/encoding/der/visitor/$(DEPDIR)/$(am__dirstamp)
 	-rm -f ndn-cpp/encoding/der/visitor/$(am__dirstamp)
 	-rm -f ndn-cpp/security/$(DEPDIR)/$(am__dirstamp)
@@ -1573,7 +1594,7 @@
 
 distclean: distclean-recursive
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-	-rm -rf ndn-cpp/$(DEPDIR) ndn-cpp/c/$(DEPDIR) ndn-cpp/c/encoding/$(DEPDIR) ndn-cpp/c/transport/$(DEPDIR) ndn-cpp/c/util/$(DEPDIR) ndn-cpp/encoding/$(DEPDIR) ndn-cpp/encoding/der/visitor/$(DEPDIR) ndn-cpp/security/$(DEPDIR) ndn-cpp/security/certificate/$(DEPDIR) ndn-cpp/security/identity/$(DEPDIR) ndn-cpp/security/policy/$(DEPDIR) ndn-cpp/transport/$(DEPDIR) ndn-cpp/util/$(DEPDIR) tests/$(DEPDIR)
+	-rm -rf ndn-cpp/$(DEPDIR) ndn-cpp/c/$(DEPDIR) ndn-cpp/c/encoding/$(DEPDIR) ndn-cpp/c/transport/$(DEPDIR) ndn-cpp/c/util/$(DEPDIR) ndn-cpp/encoding/$(DEPDIR) ndn-cpp/encoding/der/$(DEPDIR) ndn-cpp/encoding/der/visitor/$(DEPDIR) ndn-cpp/security/$(DEPDIR) ndn-cpp/security/certificate/$(DEPDIR) ndn-cpp/security/identity/$(DEPDIR) ndn-cpp/security/policy/$(DEPDIR) ndn-cpp/transport/$(DEPDIR) ndn-cpp/util/$(DEPDIR) tests/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-libtool distclean-tags
@@ -1621,7 +1642,7 @@
 maintainer-clean: maintainer-clean-recursive
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
 	-rm -rf $(top_srcdir)/autom4te.cache
-	-rm -rf ndn-cpp/$(DEPDIR) ndn-cpp/c/$(DEPDIR) ndn-cpp/c/encoding/$(DEPDIR) ndn-cpp/c/transport/$(DEPDIR) ndn-cpp/c/util/$(DEPDIR) ndn-cpp/encoding/$(DEPDIR) ndn-cpp/encoding/der/visitor/$(DEPDIR) ndn-cpp/security/$(DEPDIR) ndn-cpp/security/certificate/$(DEPDIR) ndn-cpp/security/identity/$(DEPDIR) ndn-cpp/security/policy/$(DEPDIR) ndn-cpp/transport/$(DEPDIR) ndn-cpp/util/$(DEPDIR) tests/$(DEPDIR)
+	-rm -rf ndn-cpp/$(DEPDIR) ndn-cpp/c/$(DEPDIR) ndn-cpp/c/encoding/$(DEPDIR) ndn-cpp/c/transport/$(DEPDIR) ndn-cpp/c/util/$(DEPDIR) ndn-cpp/encoding/$(DEPDIR) ndn-cpp/encoding/der/$(DEPDIR) ndn-cpp/encoding/der/visitor/$(DEPDIR) ndn-cpp/security/$(DEPDIR) ndn-cpp/security/certificate/$(DEPDIR) ndn-cpp/security/identity/$(DEPDIR) ndn-cpp/security/policy/$(DEPDIR) ndn-cpp/transport/$(DEPDIR) ndn-cpp/util/$(DEPDIR) tests/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
diff --git a/ndn-cpp/encoding/der/der-exception.cpp b/ndn-cpp/encoding/der/der-exception.cpp
new file mode 100644
index 0000000..84ab5c1
--- /dev/null
+++ b/ndn-cpp/encoding/der/der-exception.cpp
@@ -0,0 +1,29 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "der-exception.hpp"
+
+using namespace std;
+
+namespace ndn {
+
+namespace der
+{
+  
+DerException::DerException(const string& errorMessage) throw()
+  : errorMessage_(errorMessage)
+{
+}
+
+DerException::~DerException() throw()
+{
+}
+  
+} // der
+
+}
diff --git a/ndn-cpp/encoding/der/der-exception.hpp b/ndn-cpp/encoding/der/der-exception.hpp
new file mode 100644
index 0000000..1d0db2a
--- /dev/null
+++ b/ndn-cpp/encoding/der/der-exception.hpp
@@ -0,0 +1,61 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_DER_EXCEPTION_HPP
+#define NDN_DER_EXCEPTION_HPP
+
+#include <exception>
+#include <string>
+
+namespace ndn {
+
+namespace der {
+
+class DerException : public std::exception {
+public:
+  DerException(const std::string& errorMessage) throw();
+  
+  ~DerException() throw();
+  
+  std::string Msg() { return errorMessage_; }
+  
+  virtual const char* what() const throw() { return errorMessage_.c_str(); }
+
+private:
+  const std::string errorMessage_;
+};
+
+class NegativeLengthException : public DerException
+{
+public:
+  NegativeLengthException(const std::string& errorMessage)
+  : DerException(errorMessage)
+  {}
+};
+
+class DerEncodingException : public DerException
+{
+public:
+  DerEncodingException(const std::string& errorMessage)
+  : DerException(errorMessage)
+  {}
+};
+
+class DerDecodingException : public DerException
+{
+public:
+  DerDecodingException(const std::string& errorMessage)
+  : DerException(errorMessage)
+  {}
+};
+
+} // der
+
+}
+
+#endif
diff --git a/ndn-cpp/encoding/der/der.cpp b/ndn-cpp/encoding/der/der.cpp
new file mode 100644
index 0000000..9620be2
--- /dev/null
+++ b/ndn-cpp/encoding/der/der.cpp
@@ -0,0 +1,629 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#if 1 // TODO: Remove this when we don't throw "not implemented".
+#include <stdexcept>
+#endif
+#include "der-exception.hpp"
+#include "../../util/logging.hpp"
+#include "der.hpp"
+
+INIT_LOGGER("ndn.der.DER");
+
+using namespace std;
+using namespace ndn::ptr_lib;
+
+namespace ndn {
+
+namespace der {
+
+/*
+ * DerNode
+ */
+DerNode::DerNode()
+  :m_parent(0)
+{}
+
+DerNode::DerNode(DerType type)
+  :m_type(type),
+   m_parent(0)
+{}
+
+DerNode::DerNode(std::istream& start)
+  :m_parent(0)
+{
+  decode(start);
+}
+
+DerNode::~DerNode()
+{}
+
+void
+DerNode::encodeHeader(int size)
+{
+  m_header.push_back((char)m_type);
+
+  if(size >= 127)
+    {
+      int val = size;
+      char buf[sizeof(val) + 1];
+      char *p = &(buf[sizeof(buf)-1]);
+      int n = 0;
+      int mask = (1 << 8) - 1;
+
+      while(val != 0)
+        {
+          p[0] = (char)(val & mask);
+          p--;
+          n++;
+          val >>= 8;
+        }
+
+      p[0] = (char)((1<<7) | n);
+      n++;
+
+      m_header.insert(m_header.end(), p, p+n);
+    }
+  else if(size >= 0)
+    {
+      m_header.push_back((char)size);
+    }
+  else
+    throw NegativeLengthException("Negative length");
+}
+
+int
+DerNode::decodeHeader(istream& start)
+{
+  uint8_t type = start.get();
+  // char type = start.get();
+  m_header.push_back(type);
+  m_type = static_cast<DerType>((int)type);
+
+  uint8_t sizeLen = start.get(); 
+  // char sizeLen = start.get();
+  m_header.push_back(sizeLen);
+
+  bool longFormat = sizeLen & (1 << 7);
+
+  if(!longFormat)
+    {
+      // _LOG_DEBUG("Short Format");
+      // _LOG_DEBUG("sizeLen: " << (int)sizeLen);
+      return (int)sizeLen;
+    }
+  else
+    {
+      // _LOG_DEBUG("Long Format");
+      uint8_t byte;
+      // char byte;
+      int lenCount = sizeLen & ((1<<7) - 1);
+      // _LOG_DEBUG("sizeLen: " << (int)sizeLen);
+      // _LOG_DEBUG("mask: " << (int)((1<<7) - 1));
+      // _LOG_DEBUG("lenCount: " << (int)lenCount);
+      int size = 0;
+      do
+        {
+          byte = start.get();
+          m_header.push_back(byte);
+          size = size * 256 + (int)byte;
+          // _LOG_DEBUG("byte: " << (int)byte);
+          // _LOG_DEBUG("size: " << size);
+          lenCount--;
+        }
+      while(lenCount > 0);
+
+      return size;
+    }
+}
+
+void
+DerNode::encode(ostream& start)
+{
+  start.write((const char*)&m_header[0], m_header.size());
+  start.write((const char*)&m_payload[0], m_payload.size());
+}
+
+void 
+DerNode::decode(istream& start)
+{
+  int payloadSize = decodeHeader(start);
+  // _LOG_DEBUG("payloadSize: " << payloadSize);
+  if(payloadSize > 0 )
+    {
+      char buf[payloadSize];
+      start.read(buf, payloadSize);
+      m_payload.insert(m_payload.end(), buf, buf + payloadSize);
+    }
+}
+
+shared_ptr<DerNode>
+DerNode::parse(istream& start)
+{
+  int type = ((uint8_t)start.peek());
+
+  // _LOG_DEBUG("Type: " << hex << setw(2) << setfill('0') << type);
+  switch(type) {
+    case DER_BOOLEAN:
+      return shared_ptr<DerBool>(new DerBool(start));
+    case DER_INTEGER:
+      return shared_ptr<DerInteger>(new DerInteger(start));
+    case DER_BIT_STRING:
+      return shared_ptr<DerBitString>(new DerBitString(start));
+    case DER_OCTET_STRING:
+      return shared_ptr<DerOctetString>(new DerOctetString(start));
+    case DER_NULL:
+      return shared_ptr<DerNull>(new DerNull(start));
+    case DER_OBJECT_IDENTIFIER:
+      return shared_ptr<DerOid>(new DerOid(start));
+    case DER_SEQUENCE:
+      return shared_ptr<DerSequence>(new DerSequence(start));
+    case DER_PRINTABLE_STRING:
+      return shared_ptr<DerPrintableString>(new DerPrintableString(start));
+    case DER_GENERALIZED_TIME:
+      return shared_ptr<DerGtime>(new DerGtime(start));
+    default:
+      throw DerDecodingException("Unimplemented DER types");
+    }
+}
+
+
+/*
+ * DerComplex
+ */
+DerComplex::DerComplex()
+  :DerNode(),
+   m_childChanged(false),
+   m_size(0)
+{}
+
+DerComplex::DerComplex(DerType type)
+  :DerNode(type),
+   m_childChanged(false),
+   m_size(0)
+{}
+
+DerComplex::DerComplex(istream& start)
+  :DerNode(),
+   m_childChanged(false),
+   m_size(0)
+{
+  m_size = DerNode::decodeHeader(start);
+  // _LOG_DEBUG("Size: " << m_size);
+
+  int accSize = 0;
+  
+  while(accSize < m_size)
+    {
+      // _LOG_DEBUG("accSize: " << accSize);
+      shared_ptr<DerNode> nodePtr = DerNode::parse(start);
+      accSize += nodePtr->getSize();
+      addChild(nodePtr, false);
+    }
+}
+
+DerComplex::~DerComplex()
+{}
+
+int
+DerComplex::getSize()
+{
+  if(m_childChanged)
+    {
+	updateSize();
+	m_childChanged = false;
+    }
+
+  m_header.clear();
+  DerNode::encodeHeader(m_size);
+  return m_size + m_header.size();
+}
+
+shared_ptr<vector<uint8_t> >
+DerComplex::getRaw()
+{
+  shared_ptr<vector<uint8_t> > blob(new vector<uint8_t>());
+  blob->insert(blob->end(), m_header.begin(), m_header.end());
+
+  DerNodePtrList::iterator it = m_nodeList.begin();
+  for(; it != m_nodeList.end(); it++)
+    {
+      shared_ptr<vector<uint8_t> > childBlob = (*it)->getRaw();
+      blob->insert(blob->end(), childBlob->begin(), childBlob->end());
+    }
+  return blob;
+}
+
+void
+DerComplex::updateSize()
+{
+  int newSize = 0;
+
+  DerNodePtrList::iterator it = m_nodeList.begin();
+  for(; it != m_nodeList.end(); it++)
+    {
+	newSize += (*it)->getSize();
+    }
+  
+  m_size = newSize;
+  m_childChanged = false;
+}
+
+void
+DerComplex::addChild(shared_ptr<DerNode> nodePtr, bool notifyParent)
+{
+  nodePtr->setParent(this);
+
+  m_nodeList.push_back(nodePtr);
+
+  if(!notifyParent)
+    return;
+
+  if(m_childChanged)
+    return;
+  else
+    m_childChanged = true;
+
+  if(0 != m_parent)
+    m_parent->setChildChanged();
+}
+
+void
+DerComplex::setChildChanged()
+{
+  if(0 != m_parent && !m_childChanged)
+    {
+      m_parent->setChildChanged();
+      m_childChanged = true;
+    }
+  else
+    m_childChanged = true;
+}
+
+void
+DerComplex::encode(ostream& start)
+{
+  updateSize();
+  m_header.clear();
+
+  DerNode::encodeHeader(m_size);
+
+  start.write((const char*)&m_header[0], m_header.size());
+
+  DerNodePtrList::iterator it = m_nodeList.begin();
+  for(; it != m_nodeList.end(); it++)
+    (*it)->encode(start);
+}
+
+
+/*
+ * DerByteString
+ */
+DerByteString::DerByteString(const string& str, DerType type)
+  :DerNode(type)
+{
+  m_payload.insert(m_payload.end(), str.begin(), str.end());
+
+  DerNode::encodeHeader(m_payload.size());
+}
+
+DerByteString::DerByteString(const std::vector<uint8_t>& blob, DerType type)
+  :DerNode(type)
+{
+  m_payload.insert(m_payload.end(), blob.begin(), blob.end());
+
+  DerNode::encodeHeader(m_payload.size());
+}
+
+DerByteString::DerByteString(istream& start)
+  :DerNode(start)
+{}
+
+DerByteString::~DerByteString()
+{}
+
+
+/*
+ * DerBool
+ */
+DerBool::DerBool(bool value)
+  :DerNode(DER_BOOLEAN)
+
+{ 
+  char payload = (value ? 0xFF : 0x00);
+  m_payload.push_back(payload);
+
+  DerNode::encodeHeader(m_payload.size());
+}
+
+DerBool::DerBool(istream& start)
+  :DerNode(start)
+{}
+
+DerBool::~DerBool()
+{}
+
+
+/*
+ * DerInteger
+ */
+DerInteger::DerInteger(const vector<uint8_t>& blob)
+  :DerNode(DER_INTEGER)
+{
+  m_payload.insert(m_payload.end(), blob.begin(), blob.end());
+
+  DerNode::encodeHeader(m_payload.size());
+}
+
+DerInteger::DerInteger(istream& start)
+  :DerNode(start)
+{}
+
+DerInteger::~DerInteger()
+{}
+
+
+/*
+ * DerBitString
+ */
+DerBitString::DerBitString(const vector<uint8_t>& blob, uint8_t paddingLen)
+  :DerNode(DER_BIT_STRING)
+{     
+  m_payload.push_back((char)paddingLen);
+  m_payload.insert(m_payload.end(), blob.begin(), blob.end());
+
+  DerNode::encodeHeader(m_payload.size());
+}
+
+DerBitString::DerBitString(istream& start)
+  :DerNode(start)
+{}
+
+DerBitString::~DerBitString()
+{}
+
+
+/*
+ * DerOctetString
+ */
+DerOctetString::DerOctetString(const string& str)
+  :DerByteString(str, DER_OCTET_STRING)
+{}
+
+DerOctetString::DerOctetString(const vector<uint8_t>& blob)
+  :DerByteString(blob, DER_OCTET_STRING)
+{}
+
+DerOctetString::DerOctetString(istream& start)
+  :DerByteString(start)
+{}
+
+DerOctetString::~DerOctetString()
+{}
+
+
+/*
+ * DerNull
+ */
+DerNull::DerNull()
+  :DerNode(DER_NULL)
+{
+  DerNode::encodeHeader(0);
+}
+
+DerNull::DerNull(istream& start)
+  :DerNode(start)
+{}
+  
+DerNull::~DerNull()
+{}
+
+
+/*
+ * DerOid
+ */
+DerOid::DerOid(const OID& oid)
+  :DerNode(DER_OBJECT_IDENTIFIER)
+{
+  prepareEncoding(oid.getIntegerList());
+}
+
+
+DerOid::DerOid(const string& oidStr)
+  :DerNode(DER_OBJECT_IDENTIFIER)
+{
+  vector<int> value;
+
+  string str = oidStr + ".";
+
+  size_t pos = 0;
+  size_t ppos = 0;
+
+  while(string::npos != pos){
+    ppos = pos;
+
+    pos = str.find_first_of('.', pos);
+    if(string::npos == pos)
+	break;
+
+    value.push_back(atoi(str.substr(ppos, pos - ppos).c_str()));
+
+    pos++;
+  }
+
+  prepareEncoding(value);
+}
+
+DerOid::DerOid(const vector<int>& value)
+  :DerNode(DER_OBJECT_IDENTIFIER)
+{
+  prepareEncoding(value);
+}
+
+DerOid::DerOid(istream& start)
+  :DerNode(start)
+{}
+  
+DerOid::~DerOid()
+{}
+
+void
+DerOid::prepareEncoding(const vector<int>& value)
+{
+  ostringstream os;
+
+  int firstNumber = 0;
+  
+  if(value.size() >= 1){
+    if(0 <= value[0] && 2 >= value[0])
+	firstNumber = value[0] * 40;
+    else
+	throw DerEncodingException("first integer of oid is out of range");
+  }
+  else
+    throw DerEncodingException("no integer in oid");
+
+  if(value.size() >= 2){
+    if(0 <= value[1] && 39 >= value[1])
+	firstNumber += value[1];
+    else
+	throw DerEncodingException("second integer of oid is out of range");
+  }
+  
+  encode128(firstNumber, os);
+
+  if(value.size() > 2){
+    int i = 2;
+    for(; i < value.size(); i++)
+	encode128(value[i], os);
+  }
+
+  string output = os.str();
+  DerNode::encodeHeader(output.size());
+
+  m_payload.insert(m_payload.end(), output.begin(), output.end());
+}
+  
+void
+DerOid::encode128(int value, ostringstream& os)
+{
+  int mask = (1 << 7) - 1;
+
+  if(128 > value)
+    {
+	uint8_t singleByte = (uint8_t) mask & value;
+	os.write((char *)&singleByte, 1);
+    }
+  else{
+    uint8_t buf[(sizeof(value)*8 + 6)/7 + 1];
+    uint8_t *p = &(buf[sizeof(buf)-1]);
+    int n = 1;
+
+    p[0] = (uint8_t)(value & mask);
+    value >>= 7;
+
+    while(value != 0)
+	{
+	  (--p)[0] = (uint8_t)((value & mask) | (1 << 7));
+	  n++;
+	  value >>= 7;
+	}
+    
+    os.write((char *)p, n);
+  }
+}
+
+int
+DerOid::decode128(int & offset)
+{
+  uint8_t flagMask = 0x80;
+  int result = 0;
+  while(m_payload[offset] & flagMask){
+    result = 128 * result + (uint8_t) m_payload[offset] - 128;
+    offset++;
+  }
+
+  result = result * 128 + m_payload[offset];
+  offset++;
+
+  return result;
+}
+
+
+/*
+ * DerSequence
+ */
+DerSequence::DerSequence()
+  :DerComplex(DER_SEQUENCE)
+{}
+
+DerSequence::DerSequence(istream& start)
+  :DerComplex(start)
+{}
+
+DerSequence::~DerSequence() 
+{}
+
+
+/*
+ * DerPrintableString
+ */
+DerPrintableString::DerPrintableString(const string& str)
+  :DerByteString(str, DER_PRINTABLE_STRING)
+{}
+
+DerPrintableString::DerPrintableString(const vector<uint8_t>& blob)
+  :DerByteString(blob, DER_PRINTABLE_STRING)
+{}
+
+DerPrintableString::DerPrintableString(istream& start)
+  :DerByteString(start)
+{}
+
+DerPrintableString::~DerPrintableString()
+{}
+
+
+/*
+ * DerGtime
+ */
+DerGtime::DerGtime(const Time& time)
+  :DerNode(DER_GENERALIZED_TIME)
+{
+  string pTimeStr = toIsoString(time);
+  int index = pTimeStr.find_first_of('T');
+  string derTime = pTimeStr.substr(0, index) + pTimeStr.substr(index+1, pTimeStr.size() - index -1) + "Z";
+  m_payload.insert(m_payload.end(), derTime.begin(), derTime.end());
+
+  DerNode::encodeHeader(m_payload.size());
+}
+
+DerGtime::DerGtime(istream& start)
+  :DerNode(start)
+{}
+  
+DerGtime::~DerGtime()
+{}
+
+string DerGtime::toIsoString(const Time& time)
+{
+#if 1
+  throw std::runtime_error("not implemented");
+#endif
+}
+
+Time DerGtime::fromIsoString(const string& isoString)
+{
+#if 1
+  throw std::runtime_error("not implemented");
+#endif
+}
+
+} // der
+
+}
diff --git a/ndn-cpp/encoding/der/der.hpp b/ndn-cpp/encoding/der/der.hpp
index 065cfd6..52dde00 100644
--- a/ndn-cpp/encoding/der/der.hpp
+++ b/ndn-cpp/encoding/der/der.hpp
@@ -205,11 +205,10 @@
   virtual
   ~DerBool();
 
-  virtual void accept(VoidNoArgumentsVisitor& visitor) {        visitor.visit(*this);        }
-  virtual void accept(VoidVisitor& visitor, ndnboost::any param) {        visitor.visit(*this, param); }
-  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)      { return visitor.visit(*this);        }
-  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param)      { return visitor.visit(*this, param); }
-
+  virtual void accept(VoidNoArgumentsVisitor& visitor)                {        visitor.visit(*this);        }
+  virtual void accept(VoidVisitor& visitor, ndnboost::any param)      {        visitor.visit(*this, param); }
+  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)           { return visitor.visit(*this);        }
+  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param) { return visitor.visit(*this, param); }
 };
 
 //0x02  
@@ -223,11 +222,10 @@
   virtual 
   ~DerInteger();
 
-  virtual void accept(VoidNoArgumentsVisitor& visitor) {        visitor.visit(*this);        }
-  virtual void accept(VoidVisitor& visitor, ndnboost::any param) {        visitor.visit(*this, param); }
-  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)      { return visitor.visit(*this);        }
-  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param)      { return visitor.visit(*this, param); }
-
+  virtual void accept(VoidNoArgumentsVisitor& visitor)                {        visitor.visit(*this);        }
+  virtual void accept(VoidVisitor& visitor, ndnboost::any param)      {        visitor.visit(*this, param); }
+  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)           { return visitor.visit(*this);        }
+  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param) { return visitor.visit(*this, param); }
 };
 
 //0x03
@@ -241,11 +239,10 @@
   virtual
   ~DerBitString();
 
-  virtual void accept(VoidNoArgumentsVisitor& visitor) {        visitor.visit(*this);        }
-  virtual void accept(VoidVisitor& visitor, ndnboost::any param) {        visitor.visit(*this, param); }
-  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)      { return visitor.visit(*this);        }
-  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param)      { return visitor.visit(*this, param); }
-
+  virtual void accept(VoidNoArgumentsVisitor& visitor)                {        visitor.visit(*this);        }
+  virtual void accept(VoidVisitor& visitor, ndnboost::any param)      {        visitor.visit(*this, param); }
+  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)           { return visitor.visit(*this);        }
+  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param) { return visitor.visit(*this, param); }
 };
 
 //0x04
@@ -261,11 +258,10 @@
   virtual
   ~DerOctetString();
 
-  virtual void accept(VoidNoArgumentsVisitor& visitor) {        visitor.visit(*this);        }
-  virtual void accept(VoidVisitor& visitor, ndnboost::any param) {        visitor.visit(*this, param); }
-  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)      { return visitor.visit(*this);        }
-  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param)      { return visitor.visit(*this, param); }
-
+  virtual void accept(VoidNoArgumentsVisitor& visitor)                {        visitor.visit(*this);        }
+  virtual void accept(VoidVisitor& visitor, ndnboost::any param)      {        visitor.visit(*this, param); }
+  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)           { return visitor.visit(*this);        }
+  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param) { return visitor.visit(*this, param); }
 };
 
 
@@ -280,11 +276,10 @@
   virtual
   ~DerNull();
 
-  virtual void accept(VoidNoArgumentsVisitor& visitor) {        visitor.visit(*this);        }
-  virtual void accept(VoidVisitor& visitor, ndnboost::any param) {        visitor.visit(*this, param); }
-  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)      { return visitor.visit(*this);        }
-  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param)      { return visitor.visit(*this, param); }
-
+  virtual void accept(VoidNoArgumentsVisitor& visitor)                {        visitor.visit(*this);        }
+  virtual void accept(VoidVisitor& visitor, ndnboost::any param)      {        visitor.visit(*this, param); }
+  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)           { return visitor.visit(*this);        }
+  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param) { return visitor.visit(*this, param); }
 };
 
 
@@ -303,10 +298,10 @@
   virtual
   ~DerOid();
   
-  virtual void accept(VoidNoArgumentsVisitor& visitor) {        visitor.visit(*this);        }
-  virtual void accept(VoidVisitor& visitor, ndnboost::any param) {        visitor.visit(*this, param); }
-  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)      { return visitor.visit(*this);        }
-  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param)      { return visitor.visit(*this, param); }
+  virtual void accept(VoidNoArgumentsVisitor& visitor)                {        visitor.visit(*this);        }
+  virtual void accept(VoidVisitor& visitor, ndnboost::any param)      {        visitor.visit(*this, param); }
+  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)           { return visitor.visit(*this);        }
+  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param) { return visitor.visit(*this, param); }
 
   int 
   decode128(int& offset);
@@ -331,11 +326,10 @@
   virtual
   ~DerSequence();
 
-  virtual void accept(VoidNoArgumentsVisitor& visitor) {        visitor.visit(*this);        }
-  virtual void accept(VoidVisitor& visitor, ndnboost::any param) {        visitor.visit(*this, param); }
-  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)      { return visitor.visit(*this);        }
-  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param)      { return visitor.visit(*this, param); }
-
+  virtual void accept(VoidNoArgumentsVisitor& visitor)                {        visitor.visit(*this);        }
+  virtual void accept(VoidVisitor& visitor, ndnboost::any param)      {        visitor.visit(*this, param); }
+  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)           { return visitor.visit(*this);        }
+  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param) { return visitor.visit(*this, param); }
 };
 
 //0x13
@@ -351,10 +345,10 @@
   virtual 
   ~DerPrintableString();
 
-  virtual void accept(VoidNoArgumentsVisitor& visitor) {        visitor.visit(*this);        }
-  virtual void accept(VoidVisitor& visitor, ndnboost::any param) {        visitor.visit(*this, param); }
-  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)      { return visitor.visit(*this);        }
-  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param)      { return visitor.visit(*this, param); }
+  virtual void accept(VoidNoArgumentsVisitor& visitor)                {        visitor.visit(*this);        }
+  virtual void accept(VoidVisitor& visitor, ndnboost::any param)      {        visitor.visit(*this, param); }
+  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)           { return visitor.visit(*this);        }
+  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param) { return visitor.visit(*this, param); }
 };
 
 //0x1b
@@ -368,11 +362,24 @@
   virtual 
   ~DerGtime();
 
-  virtual void accept(VoidNoArgumentsVisitor& visitor) {        visitor.visit(*this);        }
-  virtual void accept(VoidVisitor& visitor, ndnboost::any param) {        visitor.visit(*this, param); }
-  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)      { return visitor.visit(*this);        }
-  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param)      { return visitor.visit(*this, param); }
+  virtual void accept(VoidNoArgumentsVisitor& visitor)                {        visitor.visit(*this);        }
+  virtual void accept(VoidVisitor& visitor, ndnboost::any param)      {        visitor.visit(*this, param); }
+  virtual ndnboost::any accept(NoArgumentsVisitor& visitor)           { return visitor.visit(*this);        }
+  virtual ndnboost::any accept(Visitor& visitor, ndnboost::any param) { return visitor.visit(*this, param); }
 
+  /**
+   * Convert to the ISO string representation of the time.
+   * @param time Milliseconds since 1/1/1970.
+   * @return The ISO string.
+   */
+  static std::string toIsoString(const Time& time);
+  
+  /**
+   * Convert from the ISO string representation to the internal time format.
+   * @param isoString The ISO time formatted string. 
+   * @return The time in milliseconds since 1/1/1970.
+   */
+  static Time fromIsoString(const std::string& isoString);
 };
  
 } // der
diff --git a/ndn-cpp/encoding/der/visitor/simple-visitor.cpp b/ndn-cpp/encoding/der/visitor/simple-visitor.cpp
index 8539950..c56f999 100644
--- a/ndn-cpp/encoding/der/visitor/simple-visitor.cpp
+++ b/ndn-cpp/encoding/der/visitor/simple-visitor.cpp
@@ -6,9 +6,6 @@
  * See COPYING for copyright and distribution information.
  */
 
-#if 1 // TODO: Remove this when we don't throw "not implemented".
-#include <stdexcept>
-#endif
 #include "simple-visitor.hpp"
 #include "../der.hpp"
 #include <ndn-cpp/encoding/oid.hpp>
@@ -65,7 +62,6 @@
 ndnboost::any 
 SimpleVisitor::visit(DerOid& derOid)
 {
-#if 0 // Include again when der is defined.
   vector<int> intList;
   int offset = 0;
 
@@ -83,9 +79,6 @@
   }
   
   return ndnboost::any(OID(intList));
-#else
-  throw std::runtime_error("not implemented");
-#endif
 }
 
 ndnboost::any 
@@ -94,14 +87,12 @@
   return ndnboost::any();
 }
 
-#if 0 // TODO: Implmenent alternative to boost::posix_time::from_iso_string.
 ndnboost::any 
 SimpleVisitor::visit(DerGtime& derGtime)
 {
   string str((const char*)&derGtime.getPayload()[0], derGtime.getPayload().size());
-  return ndnboost::any(boost::posix_time::from_iso_string(str.substr(0, 8) + "T" + str.substr(8, 6)));
+  return ndnboost::any(DerGtime::fromIsoString(str.substr(0, 8) + "T" + str.substr(8, 6)));
 }
-#endif
 
 } // der
 
diff --git a/ndn-cpp/security/certificate/certificate-extension.cpp b/ndn-cpp/security/certificate/certificate-extension.cpp
index d3719a7..aba88dd 100644
--- a/ndn-cpp/security/certificate/certificate-extension.cpp
+++ b/ndn-cpp/security/certificate/certificate-extension.cpp
@@ -20,7 +20,6 @@
 shared_ptr<der::DerNode> 
 CertificateExtension::toDer()
 {
-#if 0 // Include again when der is defined.
   shared_ptr<der::DerSequence> root(new der::DerSequence);
     
   shared_ptr<der::DerOid> extensionId(new der::DerOid(extensionId_));
@@ -34,9 +33,6 @@
   root->getSize();
 
   return root;
-#else
-  throw std::runtime_error("not implemented");
-#endif
 }
 
 Blob
diff --git a/ndn-cpp/security/certificate/certificate-subject-description.cpp b/ndn-cpp/security/certificate/certificate-subject-description.cpp
index e66b672..ee2310c 100644
--- a/ndn-cpp/security/certificate/certificate-subject-description.cpp
+++ b/ndn-cpp/security/certificate/certificate-subject-description.cpp
@@ -6,9 +6,6 @@
  * See COPYING for copyright and distribution information.
  */
 
-#if 1 // TODO: Remove this when we don't throw "not implemented".
-#include <stdexcept>
-#endif
 #include "../../encoding/der/der.hpp"
 #include <ndn-cpp/security/certificate/certificate-subject-description.hpp>
 
@@ -20,7 +17,6 @@
 shared_ptr<der::DerNode> 
 CertificateSubjectDescription::toDer()
 {
-#if 0 // Include again when der is defined.
   shared_ptr<der::DerSequence> root(new der::DerSequence());
 
   shared_ptr<der::DerOid> oid(new der::DerOid(oid_));
@@ -30,9 +26,6 @@
   root->addChild(value);
 
   return root;
-#else
-  throw std::runtime_error("not implemented");
-#endif
 }
 
 }