inline size_t calculateSkip(const Name& name, const Name& hint, const Name& zone) { size_t skip = 0; if (!hint.empty()) { // These are only asserts. The caller should supply the right parameters skip = hint.size() + 1 + zone.size(); BOOST_ASSERT(name.size() > skip); BOOST_ASSERT(name.getPrefix(hint.size()) == hint); BOOST_ASSERT(name.get(hint.size()) == FORWARDING_HINT_LABEL); BOOST_ASSERT(name.getSubName(hint.size() + 1, zone.size()) == zone); } else { skip = zone.size(); BOOST_ASSERT(name.size() > skip); BOOST_ASSERT(name.getPrefix(zone.size()) == zone); } BOOST_ASSERT(name.get(skip) == NDNS_ITERATIVE_QUERY || name.get(skip) == NDNS_CERT_QUERY); ++skip; return skip; }
bool IdentityCertificate::isCorrectName(const Name& name) { int i = name.size() - 1; string idString("ID-CERT"); for (; i >= 0; i--) { if(name.get(i).toEscapedString() == idString) break; } if (i < 0) return false; int keyIdx = 0; string keyString("KEY"); for (; keyIdx < name.size(); keyIdx++) { if(name.get(keyIdx).toEscapedString() == keyString) break; } if (keyIdx >= name.size()) return false; return true; }
BOOST_FIXTURE_TEST_CASE(FullName, IdentityManagementFixture) { Data d(Name("/local/ndn/prefix")); d.setContentType(tlv::ContentType_Blob); d.setFreshnessPeriod(10_s); d.setContent(CONTENT1, sizeof(CONTENT1)); BOOST_CHECK_THROW(d.getFullName(), Data::Error); // FullName is unavailable without signing m_keyChain.sign(d); BOOST_CHECK_EQUAL(d.hasWire(), true); Name fullName = d.getFullName(); // FullName is available after signing BOOST_CHECK_EQUAL(d.getName().size() + 1, fullName.size()); BOOST_CHECK_EQUAL_COLLECTIONS(d.getName().begin(), d.getName().end(), fullName.begin(), fullName.end() - 1); BOOST_CHECK_EQUAL(fullName.get(-1).value_size(), util::Sha256::DIGEST_SIZE); // FullName should be cached, so value() pointer points to same memory location BOOST_CHECK_EQUAL(fullName.get(-1).value(), d.getFullName().get(-1).value()); d.setFreshnessPeriod(100_s); // invalidates FullName BOOST_CHECK_THROW(d.getFullName(), Data::Error); Data d1(Block(DATA1, sizeof(DATA1))); BOOST_CHECK_EQUAL(d1.getFullName(), "/local/ndn/prefix/" "sha256digest=28bad4b5275bd392dbb670c75cf0b66f13f7942b21e80f55c0e86b374753a548"); }
Name IdentityCertificate::certificateNameToPublicKeyName(const Name& certificateName) { int i = certificateName.size() - 1; string idString("ID-CERT"); bool foundIdString = false; for (; i >= 0; i--) { if (certificateName.get(i).toEscapedString() == idString) { foundIdString = true; break; } } if(!foundIdString) throw Error("Incorrect identity certificate name " + certificateName.toUri()); Name tmpName = certificateName.getSubName(0, i); string keyString("KEY"); bool foundKeyString = false; for (i = 0; i < tmpName.size(); i++) { if (tmpName.get(i).toEscapedString() == keyString) { foundKeyString = true; break; } } if(!foundKeyString) throw Error("Incorrect identity certificate name " + certificateName.toUri()); return tmpName.getSubName(0, i).append(tmpName.getSubName(i + 1, tmpName.size() - i - 1)); }
/** * Check if the last component in the name is a segment number. * @param name The name to check. * @return True if the name ends with a segment number, otherwise false. */ static bool endsWithSegmentNumber(Name name) { return name.size() >= 1 && name.get(-1).getValue().size() >= 1 && name.get(-1).getValue().buf()[0] == 0; }
ActionItemPtr ActionLog::AddRemoteAction(shared_ptr<Data> actionData) { Name name = actionData->getName(); // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq> uint64_t seqno = name.get(-1).toNumber(); std::string sharedFolder = name.get(-2).toUri(); if (sharedFolder != m_sharedFolderName) { _LOG_ERROR("Action doesn't belong to this shared folder"); return ActionItemPtr(); } if (name.get(-3).toUri() != "action") { _LOG_ERROR("not an action"); return ActionItemPtr(); } if (name.get(-4) != m_appName) { _LOG_ERROR("Action doesn't belong to this application"); return ActionItemPtr(); } Name deviceName = name.getSubName(0, name.size() - 4); _LOG_DEBUG("From [" << name << "] extracted deviceName: " << deviceName << ", sharedFolder: " << sharedFolder << ", seqno: " << seqno); return AddRemoteAction(deviceName, seqno, actionData); }
bool IdentityCertificate::isCorrectName(const Name& name) { string idString("ID-CERT"); int i = name.size() - 1; for (; i >= 0; i--) { if (name.get(i).toUri() == idString) break; } if (i < 0) return false; string keyString("KEY"); size_t keyIndex = 0; for (; keyIndex < name.size(); keyIndex++) { if (name.get(keyIndex).toUri() == keyString) break; } if (keyIndex >= name.size()) return false; return true; }
/** * Use /localhost/nfd/rib/register to register the prefix to the faceId. * @param prefix The prefix name to register. * @param faceId The face ID. * @param face The Face which is used to sign the command interest and call * expressInterest. * @param enabled On success or error, set enabled[0] = false; */ static void registerRoute(const Name& prefix, boost::uint64_t faceId, Face* face, bool* enabled) { // Use default values; boost::uint64_t origin = 255; boost::uint64_t cost = 0; const boost::uint64_t CHILD_INHERIT = 1; boost::uint64_t flags = CHILD_INHERIT; ndn_message::ControlParametersTypes_ControlParametersMessage parameters; for (size_t i = 0; i < prefix.size(); ++i) parameters.mutable_control_parameters()->mutable_name()->add_component (prefix.get(i).getValue().buf(), prefix.get(i).getValue().size()); parameters.mutable_control_parameters()->set_face_id(faceId); parameters.mutable_control_parameters()->set_origin(origin); parameters.mutable_control_parameters()->set_cost(cost); parameters.mutable_control_parameters()->set_flags(flags); Blob encodedControlParameters = ProtobufTlv::encode(parameters); Interest interest(Name("/localhost/nfd/rib/register")); interest.getName().append(encodedControlParameters); interest.setInterestLifetimeMilliseconds(10000); // Sign and express the interest. face->makeCommandInterest(interest); face->expressInterest (interest, bind(&processRegisterResponse, _1, _2, enabled), bind(&onTimeout, _1, "Register route command timed out.", enabled)); }
bool RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len) { bool isMatched = false; /* componentset only matches one component */ if (len != 1) { return false; } for (auto& component : m_components) { if (component->match(name, offset, len)) { isMatched = true; break; } } m_matchResult.clear(); if (m_isInclusion ? isMatched : !isMatched) { m_matchResult.push_back(name.get(offset)); return true; } else return false; }
bool NdnRegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len) { bool isMatched = false; // ComponentSet only matches one component. if (len != 1) return false; for (vector<ptr_lib::shared_ptr<NdnRegexComponentMatcher> >::iterator it = components_.begin(); it != components_.end(); ++it) { if ((*it)->match(name, offset, len)) { isMatched = true; break; } } matchResult_.clear(); if (isInclusion_ ? isMatched : !isMatched) { matchResult_.push_back(name.get(offset)); return true; } else return false; }
shared_ptr<Data> Response::toData() { Name name; name.append(m_zone) .append(m_queryType) .append(m_rrLabel) .append(m_rrType); if (m_version.empty()) { name.appendVersion(); m_version = name.get(-1); } else { name.append(m_version); } shared_ptr<Data> data = make_shared<Data>(name); if (m_contentType != NDNS_BLOB && m_contentType != NDNS_KEY) { data->setContent(this->wireEncode()); } else { data->setContent(m_appContent); } data->setFreshnessPeriod(m_freshnessPeriod); data->setContentType(m_contentType); return data; }
inline bool RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len) { bool isMatched = false; /* componentset only matches one component */ if (len != 1) { return false; } for (ComponentsSet::iterator it = m_components.begin(); it != m_components.end(); ++it) { if ((*it)->match(name, offset, len)) { isMatched = true; break; } } m_matchResult.clear(); if (m_isInclusion ? isMatched : !isMatched) { m_matchResult.push_back(name.get(offset)); return true; } else return false; }
Name IdentityCertificate::certificateNameToPublicKeyName(const Name& certificateName) { int i = certificateName.size() - 1; string idString("ID-CERT"); for (; i >= 0; i--) { if (certificateName.get(i).toEscapedString() == idString) break; } Name tmpName = certificateName.getSubName(0, i); string keyString("KEY"); for (i = 0; i < tmpName.size(); i++) { if (tmpName.get(i).toEscapedString() == keyString) break; } return tmpName.getSubName(0, i).append(tmpName.getSubName(i + 1, tmpName.size() - i - 1)); }
BOOST_FIXTURE_TEST_CASE(FullName, DataIdentityFixture) { // Encoding pipeline ndn::Data d(ndn::Name("/local/ndn/prefix")); d.setContentType(tlv::ContentType_Blob); d.setFreshnessPeriod(time::seconds(10)); d.setContent(Content1, sizeof(Content1)); BOOST_CHECK_THROW(d.getFullName(), Data::Error); keyChain.sign(d, security::SigningInfo(security::SigningInfo::SIGNER_TYPE_CERT, certName)); Name fullName; BOOST_REQUIRE_NO_THROW(fullName = d.getFullName()); BOOST_CHECK_EQUAL(d.getName().hasWire(), true); BOOST_CHECK_EQUAL(fullName.hasWire(), false); // check if name was properly cached BOOST_CHECK_EQUAL(fullName.get(-1).value(), d.getFullName().get(-1).value()); // check FullName content BOOST_REQUIRE_EQUAL(d.getName().size() + 1, fullName.size()); BOOST_CHECK_EQUAL_COLLECTIONS(d.getName().begin(), d.getName().end(), fullName.begin(), fullName.end() - 1); BOOST_CHECK_EQUAL(fullName.get(-1).value_size(), 32); // FullName should be reset after the next line d.setFreshnessPeriod(time::seconds(100)); BOOST_CHECK_THROW(d.getFullName(), Data::Error); // Decoding pipeline d.wireDecode(Block(Data1, sizeof(Data1))); BOOST_REQUIRE_NO_THROW(fullName = d.getFullName()); BOOST_CHECK_EQUAL(fullName.toUri(), "/local/ndn/prefix/" "sha256digest=28bad4b5275bd392dbb670c75cf0b66f13f7942b21e80f55c0e86b374753a548"); }
Name IdentityCertificate::certificateNameToPublicKeyName(const Name& certificateName) { string idString("ID-CERT"); bool foundIdString = false; size_t idCertComponentIndex = certificateName.size() - 1; for (; idCertComponentIndex + 1 > 0; --idCertComponentIndex) { if (certificateName.get(idCertComponentIndex).toUri() == idString) { foundIdString = true; break; } } if (!foundIdString) throw Error("Incorrect identity certificate name " + certificateName.toUri()); Name tmpName = certificateName.getSubName(0, idCertComponentIndex); string keyString("KEY"); bool foundKeyString = false; size_t keyComponentIndex = 0; for (; keyComponentIndex < tmpName.size(); keyComponentIndex++) { if (tmpName.get(keyComponentIndex).toUri() == keyString) { foundKeyString = true; break; } } if (!foundKeyString) throw Error("Incorrect identity certificate name " + certificateName.toUri()); return tmpName .getSubName(0, keyComponentIndex) .append(tmpName.getSubName(keyComponentIndex + 1, tmpName.size() - keyComponentIndex - 1)); }
void keySearchOnEncryptedKeys (const vector<ptr_lib::shared_ptr<Data> >& result, int* requestCount, Name cKeyName, Name timeMarkerThirdHop, Name expectedInterest) { ASSERT_EQ(3, *requestCount); ASSERT_EQ(1, result.size()); const Data& keyData = *result[0]; const Name& keyName = keyData.getName(); ASSERT_EQ(cKeyName, keyName.getSubName(0, 4)); ASSERT_EQ(timeMarkerThirdHop.get(0), keyName.get(4)); ASSERT_EQ(Encryptor::getNAME_COMPONENT_FOR(), keyName.get(5)); ASSERT_EQ(expectedInterest.append(timeMarkerThirdHop), keyName.getSubName(6)); }
shared_ptr<IdentityCertificate> Pib::prepareCertificate(const Name& keyName, const KeyParams& keyParams, const time::system_clock::TimePoint& notBefore, const time::system_clock::TimePoint& notAfter, const Name& signerName) { // Generate mgmt key m_tpm->generateKeyPairInTpm(keyName, keyParams); shared_ptr<PublicKey> publicKey = m_tpm->getPublicKeyFromTpm(keyName); // Set mgmt cert auto certificate = make_shared<IdentityCertificate>(); Name certName = keyName.getPrefix(-1); certName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion(); certificate->setName(certName); certificate->setNotBefore(notBefore); certificate->setNotAfter(notAfter); certificate->setPublicKeyInfo(*publicKey); CertificateSubjectDescription subjectName(oid::ATTRIBUTE_NAME, keyName.getPrefix(-1).toUri()); certificate->addSubjectDescription(subjectName); certificate->encode(); Name signingKeyName; KeyLocator keyLocator; if (signerName == EMPTY_SIGNER_NAME) { // Self-sign mgmt cert keyLocator = KeyLocator(certificate->getName().getPrefix(-1)); signingKeyName = keyName; } else { keyLocator = KeyLocator(signerName.getPrefix(-1)); signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(signerName); } SignatureSha256WithRsa signature(keyLocator); certificate->setSignature(signature); EncodingBuffer encoder; certificate->wireEncode(encoder, true); Block signatureValue = m_tpm->signInTpm(encoder.buf(), encoder.size(), signingKeyName, DIGEST_ALGORITHM_SHA256); certificate->wireEncode(encoder, signatureValue); return certificate; }
Blob Tlv0_2WireFormat::encodeName(const Name& name) { struct ndn_NameComponent nameComponents[100]; NameLite nameLite (nameComponents, sizeof(nameComponents) / sizeof(nameComponents[0])); name.get(nameLite); DynamicUInt8Vector output(256); ndn_Error error; size_t dummyBeginOffset, dummyEndOffset, encodingLength; if ((error = Tlv0_2WireFormatLite::encodeName (nameLite, &dummyBeginOffset, &dummyEndOffset, DynamicUInt8ArrayLite::downCast(output), &encodingLength))) throw runtime_error(ndn_getErrorString(error)); return output.finish(encodingLength); }
Name IdentityManager::getKeyNameFromCertificatePrefix(const Name & certificatePrefix) { Name result; string keyString("KEY"); int i = 0; for(; i < certificatePrefix.size(); i++) { if (certificatePrefix.get(i).toEscapedString() == keyString) break; } if (i >= certificatePrefix.size()) throw SecurityException("Identity Certificate Prefix does not have a KEY component"); result.append(certificatePrefix.getSubName(0, i)); result.append(certificatePrefix.getSubName(i + 1, certificatePrefix.size()-i-1)); return result; }
ptr_lib::shared_ptr<IdentityCertificate> IdentityManager::selfSign(const Name& keyName) { ptr_lib::shared_ptr<IdentityCertificate> certificate(new IdentityCertificate()); Blob keyBlob = identityStorage_->getKey(keyName); ptr_lib::shared_ptr<PublicKey> publicKey(new PublicKey(keyBlob)); #if NDN_CPP_HAVE_GMTIME_SUPPORT time_t nowSeconds = time(NULL); struct tm current = *gmtime(&nowSeconds); current.tm_hour = 0; current.tm_min = 0; current.tm_sec = 0; MillisecondsSince1970 notBefore = timegm(¤t) * 1000.0; current.tm_year = current.tm_year + 2; MillisecondsSince1970 notAfter = timegm(¤t) * 1000.0; certificate->setNotBefore(notBefore); certificate->setNotAfter(notAfter); #else // Don't really expect this to happen. throw SecurityException("selfSign: Can't set certificate validity because time functions are not supported by the standard library."); #endif Name certificateName = keyName.getPrefix(-1).append("KEY").append (keyName.get(-1)).append("ID-CERT").append (Name::Component::fromNumber((uint64_t)ndn_getNowMilliseconds())); certificate->setName(certificateName); certificate->setPublicKeyInfo(*publicKey); certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri())); certificate->encode(); signByCertificate(*certificate, certificate->getName()); return certificate; }
void Forwarder::onIncomingInterest(Face& inFace, const Interest& interest) { int level = inFace.getLevel(); Name prefix; Name interestName = interest.getName(); if(level>=0 && level+2<interestName.size()){ if(hasLeft(interestName.get(level+1).toUri())){ Name pitEntryNameToDivide; for(int i=level+1;i<interestName.size()-1;++i) pitEntryNameToDivide.append(interestName.get(i)); std::string nameString = pitEntryNameToDivide.toUri(); nameString = nameString.substr(4,nameString.length()-7);std::cout<<nameString<<std::endl; Name pitEntryNameToDivideNew(nameString); int bracketCount = 0; int begin = 0; for(int i=0;i<pitEntryNameToDivideNew.size();++i){ if(hasLeft(pitEntryNameToDivideNew.get(i).toUri())){ bracketCount+=hasLeft(pitEntryNameToDivideNew.get(i).toUri()); } if(hasRight(pitEntryNameToDivideNew.get(i).toUri())){ bracketCount-=hasRight(pitEntryNameToDivideNew.get(i).toUri()); } if(hasDot(pitEntryNameToDivideNew.get(i).toUri()) || i==pitEntryNameToDivideNew.size()-1){ if(bracketCount==0){ Name subPrefix; for(int j=0;j<=level;++j){ subPrefix.append(interestName.get(j)); } for(int j=begin;j<i;++j){ subPrefix.append(pitEntryNameToDivideNew.get(j)); } begin = i+1; if(hasDot(pitEntryNameToDivideNew.get(i).toUri())){ subPrefix.append(pitEntryNameToDivideNew.get(i).toUri().substr(0,pitEntryNameToDivideNew.get(i).size()-3)); }else{ subPrefix.append(pitEntryNameToDivideNew.get(i).toUri().substr(0,pitEntryNameToDivideNew.get(i).size())); } std::cout<<"subPrefix: "<<subPrefix<<" "<<subPrefix.get(level+1)<<std::endl; std::cout<<"interest name: "<<interest.getName()<<std::endl; Interest interestNew(interest); subPrefix.append(interest.getName().get(interest.getName().size()-1)); interestNew.setName(subPrefix); prefix.append(subPrefix.get(level+1)); onIncomingSubInterest(inFace, interestNew, prefix); } } } }else{ prefix.append(interestName.get(level+1)); onIncomingSubInterest(inFace,interest,prefix); } }else if(level+2==interestName.size()){ onIncomingSubInterest(inFace,interest,prefix); } }
int ndnsec_cert_gen(int argc, char** argv) { using boost::tokenizer; using boost::escaped_list_separator; using namespace ndn; using namespace ndn::time; namespace po = boost::program_options; std::string notBeforeStr; std::string notAfterStr; std::string subjectName; std::string requestFile("-"); std::string signId; std::string subjectInfo; bool hasSignId = false; bool isNack = false; po::options_description description("General Usage\n ndnsec cert-gen [-h] [-S date] [-E date] [-N subject-name] [-I subject-info] [-s sign-id] request\nGeneral options"); description.add_options() ("help,h", "produce help message") ("not-before,S", po::value<std::string>(¬BeforeStr), "certificate starting date, YYYYMMDDhhmmss") ("not-after,E", po::value<std::string>(¬AfterStr), "certificate ending date, YYYYMMDDhhmmss") ("subject-name,N", po::value<std::string>(&subjectName), "subject name") ("subject-info,I", po::value<std::string>(&subjectInfo), "subject info, pairs of OID and string description: \"2.5.4.10 'University of California, Los Angeles'\"") ("nack", "Generate revocation certificate (NACK)") ("sign-id,s", po::value<std::string>(&signId), "signing Identity, system default identity if not specified") ("request,r", po::value<std::string>(&requestFile), "request file name, - for stdin") ; po::positional_options_description p; p.add("request", 1); po::variables_map vm; try { po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm); po::notify(vm); } catch (const std::exception& e) { std::cerr << "ERROR: " << e.what() << std::endl; return 1; } if (vm.count("help") != 0) { std::cerr << description << std::endl; return 0; } if (vm.count("sign-id") != 0) { hasSignId = true; } if (vm.count("nack") != 0) { isNack = true; } std::vector<CertificateSubjectDescription> otherSubDescrypt; tokenizer<escaped_list_separator<char> > subjectInfoItems (subjectInfo, escaped_list_separator<char> ("\\", " \t", "'\"")); tokenizer<escaped_list_separator<char> >::iterator it = subjectInfoItems.begin(); while (it != subjectInfoItems.end()) { std::string oid = *it; it++; if (it == subjectInfoItems.end()) { std::cerr << "ERROR: unmatched info for oid [" << oid << "]" << std::endl; return 1; } std::string value = *it; otherSubDescrypt.push_back(CertificateSubjectDescription(oid, value)); it++; } system_clock::TimePoint notBefore; system_clock::TimePoint notAfter; if (vm.count("not-before") == 0) { notBefore = system_clock::now(); } else { notBefore = fromIsoString(notBeforeStr.substr(0, 8) + "T" + notBeforeStr.substr(8, 6)); } if (vm.count("not-after") == 0) { notAfter = notBefore + days(365); } else { notAfter = fromIsoString(notAfterStr.substr(0, 8) + "T" + notAfterStr.substr(8, 6)); if (notAfter < notBefore) { std::cerr << "not-before is later than not-after" << std::endl; return 1; } } if (vm.count("request") == 0) { std::cerr << "request file must be specified" << std::endl; return 1; } shared_ptr<IdentityCertificate> selfSignedCertificate = getIdentityCertificate(requestFile); if (!static_cast<bool>(selfSignedCertificate)) { std::cerr << "ERROR: input error" << std::endl; return 1; } KeyChain keyChain; Name keyName = selfSignedCertificate->getPublicKeyName(); Name signIdName; Name certName; if (!hasSignId) signIdName = keyChain.getDefaultIdentity(); else signIdName = Name(signId); if (signIdName.isPrefixOf(keyName)) { // if signee's namespace is a sub-namespace of signer, for example, signer's namespace is // /ndn/test, signee's namespace is /ndn/test/alice, the generated certificate name is // /ndn/test/KEY/alice/ksk-1234/ID-CERT/%01%02 certName.append(signIdName) .append("KEY") .append(keyName.getSubName(signIdName.size())) .append("ID-CERT") .appendVersion(); } else { // if signee's namespace is not a sub-namespace of signer, for example, signer's namespace is // /ndn/test, signee's namespace is /ndn/ucla/bob, the generated certificate name is // /ndn/ucla/bob/KEY/ksk-1234/ID-CERT/%01%02 certName.append(keyName.getPrefix(-1)) .append("KEY") .append(keyName.get(-1)) .append("ID-CERT") .appendVersion(); } Block wire; if (!isNack) { if (vm.count("subject-name") == 0) { std::cerr << "subject_name must be specified" << std::endl; return 1; } CertificateSubjectDescription subDescryptName("2.5.4.41", subjectName); IdentityCertificate certificate; certificate.setName(certName); certificate.setNotBefore(notBefore); certificate.setNotAfter(notAfter); certificate.setPublicKeyInfo(selfSignedCertificate->getPublicKeyInfo()); certificate.addSubjectDescription(subDescryptName); for (size_t i = 0; i < otherSubDescrypt.size(); i++) certificate.addSubjectDescription(otherSubDescrypt[i]); certificate.encode(); keyChain.createIdentity(signIdName); Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(signIdName); keyChain.sign(certificate, signingCertificateName); wire = certificate.wireEncode(); } else { Data revocationCert; // revocationCert.setContent(void*, 0); // empty content revocationCert.setName(certName); keyChain.createIdentity(signIdName); Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(signIdName); keyChain.sign(revocationCert, signingCertificateName); wire = revocationCert.wireEncode(); } try { using namespace CryptoPP; StringSource ss(wire.wire(), wire.size(), true, new Base64Encoder(new FileSink(std::cout), true, 64)); } catch (const CryptoPP::Exception& e) { std::cerr << "ERROR: " << e.what() << std::endl; return 1; } return 0; }