예제 #1
0
파일: ndns-label.cpp 프로젝트: cawka/ndns
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;
}
예제 #2
0
void
ValidatorInvitation::internalCheck(const uint8_t* buf, size_t size,
                                   const Signature& signature,
                                   const Name& keyLocatorName,
                                   const Data& innerData,
                                   const OnValidated& onValidated,
                                   const OnValidationFailed& onValidationFailed)
{
  Name signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);

  TrustAnchors::const_iterator keyIt = m_trustAnchors.find(signingKeyName);
  if (keyIt == m_trustAnchors.end())
    return onValidationFailed("Cannot reach any trust anchor");

  if (!Validator::verifySignature(buf, size, signature, keyIt->second))
    return onValidationFailed("Cannot verify outer signature");

  // Temporarily disabled, we should get it back when we create a specific key for the chatroom.
  // if(!Validator::verifySignature(innerData, m_trustAnchors[signingKeyName]))
  //   return onValidationFailed("Cannot verify inner signature");

  if (!m_innerKeyRegex.match(innerData.getName()) ||
      m_innerKeyRegex.expand() != signingKeyName.getPrefix(-1))
    return onValidationFailed("Inner certificate does not comply with the rule");

  return onValidated();
}
inline void
CertificateCacheTtl::remove(const Name& certificateName)
{
  Name name = certificateName.getPrefix(-1);
  Cache::iterator it = m_cache.find(name);
  if (it != m_cache.end())
    m_cache.erase(it);
}
예제 #4
0
파일: test-common.hpp 프로젝트: eric135/NFD
void
setNameComponent(Name& name, ssize_t index, const A& ...a)
{
  Name name2 = name.getPrefix(index);
  name2.append(name::Component(a...));
  name2.append(name.getSubName(name2.size()));
  name = name2;
}
    shared_ptr<ndn::Data>
    NdnDataManager::operator[]( shared_ptr<const ndn::Interest> interest )
    {
            Name subname = interest->getName();
            auto it = subname.end()-1;

            while( ( it->isVersion() || it->isSegment()
                     || it->isSegmentOffset() || it->isTimestamp()
                     || it->isSequenceNumber() ) && ( it-- ) != subname.begin() );

            subname = subname.getPrefix( it - subname.begin() + 1 );

            if( m_producers.find( subname ) != m_producers.end() )
            {
                // find data producer
                auto producer = m_producers[subname];

                // if access level is 0, no access needs to be provided
                if( interest->getAuthTag().getAccessLevel() == 0 )
                {
                    Coordinator::
                    producerSatisfiedRequest( interest->getName().getPrefix( 2 ),
                                                interest->getName() );
                    return producer->makeData( interest );
                }

                // generate data packet
                shared_ptr<Data> data = producer->makeData( interest );

                // check that the interest's access rights
                // satisfy the data's requirements
                if( m_auth_manager->getTagAccess( interest->getAuthTag() )
                    < data->getAccessLevel() )
                {
                    Coordinator::
                    producerDeniedRequest( interest->getName().getPrefix( 2 ),
                                           interest->getName(),
                                           "Insufficient Auth" );
                    return makeNack( *data );
                }



                // check that the data satisfies interest
                if( interest->matchesData( *data ) )
                {
                    Coordinator::
                    producerSatisfiedRequest( interest->getName().getPrefix(2),
                                               interest->getName() );
                    return data;
                }
            }
           Coordinator::producerOther( interest->getName().getPrefix( 2 ),
                                       "No data matching "
                                       + interest->getName().toUri() );
           return NULL;

    };
예제 #6
0
파일: pib.cpp 프로젝트: CSUL/ndn-tools
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;
}
void
SecPublicInfoMemory::addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKey)
{
  Name identityName = keyName.getPrefix(-1);

  addIdentity(identityName);

  m_keyStore[keyName.toUri()] = make_shared<KeyRecord>(keyType, publicKey);
}
예제 #8
0
파일: strategy.cpp 프로젝트: cawka/NFD
Strategy::ParsedInstanceName
Strategy::parseInstanceName(const Name& input)
{
  for (ssize_t i = input.size() - 1; i > 0; --i) {
    if (input[i].isVersion()) {
      return {input.getPrefix(i + 1), input[i].toVersion(), input.getSubName(i + 1)};
    }
  }
  return {input, nullopt, PartialName()};
}
예제 #9
0
inline void
SecPublicInfo::addCertificateAsSystemDefault(const IdentityCertificate& certificate)
{
  addCertificate(certificate);
  Name certName = certificate.getName();
  Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certName);
  setDefaultIdentityInternal(keyName.getPrefix(-1));
  setDefaultKeyNameForIdentityInternal(keyName);
  setDefaultCertificateNameForKeyInternal(certName);
  refreshDefaultCertificate();
}
예제 #10
0
shared_ptr<RibEntry>
Rib::findParent(const Name& prefix) const
{
  for (int i = prefix.size() - 1; i >= 0; i--) {
    RibTable::const_iterator it = m_rib.find(prefix.getPrefix(i));

    if (it != m_rib.end()) {
      return (it->second);
    }
  }

  return shared_ptr<RibEntry>();
}
예제 #11
0
ptr_lib::shared_ptr<Signature>
IdentityManager::makeSignatureByCertificate
  (const Name& certificateName, DigestAlgorithm& digestAlgorithm)
{
  Name keyName = IdentityCertificate::certificateNameToPublicKeyName
    (certificateName);
  ptr_lib::shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey
    (keyName);
  KeyType keyType = publicKey->getKeyType();

  if (keyType == KEY_TYPE_RSA) {
    ptr_lib::shared_ptr<Sha256WithRsaSignature> signature
      (new Sha256WithRsaSignature());
    digestAlgorithm = DIGEST_ALGORITHM_SHA256;

    signature->getKeyLocator().setType(ndn_KeyLocatorType_KEYNAME);
    signature->getKeyLocator().setKeyName(certificateName.getPrefix(-1));
    // Ignore witness and leave the digestAlgorithm as the default.
    signature->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest
      (publicKey->getDigest());

    return signature;
  }
  else if (keyType == KEY_TYPE_ECDSA) {
    ptr_lib::shared_ptr<Sha256WithEcdsaSignature> signature
      (new Sha256WithEcdsaSignature());
    digestAlgorithm = DIGEST_ALGORITHM_SHA256;

    signature->getKeyLocator().setType(ndn_KeyLocatorType_KEYNAME);
    signature->getKeyLocator().setKeyName(certificateName.getPrefix(-1));

    return signature;
  }
  else
    throw SecurityException("Key type is not recognized");
}
예제 #12
0
shared_ptr<const Data>
ResponseCache::find(const Name& dataName, bool hasVersion) const
{
  if (!hasVersion) {
    Storage::const_iterator it = m_storage.find(dataName);
    if (it != m_storage.end())
      return it->second;
    else
      return shared_ptr<const Data>();
  }
  else {
    Storage::const_iterator it = m_storage.find(dataName.getPrefix(-1));
    if (it != m_storage.end() && it->second->getName() == dataName)
      return it->second;
    else
      return shared_ptr<const Data>();
  }
}
예제 #13
0
uint64_t
RepoEnumerator::enumerate(bool showImplicitDigest)
{
  sqlite3_stmt* m_stmt = 0;
  int rc = SQLITE_DONE;
  string sql = string("SELECT id, name, keylocatorHash FROM NDN_REPO;");
  rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &m_stmt, 0);
  if (rc != SQLITE_OK)
    throw Error("Initiation Read Entries from Database Prepare error");
  uint64_t entryNumber = 0;
  while (true) {
    rc = sqlite3_step(m_stmt);
    if (rc == SQLITE_ROW) {
      Name name;
      name.wireDecode(Block(sqlite3_column_blob(m_stmt, 1),
                            sqlite3_column_bytes(m_stmt, 1)));
      try {
        if (showImplicitDigest) {
          std::cout << name << std::endl;
        }
        else {
          std::cout << name.getPrefix(-1) << std::endl;
        }
      }
      catch (...){
        sqlite3_finalize(m_stmt);
        throw;
      }
      entryNumber++;
    }
    else if (rc == SQLITE_DONE) {
      sqlite3_finalize(m_stmt);
      break;
    }
    else {
      sqlite3_finalize(m_stmt);
      throw Error("Initiation Read Entries error");
    }
  }
  return entryNumber;
}
void
PipelineInterests::runWithExcludedSegment(const Data& data, DataCallback onData,
                                          FailureCallback onFailure)
{
  BOOST_ASSERT(onData != nullptr);

  // record the start time of running pipeline
  m_startTime = time::steady_clock::now();

  m_onData = std::move(onData);
  m_onFailure = std::move(onFailure);
  m_numOfSegmentReceived++; // count the excluded segment

  Name dataName = data.getName();
  m_prefix = dataName.getPrefix(-1);
  m_excludeSegmentNo = dataName[-1].toSegment();

  if (!data.getFinalBlockId().empty()) {
    m_hasFinalBlockId = true;
    m_lastSegmentNo = data.getFinalBlockId().toSegment();
  }
  else { // Name must contain a final block ID so that consumer knows when download finishes
    fail("Name of Data packet: " + data.getName().toUri() +
         " must a final block ID!");
  }

  // schedule the event to check retransmission timer.
  m_eventCheckRto = m_scheduler.scheduleEvent(time::milliseconds(m_options.rtoCheckInterval),
                                              bind(&PipelineInterests::checkRto, this));

  if (m_options.keepStats) {
    // schedule the event to keep track the history of cwnd size
    m_eventRecordCwnd =
      m_scheduler.scheduleEvent(time::milliseconds(m_options.cwndRecordInterval),
                                bind(&PipelineInterests::recordCwnd, this));
  }

  sendFirstInterest();
}
예제 #15
0
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(&current) * 1000.0;
  current.tm_year = current.tm_year + 2;
  MillisecondsSince1970 notAfter = timegm(&current) * 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;
}
Producer::Producer(const Name& prefix,
                   Face& face,
                   KeyChain& keyChain,
                   const security::SigningInfo& signingInfo,
                   time::milliseconds freshnessPeriod,
                   size_t maxSegmentSize,
                   bool isVerbose,
                   bool needToPrintVersion,
                   std::istream& is)
  : m_face(face)
  , m_keyChain(keyChain)
  , m_signingInfo(signingInfo)
  , m_freshnessPeriod(freshnessPeriod)
  , m_maxSegmentSize(maxSegmentSize)
  , m_isVerbose(isVerbose)
{
  if (prefix.size() > 0 && prefix[-1].isVersion()) {
    m_prefix = prefix.getPrefix(-1);
    m_versionedPrefix = prefix;
  }
  else {
    m_prefix = prefix;
    m_versionedPrefix = Name(m_prefix).appendVersion();
  }

  populateStore(is);

  if (needToPrintVersion)
    std::cout << m_versionedPrefix[-1] << std::endl;

  m_face.setInterestFilter(m_prefix,
                           bind(&Producer::onInterest, this, _2),
                           RegisterPrefixSuccessCallback(),
                           bind(&Producer::onRegisterFailed, this, _1, _2));

  if (m_isVerbose)
    std::cerr << "Data published with name: " << m_versionedPrefix << std::endl;
}
예제 #17
0
void
KeyChain::sign
  (Interest& interest, const Name& certificateName, WireFormat& wireFormat)
{
  // TODO: Handle signature algorithms other than Sha256WithRsa.
  Sha256WithRsaSignature signature;
  signature.getKeyLocator().setType(ndn_KeyLocatorType_KEYNAME);
  signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1));

  // Append the encoded SignatureInfo.
  interest.getName().append(wireFormat.encodeSignatureInfo(signature));

  // Append an empty signature so that the "signedPortion" is correct.
  interest.getName().append(Name::Component());
  // Encode once to get the signed portion, and sign.
  SignedBlob encoding = interest.wireEncode(wireFormat);
  ptr_lib::shared_ptr<Signature> signedSignature = sign
    (encoding.signedBuf(), encoding.signedSize(), certificateName);

  // Remove the empty signature and append the real one.
  interest.setName(interest.getName().getPrefix(-1).append
    (wireFormat.encodeSignatureValue(*signedSignature)));
}
예제 #18
0
파일: name-tree.cpp 프로젝트: danposch/NFD
// Name Prefix Lookup. Create Name Tree Entry if not found
shared_ptr<name_tree::Entry>
NameTree::lookup(const Name& prefix)
{
  NFD_LOG_TRACE("lookup " << prefix);

  shared_ptr<name_tree::Entry> entry;
  shared_ptr<name_tree::Entry> parent;

  for (size_t i = 0; i <= prefix.size(); i++)
    {
      Name temp = prefix.getPrefix(i);

      // insert() will create the entry if it does not exist.
      std::pair<shared_ptr<name_tree::Entry>, bool> ret = insert(temp);
      entry = ret.first;

      if (ret.second == true)
        {
          m_nItems++; // Increase the counter
          entry->m_parent = parent;

          if (static_cast<bool>(parent))
            {
              parent->m_children.push_back(entry);
            }
        }

      if (m_nItems > m_enlargeThreshold)
        {
          resize(m_enlargeFactor * m_nBuckets);
        }

      parent = entry;
    }
  return entry;
}
void
StrategyChoice::erase(const Name& prefix)
{
  BOOST_ASSERT(prefix.size() > 0);

  shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.findExactMatch(prefix);
  if (!static_cast<bool>(nameTreeEntry)) {
    return;
  }

  shared_ptr<Entry> entry = nameTreeEntry->getStrategyChoiceEntry();
  if (!static_cast<bool>(entry)) {
    return;
  }

  Strategy& oldStrategy = entry->getStrategy();

  Strategy& parentStrategy = this->findEffectiveStrategy(prefix.getPrefix(-1));
  this->changeStrategy(entry, oldStrategy.shared_from_this(), parentStrategy.shared_from_this());

  nameTreeEntry->setStrategyChoiceEntry(shared_ptr<Entry>());
  m_nameTree.eraseEntryIfEmpty(nameTreeEntry);
  --m_nItems;
}
예제 #20
0
void
StrategyChoice::erase(const Name& prefix)
{
  BOOST_ASSERT(prefix.size() > 0);

  shared_ptr<name_tree::Entry> nte = m_nameTree.findExactMatch(prefix);
  if (nte == nullptr) {
    return;
  }

  shared_ptr<Entry> entry = nte->getStrategyChoiceEntry();
  if (entry == nullptr) {
    return;
  }

  Strategy& oldStrategy = entry->getStrategy();

  Strategy& parentStrategy = this->findEffectiveStrategy(prefix.getPrefix(-1));
  this->changeStrategy(*entry, oldStrategy, parentStrategy);

  nte->setStrategyChoiceEntry(shared_ptr<Entry>());
  m_nameTree.eraseEntryIfEmpty(nte);
  --m_nItems;
}
예제 #21
0
파일: pib-db.cpp 프로젝트: CSUL/ndn-tools
int64_t
PibDb::addKey(const Name& keyName, const PublicKey& key)
{
  if (keyName.empty())
    return 0;

  Name&& identity = keyName.getPrefix(-1);
  if (!hasIdentity(identity))
    addIdentity(identity);

  sqlite3_stmt* statement;
  sqlite3_prepare_v2(m_database,
                     "INSERT INTO keys (identity_id, key_name, key_type, key_bits) \
                      values ((SELECT id FROM identities WHERE identity=?), ?, ?, ?)",
                     -1, &statement, nullptr);
  sqlite3_bind_block(statement, 1, identity.wireEncode(), SQLITE_TRANSIENT);
  sqlite3_bind_block(statement, 2, keyName.wireEncode(), SQLITE_TRANSIENT);
  sqlite3_bind_int(statement, 3, key.getKeyType());
  sqlite3_bind_blob(statement, 4, key.get().buf(), key.get().size(), SQLITE_STATIC);
  sqlite3_step(statement);
  sqlite3_finalize(statement);

  return sqlite3_last_insert_rowid(m_database);
}
                shared_ptr<ndn::Data>
                makeData( shared_ptr<const ndn::Interest> interest ) override
                {
                        auto data = make_shared<Data>(interest->getName());
                        streamoff offset  = 0;
                        streamoff segment = 0;
                        Name     name     = interest->getName();


                        // find segment and offset
                        auto it = name.end() - 1;
                        if( it->isSegmentOffset() )
                        {
                            offset = it->toSegmentOffset();
                            name = name.getPrefix( name.size() - 1 );
                        }
                        it = name.end() - 1;
                        if( it->isSegment() )
                        {
                            segment = it->toSegment();
                            name = name.getPrefix( name.size() - 1 );
                        }

                        // open file
                        ifstream file( m_filename );
                        if( !file.is_open() )
                            BOOST_THROW_EXCEPTION(runtime_error
                                                    ("Unable to open file") );

                        // figure out filesize
                        file.seekg( 0, ios_base::end );
                        streamoff end = file.tellg();

                        // check that segment is available
                        if( streamoff(segment*FILE_SEGMENT_SIZE + offset) < end )
                        {
                            // make segment
                            file.seekg( segment*FILE_SEGMENT_SIZE + offset,
                                        ios_base::beg );
                            int64_t segsize = min( streamoff(end
                                                             - segment
                                                             * FILE_SEGMENT_SIZE
                                                             + offset ),
                                                   streamoff(FILE_SEGMENT_SIZE) );
                            auto buffer = make_shared<Buffer>( segsize );
                            file.readsome( (char*) buffer->buf(), segsize );
                            data->setContentType( tlv::ContentType_Blob );
                            data->setContent( buffer );
                            data->setAccessLevel( m_access_level );
                            data->setFreshnessPeriod( time::days( 1 ) );
                        }
                        else
                        {
                            data->setContentType( tlv::ContentType_Nack );
                            data->setFreshnessPeriod( time::milliseconds( 0 ) );
                            data->setAccessLevel( 0 );
                        }

                        // close file
                        file.close();

                        m_signer.sign( *data );
                        return data;
                }
예제 #23
0
BOOST_FIXTURE_TEST_CASE(GeneralSigningInterface, IdentityManagementFixture)
{
  Name id("/id");
  Name certName = m_keyChain.createIdentity(id);
  shared_ptr<v1::IdentityCertificate> idCert = m_keyChain.getCertificate(certName);
  Name keyName = idCert->getPublicKeyName();
  m_keyChain.setDefaultIdentity(id);

  Name id2("/id2");
  Name cert2Name = m_keyChain.createIdentity(id2);
  shared_ptr<v1::IdentityCertificate> id2Cert = m_keyChain.getCertificate(cert2Name);

  // SigningInfo is set to default
  Data data1("/data1");
  m_keyChain.sign(data1);
  BOOST_CHECK(Validator::verifySignature(data1, idCert->getPublicKeyInfo()));
  BOOST_CHECK_EQUAL(data1.getSignature().getKeyLocator().getName(), certName.getPrefix(-1));

  Interest interest1("/interest1");
  m_keyChain.sign(interest1);
  BOOST_CHECK(Validator::verifySignature(interest1, idCert->getPublicKeyInfo()));
  SignatureInfo sigInfo1(interest1.getName()[-2].blockFromValue());
  BOOST_CHECK_EQUAL(sigInfo1.getKeyLocator().getName(), certName.getPrefix(-1));

  // SigningInfo is set to Identity
  Data data2("/data2");
  m_keyChain.sign(data2, SigningInfo(SigningInfo::SIGNER_TYPE_ID, id2));
  BOOST_CHECK(Validator::verifySignature(data2, id2Cert->getPublicKeyInfo()));
  BOOST_CHECK_EQUAL(data2.getSignature().getKeyLocator().getName(), cert2Name.getPrefix(-1));

  Interest interest2("/interest2");
  m_keyChain.sign(interest2, SigningInfo(SigningInfo::SIGNER_TYPE_ID, id2));
  BOOST_CHECK(Validator::verifySignature(interest2, id2Cert->getPublicKeyInfo()));
  SignatureInfo sigInfo2(interest2.getName()[-2].blockFromValue());
  BOOST_CHECK_EQUAL(sigInfo2.getKeyLocator().getName(), cert2Name.getPrefix(-1));

  // SigningInfo is set to Key
  Data data3("/data3");
  m_keyChain.sign(data3, SigningInfo(SigningInfo::SIGNER_TYPE_KEY, keyName));
  BOOST_CHECK(Validator::verifySignature(data3, idCert->getPublicKeyInfo()));
  BOOST_CHECK_EQUAL(data3.getSignature().getKeyLocator().getName(), certName.getPrefix(-1));

  Interest interest3("/interest3");
  m_keyChain.sign(interest3);
  BOOST_CHECK(Validator::verifySignature(interest3, idCert->getPublicKeyInfo()));
  SignatureInfo sigInfo3(interest1.getName()[-2].blockFromValue());
  BOOST_CHECK_EQUAL(sigInfo3.getKeyLocator().getName(), certName.getPrefix(-1));

  // SigningInfo is set to Cert
  Data data4("/data4");
  m_keyChain.sign(data4, SigningInfo(SigningInfo::SIGNER_TYPE_CERT, certName));
  BOOST_CHECK(Validator::verifySignature(data4, idCert->getPublicKeyInfo()));
  BOOST_CHECK_EQUAL(data4.getSignature().getKeyLocator().getName(), certName.getPrefix(-1));

  Interest interest4("/interest4");
  m_keyChain.sign(interest4, SigningInfo(SigningInfo::SIGNER_TYPE_CERT, certName));
  BOOST_CHECK(Validator::verifySignature(interest4, idCert->getPublicKeyInfo()));
  SignatureInfo sigInfo4(interest4.getName()[-2].blockFromValue());
  BOOST_CHECK_EQUAL(sigInfo4.getKeyLocator().getName(), certName.getPrefix(-1));


  // SigningInfo is set to DigestSha256
  Data data5("/data5");
  m_keyChain.sign(data5, SigningInfo(SigningInfo::SIGNER_TYPE_SHA256));
  BOOST_CHECK(Validator::verifySignature(data5, DigestSha256(data5.getSignature())));

  Interest interest5("/interest4");
  m_keyChain.sign(interest5, SigningInfo(SigningInfo::SIGNER_TYPE_SHA256));
  BOOST_CHECK(Validator::verifySignature(interest5,
                                         DigestSha256(Signature(interest5.getName()[-2].blockFromValue(),
                                                                interest5.getName()[-1].blockFromValue()))));
}
예제 #24
0
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>(&notBeforeStr), "certificate starting date, YYYYMMDDhhmmss")
    ("not-after,E", po::value<std::string>(&notAfterStr), "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;
}