| /* -*- 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 <ndn-cpp/common.hpp> |
| |
| #include <ndn-cpp/security/certificate/certificate.hpp> |
| |
| #if NDN_CPP_USE_SYSTEM_BOOST |
| #include <boost/iostreams/stream.hpp> |
| #include <boost/iostreams/device/array.hpp> |
| namespace ndnboost = boost; |
| #else |
| // We can use ndnboost::iostreams because this is internal and will not conflict with the application if it uses boost::iostreams. |
| #include <ndnboost/iostreams/stream.hpp> |
| #include <ndnboost/iostreams/device/array.hpp> |
| #endif |
| |
| #include "../../util/logging.hpp" |
| // #include "../../util/blob-stream.hpp" |
| // #include <ndn-cpp/security/certificate/certificate.hpp> |
| #include "../../util/time.hpp" |
| |
| #include <cryptopp/asn.h> |
| #include <cryptopp/base64.h> |
| #include <cryptopp/files.h> |
| |
| #include "../../encoding/cryptopp/asn_ext.hpp" |
| |
| INIT_LOGGER("ndn.security.Certificate"); |
| |
| using namespace std; |
| |
| namespace ndn { |
| |
| Certificate::Certificate() |
| : notBefore_(std::numeric_limits<MillisecondsSince1970>::max()) |
| , notAfter_(std::numeric_limits<MillisecondsSince1970>::min()) |
| {} |
| |
| Certificate::Certificate(const Data& data) |
| // Use the copy constructor. It clones the signature object. |
| : Data(data) |
| { |
| // _LOG_DEBUG("Finish local copy: " << getContent().getContent().size()); |
| |
| decode(); |
| } |
| |
| Certificate::~Certificate() |
| { |
| //TODO: |
| } |
| |
| bool |
| Certificate::isTooEarly() |
| { |
| MillisecondsSince1970 now = ndn_getNowMilliseconds(); |
| if(now < notBefore_) |
| return true; |
| else |
| return false; |
| } |
| |
| bool |
| Certificate::isTooLate() |
| { |
| MillisecondsSince1970 now = ndn_getNowMilliseconds(); |
| if(now > notAfter_) |
| return true; |
| else |
| return false; |
| } |
| |
| void |
| Certificate::encode() |
| { |
| // Name |
| // <key_name>/ID-CERT/<id#> |
| // Content |
| // DER encoded idCert: |
| // |
| // idCert ::= SEQUENCE { |
| // validity Validity, |
| // subject Name, |
| // subjectPubKeyInfo SubjectPublicKeyInfo, |
| // extension Extensions OPTIONAL } |
| // |
| // Validity ::= SEQUENCE { |
| // notBefore Time, |
| // notAfter Time } |
| // |
| // Name ::= CHOICE { |
| // RDNSequence } |
| // |
| // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName |
| // |
| // RelativeDistinguishedName ::= |
| // SET OF AttributeTypeAndValue |
| // |
| // SubjectPublicKeyInfo ::= SEQUENCE { |
| // algorithm AlgorithmIdentifier |
| // keybits BIT STRING } |
| // |
| // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension |
| // |
| // (see http://www.ietf.org/rfc/rfc3280.txt for more detail) |
| // |
| // KeyLocator |
| // issuer’s certificate name |
| // Signature |
| |
| using namespace CryptoPP; |
| |
| OBufferStream os; |
| CryptoPP::FileSink sink(os); |
| |
| // idCert ::= SEQUENCE { |
| // validity Validity, |
| // subject Name, |
| // subjectPubKeyInfo SubjectPublicKeyInfo, |
| // extension Extensions OPTIONAL } |
| DERSequenceEncoder idCert(sink); |
| { |
| // Validity ::= SEQUENCE { |
| // notBefore Time, |
| // notAfter Time } |
| DERSequenceEncoder validity(idCert); |
| { |
| DEREncodeGeneralTime(validity, notBefore_); |
| DEREncodeGeneralTime(validity, notAfter_); |
| } |
| validity.MessageEnd(); |
| |
| // Name ::= CHOICE { |
| // RDNSequence } |
| // |
| // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName |
| DERSequenceEncoder name(idCert); |
| { |
| for(SubjectDescriptionList::iterator it = subjectDescriptionList_.begin(); |
| it != subjectDescriptionList_.end(); ++it) |
| { |
| it->encode(name); |
| } |
| } |
| name.MessageEnd(); |
| |
| // SubjectPublicKeyInfo |
| key_.encode(idCert); |
| |
| // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension |
| // |
| // Extension ::= SEQUENCE { |
| // extnID OBJECT IDENTIFIER, |
| // critical BOOLEAN DEFAULT FALSE, |
| // extnValue OCTET STRING } |
| if(!extensionList_.empty()) |
| { |
| DERSequenceEncoder extensions(idCert); |
| { |
| |
| for(ExtensionList::iterator it = extensionList_.begin(); |
| it != extensionList_.end(); ++it) |
| { |
| it->encode(extensions); |
| } |
| } |
| extensions.MessageEnd(); |
| } |
| } |
| |
| idCert.MessageEnd(); |
| |
| setContent(os.buf()); |
| setContentType(MetaInfo::TYPE_KEY); |
| } |
| |
| void |
| Certificate::decode() |
| { |
| using namespace CryptoPP; |
| |
| OBufferStream os; |
| CryptoPP::StringSource source(getContent().value(), getContent().value_size(), true); |
| |
| // idCert ::= SEQUENCE { |
| // validity Validity, |
| // subject Name, |
| // subjectPubKeyInfo SubjectPublicKeyInfo, |
| // extension Extensions OPTIONAL } |
| BERSequenceDecoder idCert(source); |
| { |
| // Validity ::= SEQUENCE { |
| // notBefore Time, |
| // notAfter Time } |
| BERSequenceDecoder validity(idCert); |
| { |
| BERDecodeTime(validity, notBefore_); |
| BERDecodeTime(validity, notAfter_); |
| } |
| validity.MessageEnd(); |
| |
| // Name ::= CHOICE { |
| // RDNSequence } |
| // |
| // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName |
| subjectDescriptionList_.clear(); |
| BERSequenceDecoder name(idCert); |
| { |
| while(!name.EndReached()) |
| { |
| subjectDescriptionList_.push_back(CertificateSubjectDescription(name)); |
| } |
| } |
| name.MessageEnd(); |
| |
| // SubjectPublicKeyInfo ::= SEQUENCE { |
| // algorithm AlgorithmIdentifier |
| // keybits BIT STRING } |
| key_.decode(idCert); |
| |
| // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension |
| // |
| // Extension ::= SEQUENCE { |
| // extnID OBJECT IDENTIFIER, |
| // critical BOOLEAN DEFAULT FALSE, |
| // extnValue OCTET STRING } |
| extensionList_.clear(); |
| if(!idCert.EndReached()) |
| { |
| BERSequenceDecoder extensions(idCert); |
| { |
| while(!extensions.EndReached()) |
| { |
| extensionList_.push_back(CertificateExtension(extensions)); |
| } |
| } |
| extensions.MessageEnd(); |
| } |
| } |
| |
| idCert.MessageEnd(); |
| } |
| |
| void |
| Certificate::printCertificate(std::ostream &os) const |
| { |
| os << "Certificate name:" << endl; |
| os << " " << getName() << endl; |
| os << "Validity:" << endl; |
| { |
| os << " NotBefore: " << toIsoString(notBefore_) << endl; |
| os << " NotAfter: " << toIsoString(notAfter_) << endl; |
| } |
| |
| os << "Subject Description:" << endl; |
| for(SubjectDescriptionList::const_iterator it = subjectDescriptionList_.begin(); |
| it != subjectDescriptionList_.end(); ++it) |
| { |
| os << " " << it->getOidString() << ": " << it->getValue() << endl; |
| } |
| |
| os << "Public key bits:" << endl; |
| CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os), true, 64); |
| key_.encode(encoder); |
| |
| // ndnboost::iostreams::stream<ndnboost::iostreams::array_source> is((const char*)key_.getKeyDer().buf(), key_.getKeyDer().size()); |
| |
| // ptr_lib::shared_ptr<der::DerNode> keyRoot = der::DerNode::parse(reinterpret_cast<der::InputIterator&> (is)); |
| |
| // der::PrintVisitor printVisitor; |
| // keyRoot->accept(printVisitor, string("")); |
| } |
| |
| } |