v1/certificate.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "certificate.hpp"
27 #include "../../util/time.hpp"
28 #include "cryptopp.hpp"
29 #include "../../encoding/cryptopp/asn_ext.hpp"
30 #include "../../encoding/buffer-stream.hpp"
31 #include "../../util/concepts.hpp"
32 #include "../../util/indented-stream.hpp"
33 
34 #include <boost/algorithm/string/split.hpp>
35 
36 namespace ndn {
37 namespace security {
38 namespace v1 {
39 
40 BOOST_CONCEPT_ASSERT((WireEncodable<Certificate>));
41 BOOST_CONCEPT_ASSERT((WireDecodable<Certificate>));
42 static_assert(std::is_base_of<tlv::Error, Certificate::Error>::value,
43  "Certificate::Error must inherit from tlv::Error");
44 
46  : m_notBefore(time::system_clock::TimePoint::max())
47  , m_notAfter(time::system_clock::TimePoint::min())
48 {
49 }
50 
52  // Use the copy constructor. It clones the signature object.
53  : Data(data)
54 {
55  decode();
56 }
57 
59  : Data(block)
60 {
61  decode();
62 }
63 
65 {
66 }
67 
68 void
70 {
71  Data::wireDecode(wire);
72  decode();
73 }
74 
75 bool
77 {
79  return true;
80  else
81  return false;
82 }
83 
84 bool
86 {
88  return true;
89  else
90  return false;
91 }
92 
93 void
95 {
96  // Name
97  // <key_name>/ID-CERT/<id#>
98  // Content
99  // DER encoded idCert:
100  //
101  // idCert ::= SEQUENCE {
102  // validity Validity,
103  // subject Name,
104  // subjectPubKeyInfo SubjectPublicKeyInfo,
105  // extension Extensions OPTIONAL }
106  //
107  // Validity ::= SEQUENCE {
108  // notBefore Time,
109  // notAfter Time }
110  //
111  // Name ::= CHOICE {
112  // RDNSequence }
113  //
114  // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
115  //
116  // RelativeDistinguishedName ::=
117  // SET OF AttributeTypeAndValue
118  //
119  // SubjectPublicKeyInfo ::= SEQUENCE {
120  // algorithm AlgorithmIdentifier
121  // keybits BIT STRING }
122  //
123  // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
124  //
125  // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
126  //
127  // KeyLocator
128  // issuer’s certificate name
129  // Signature
130 
131  using namespace CryptoPP;
132 
133  OBufferStream os;
134  CryptoPP::FileSink sink(os);
135 
136  // idCert ::= SEQUENCE {
137  // validity Validity,
138  // subject Name,
139  // subjectPubKeyInfo SubjectPublicKeyInfo,
140  // extension Extensions OPTIONAL }
141  DERSequenceEncoder idCert(sink);
142  {
143  // Validity ::= SEQUENCE {
144  // notBefore Time,
145  // notAfter Time }
146  DERSequenceEncoder validity(idCert);
147  {
149  DEREncodeGeneralTime(validity, m_notAfter);
150  }
151  validity.MessageEnd();
152 
153  // Name ::= CHOICE {
154  // RDNSequence }
155  //
156  // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
157  DERSequenceEncoder name(idCert);
158  {
159  for (SubjectDescriptionList::iterator it = m_subjectDescriptionList.begin();
160  it != m_subjectDescriptionList.end(); ++it)
161  {
162  it->encode(name);
163  }
164  }
165  name.MessageEnd();
166 
167  // SubjectPublicKeyInfo
168  m_key.encode(idCert);
169 
170  // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
171  //
172  // Extension ::= SEQUENCE {
173  // extnID OBJECT IDENTIFIER,
174  // critical BOOLEAN DEFAULT FALSE,
175  // extnValue OCTET STRING }
176  if (!m_extensionList.empty())
177  {
178  DERSequenceEncoder extensions(idCert);
179  {
180  for (ExtensionList::iterator it = m_extensionList.begin();
181  it != m_extensionList.end(); ++it)
182  {
183  it->encode(extensions);
184  }
185  }
186  extensions.MessageEnd();
187  }
188  }
189 
190  idCert.MessageEnd();
191 
192  setContent(os.buf());
194 }
195 
196 void
198 {
199  using namespace CryptoPP;
200 
201  try {
202  OBufferStream os;
203  StringSource source(getContent().value(), getContent().value_size(), true);
204 
205  // idCert ::= SEQUENCE {
206  // validity Validity,
207  // subject Name,
208  // subjectPubKeyInfo SubjectPublicKeyInfo,
209  // extension Extensions OPTIONAL }
210  BERSequenceDecoder idCert(source);
211  {
212  // Validity ::= SEQUENCE {
213  // notBefore Time,
214  // notAfter Time }
215  BERSequenceDecoder validity(idCert);
216  {
217  BERDecodeTime(validity, m_notBefore);
218  BERDecodeTime(validity, m_notAfter);
219  }
220  validity.MessageEnd();
221 
222  // Name ::= CHOICE {
223  // RDNSequence }
224  //
225  // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
226  m_subjectDescriptionList.clear();
227  BERSequenceDecoder name(idCert);
228  {
229  while (!name.EndReached())
230  {
232  }
233  }
234  name.MessageEnd();
235 
236  // SubjectPublicKeyInfo ::= SEQUENCE {
237  // algorithm AlgorithmIdentifier
238  // keybits BIT STRING }
239  m_key.decode(idCert);
240 
241  // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
242  //
243  // Extension ::= SEQUENCE {
244  // extnID OBJECT IDENTIFIER,
245  // critical BOOLEAN DEFAULT FALSE,
246  // extnValue OCTET STRING }
247  m_extensionList.clear();
248  if (!idCert.EndReached())
249  {
250  BERSequenceDecoder extensions(idCert);
251  {
252  while (!extensions.EndReached())
253  {
254  m_extensionList.push_back(CertificateExtension(extensions));
255  }
256  }
257  extensions.MessageEnd();
258  }
259  }
260 
261  idCert.MessageEnd();
262  }
263  catch (CryptoPP::BERDecodeErr&) {
264  BOOST_THROW_EXCEPTION(Error("Certificate Decoding Error"));
265  }
266 }
267 
268 void
269 Certificate::printCertificate(std::ostream& oss, const std::string& indent) const
270 {
271  util::IndentedStream os(oss, indent);
272 
273  os << "Certificate name:\n";
274  os << " " << getName() << "\n";
275  os << "Validity:\n";
276  {
277  os << " NotBefore: " << time::toIsoString(m_notBefore) << "\n";
278  os << " NotAfter: " << time::toIsoString(m_notAfter) << "\n";
279  }
280 
281  os << "Subject Description:\n";
282  for (const auto& description : m_subjectDescriptionList)
283  os << " " << description.getOidString() << ": " << description.getValue() << "\n";
284 
285  os << "Public key bits: ";
286  switch (m_key.getKeyType()) {
287  case KeyType::RSA:
288  os << "(RSA)";
289  break;
290  case KeyType::EC:
291  os << "(EC)";
292  break;
293  default:
294  os << "(Unknown key type)";
295  break;
296  }
297  os << "\n";
298 
299  {
300  util::IndentedStream os2(os, " ");
301  CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os2), true, 64);
302  m_key.encode(encoder);
303  }
304 
305  os << "Signature Information:\n";
306  {
307  os << " Signature Type: ";
308  switch (getSignature().getType()) {
310  os << "DigestSha256";
311  break;
313  os << "SignatureSha256WithRsa";
314  break;
316  os << "SignatureSha256WithEcdsa";
317  break;
318  default:
319  os << "Unknown Signature Type";
320  }
321  os << "\n";
322 
323  if (getSignature().hasKeyLocator()) {
324  const KeyLocator& keyLocator = getSignature().getKeyLocator();
325  os << " Key Locator: ";
326  switch (keyLocator.getType()) {
328  {
329  const Name& signerName = keyLocator.getName();
330  if (signerName.isPrefixOf(getName()))
331  os << "(Self-Signed) " << keyLocator.getName();
332  else
333  os << "(Name) " << keyLocator.getName();
334  break;
335  }
337  os << "(KeyDigest)";
338  break;
340  os << "None";
341  break;
342  default:
343  os << "Unknown";
344  }
345  os << "\n";
346  }
347  }
348 }
349 
350 std::ostream&
351 operator<<(std::ostream& os, const Certificate& cert)
352 {
353  cert.printCertificate(os);
354  return os;
355 }
356 
357 } // namespace v1
358 } // namespace security
359 } // namespace ndn
Data & setContentType(uint32_t type)
Definition: data.cpp:241
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:75
time::system_clock::TimePoint m_notBefore
void wireDecode(const Block &wire)
Decode from the wire format.
Definition: data.cpp:122
Copyright (c) 2013-2017 Regents of the University of California.
Definition: oid.hpp:29
size_t DEREncodeGeneralTime(CryptoPP::BufferedTransformation &bt, const time::system_clock::TimePoint &time)
Definition: asn_ext.cpp:36
std::ostream & operator<<(std::ostream &os, const Certificate &cert)
Certificate()
The default constructor.
Data & setContent(const Block &block)
Set Content from a block.
Definition: data.cpp:194
const Signature & getSignature() const
Get Signature.
Definition: data.hpp:182
const KeyLocator & getKeyLocator() const
Get KeyLocator.
Definition: signature.hpp:131
SubjectDescriptionList m_subjectDescriptionList
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
void encode(CryptoPP::BufferedTransformation &out) const
indicates KeyLocator contains a Name
Definition: key-locator.hpp:49
BOOST_CONCEPT_ASSERT((WireEncodable< Certificate >))
static time_point now() noexcept
Definition: time.cpp:46
const Name & getName() const
get Name element
Type getType() const
bool isTooEarly()
Check if the certificate is valid.
void BERDecodeTime(CryptoPP::BufferedTransformation &bt, time::system_clock::TimePoint &time)
Definition: asn_ext.cpp:52
indicates KeyLocator is empty (internal use only)
Definition: key-locator.hpp:46
A CertificateSubjectDescription represents the SubjectDescription entry in a Certificate.
void encode()
encode certificate info into content
Represents an absolute name.
Definition: name.hpp:42
bool isPrefixOf(const Name &other) const
Check if this name is a prefix of another name.
Definition: name.cpp:260
std::string toIsoString(const system_clock::TimePoint &timePoint)
Convert to the ISO string representation of the time (YYYYMMDDTHHMMSS,fffffffff)
Definition: time.cpp:131
indicates KeyLocator contains a KeyDigest
Definition: key-locator.hpp:52
const Name & getName() const
Get name.
Definition: data.hpp:121
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
const Block & getContent() const
Get Content.
Definition: data.cpp:185
void printCertificate(std::ostream &os, const std::string &indent="") const
indicates content is a public key
bool isTooLate()
Check if the certificate is valid.
implements an output stream that constructs ndn::Buffer
void decode(CryptoPP::BufferedTransformation &in)
A CertificateExtension represents the Extension entry in a certificate.
time::system_clock::TimePoint m_notAfter
Represents a Data packet.
Definition: data.hpp:35
void wireDecode(const Block &wire)
Output to stream with specified indent or prefix.