Skip to content

Commit

Permalink
refactor consumer certificate fetching
Browse files Browse the repository at this point in the history
  • Loading branch information
tianyuan129 committed Aug 15, 2023
1 parent 4cea89f commit 75b1c6b
Show file tree
Hide file tree
Showing 14 changed files with 230 additions and 140 deletions.
19 changes: 13 additions & 6 deletions examples/kp-aa-example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,25 @@
namespace examples {

using ndn::nacabe::KpAttributeAuthority;
ndn::KeyChain m_keyChain;
ndn::security::Certificate m_cert = m_keyChain.getPib().getIdentity("/example/aa").getDefaultKey().getDefaultCertificate();
class AttributeAuthority
{
public:
AttributeAuthority()
: m_aa(m_cert, m_face, m_keyChain)
: m_aaCert(m_keyChain.getPib().getIdentity("/example/aa").getDefaultKey().getDefaultCertificate())
, m_aa(m_aaCert, m_face, m_validator, m_keyChain)
{
auto consumerCert1 = m_keyChain.getPib().getIdentity("/example/consumer").getDefaultKey().getDefaultCertificate();
m_aa.addNewPolicy(consumerCert1, "attribute");
// 1. this approach will directly use the certificate passed in without validation
// m_aa.addNewPolicy(consumerCert1, "attribute");
// 2. this approach will try fetch corresponding certificate when receiving
// corresponding DKEY Interest
m_aa.addNewPolicy("/example/consumer", "attribute");
m_validator.load("trust-schema.conf");

// self certificate filter
m_face.setInterestFilter(m_cert.getKeyName(),
m_face.setInterestFilter(m_aaCert.getKeyName(),
[this] (auto&...) {
m_face.put(m_cert);
m_face.put(m_aaCert);
}
);
}
Expand All @@ -55,6 +59,9 @@ class AttributeAuthority

private:
ndn::Face m_face;
ndn::KeyChain m_keyChain;
ndn::ValidatorConfig m_validator{m_face};
ndn::security::Certificate m_aaCert;
KpAttributeAuthority m_aa;
};

Expand Down
40 changes: 27 additions & 13 deletions examples/kp-consumer-example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,51 @@

#include <iostream>

using namespace ndn::time_literals;
namespace examples {

class Consumer
{
public:
Consumer()
: m_producerCert(m_keyChain.getPib().getIdentity("/example/producer").getDefaultKey().getDefaultCertificate())
, m_consumerCert(m_keyChain.getPib().getIdentity("/example/consumer").getDefaultKey().getDefaultCertificate())
, m_consumer(m_face, m_keyChain, m_validator, m_consumerCert,
m_keyChain.getPib().getIdentity("/example/aa").getDefaultKey().getDefaultCertificate())
: m_consumerCert(m_keyChain.getPib().getIdentity("/example/consumer").getDefaultKey().getDefaultCertificate())
{
m_validator.load("trust-schema.conf");
m_consumer.obtainDecryptionKey();
m_face.registerPrefix(m_consumerCert.getIdentity(),
[this] (const ndn::Name& name) {
m_face.setInterestFilter(m_consumerCert.getKeyName(),
[=] (const auto&, const auto& interest) {
std::cout << ">> I: " << interest << std::endl;
// for own certificate
m_face.put(m_consumerCert);
}
);
m_consumer = std::make_shared<ndn::nacabe::Consumer>(
m_face, m_keyChain, m_validator, m_consumerCert,
m_keyChain.getPib().getIdentity("/example/aa").getDefaultKey().getDefaultCertificate()
);
m_consumer->obtainDecryptionKey();
},
[this] (const auto& prefix, const std::string& reason) {
std::cerr << "ERROR: Failed to register prefix '" << prefix
<< "' with the local forwarder (" << reason << ")" << std::endl;
m_face.shutdown();
}
);
}

void
run()
{
ndn::Name dataName("/randomData");
m_consumer.consume(m_producerCert.getIdentity().append(dataName),
m_consumer->consume("/example/producer/randomData",
[] (const auto& result) {
std::cout << "Received data: " << std::string(result.begin(), result.end()) << std::endl;
},
[] (const auto& error) {
std::cout << "Error: " << error << std::endl;
}
);

m_face.processEvents();
processEvents(1_s);
}

void processEvents(ndn::time::milliseconds ms)
Expand All @@ -66,21 +82,19 @@ class Consumer
ndn::Face m_face;
ndn::KeyChain m_keyChain;
ndn::ValidatorConfig m_validator{m_face};
ndn::security::Certificate m_producerCert;
ndn::security::Certificate m_consumerCert;
ndn::nacabe::Consumer m_consumer;
std::shared_ptr<ndn::nacabe::Consumer> m_consumer;
};

} // namespace examples

int
main(int argc, char** argv)
{
using namespace ndn::time_literals;

try {
examples::Consumer consumer;
consumer.processEvents(5_s);
consumer.processEvents(1_s);
consumer.run();
return 0;
}
Expand Down
9 changes: 4 additions & 5 deletions examples/kp-producer-example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@

namespace examples {

ndn::KeyChain m_keyChain;
ndn::security::Certificate m_cert = m_keyChain.getPib().getIdentity("/example/producer").getDefaultKey().getDefaultCertificate();
class Producer
{
public:
Producer()
: m_producerCert(m_cert)
: m_producerCert(m_keyChain.getPib().getIdentity("/example/producer").getDefaultKey().getDefaultCertificate())
, m_producer(m_face, m_keyChain, m_validator, m_producerCert,
m_keyChain.getPib().getIdentity("/example/aa").getDefaultKey().getDefaultCertificate())
{
Expand Down Expand Up @@ -72,8 +70,8 @@ class Producer
[=] (const auto&, const auto& interest) {
std::cout << ">> I: " << interest << std::endl;
// for own certificate
if (interest.getName().isPrefixOf(m_cert.getName())) {
m_face.put(m_cert);
if (interest.getName().isPrefixOf(m_producerCert.getName())) {
m_face.put(m_producerCert);
}
// for content data segments
putSegments(interest, contentData);
Expand All @@ -96,6 +94,7 @@ class Producer

private:
ndn::Face m_face;
ndn::KeyChain m_keyChain;
ndn::ValidatorConfig m_validator{m_face};
ndn::security::Certificate m_producerCert;
ndn::nacabe::Producer m_producer;
Expand Down
9 changes: 7 additions & 2 deletions examples/run-examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
# If you would like to try on a normal user account, make sure that identity /consumerPrefix1, /aaPrefix, /producerPrefix
# are not used, as these keys will be deleted.

if ndnsec list | grep "/example/consumer\|/example/aa\|/example/producer"
if ndnsec list | grep "/example"
then
echo "cleaning example identities"
ndnsec delete /example/consumer
ndnsec delete /example
ndnsec delete /example/aa
ndnsec delete /example/consumer
ndnsec delete /example/producer
fi

Expand All @@ -26,6 +27,9 @@ ndnsec sign-req /example/producer | ndnsec cert-gen -s /example -i example | ndn
ndnsec key-gen -t r /example/consumer > /dev/null
ndnsec sign-req /example/consumer | ndnsec cert-gen -s /example -i example | ndnsec cert-install -

# cp example-trust-anchor.cert $1/examples/example-trust-anchor.cert
# cp trust-schema.conf $1/examples/trust-schema.conf
nfdc cs erase /example
$1/examples/kp-aa-example &
aa_pid=$!
sleep 1
Expand All @@ -39,6 +43,7 @@ exit_val=$?
kill $aa_pid
kill $pro_pid

ndnsec delete /example
ndnsec delete /example/consumer
ndnsec delete /example/aa
ndnsec delete /example/producer
Expand Down
75 changes: 48 additions & 27 deletions src/attribute-authority.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ namespace nacabe {
NDN_LOG_INIT(nacabe.AttributeAuthority);

AttributeAuthority::AttributeAuthority(const security::Certificate& identityCert, Face& face,
KeyChain& keyChain, const AbeType& abeType, size_t maxSegmentSize)
security::Validator& validator, KeyChain& keyChain,
const AbeType& abeType, size_t maxSegmentSize)
: m_cert(identityCert)
, m_face(face)
, m_validator(validator)
, m_keyChain(keyChain)
, m_abeType(abeType)
, m_maxSegmentSize(maxSegmentSize)
Expand All @@ -50,7 +52,7 @@ AttributeAuthority::AttributeAuthority(const security::Certificate& identityCert
NDN_THROW(std::runtime_error("Unsupported ABE type: " + m_abeType));
}

// prefix registration
// prefix registrationexport NDN_LOG="nacabe.*=TRACE:ndn.security.Validator=DEBUG"
m_registeredPrefix = m_face.registerPrefix(m_cert.getIdentity(),
[this] (const Name& name) {
NDN_LOG_TRACE("Prefix " << name << " registered successfully");
Expand Down Expand Up @@ -84,6 +86,7 @@ AttributeAuthority::onDecryptionKeyRequest(const Interest& request)

Name supposedKeyName(request.getName().at(m_cert.getIdentity().size() + 1).blockFromValue());
if (requestName.at(-1).isSegment() && requestName.at(-2).isVersion()) {
NDN_LOG_DEBUG("For DKEY segment --------> " << requestName);
auto mapIterator = m_segmentMap.find(requestName.getPrefix(-1));
if (mapIterator != m_segmentMap.end()) {
for (auto data : mapIterator->second) {
Expand All @@ -97,32 +100,49 @@ AttributeAuthority::onDecryptionKeyRequest(const Interest& request)
NDN_LOG_DEBUG("KeyName --------> " << supposedKeyName);
Name identityName = security::extractIdentityFromKeyName(supposedKeyName);
// verify request and generate token
auto optionalCert = m_trustConfig.findCertificate(identityName);
if (!optionalCert) {
NDN_LOG_INFO("DKEY Request Interest cannot be authenticated: no certificate for " << identityName);
return;
auto optionalCert = m_trustConfig.findCertificateFromLocal(supposedKeyName);
if (optionalCert) {
NDN_LOG_INFO("Found local certificate for " << supposedKeyName << ", bypass certificate fetching...");
auto dkSegments = generateDecryptionKeySegments(Name(request.getName()).appendVersion(), *optionalCert);
if (dkSegments.size() > 0) {
m_face.put(*dkSegments.at(0));
}
}
NDN_LOG_INFO("Find consumer(decryptor) certificate: " << optionalCert->getName());
auto ABEPrvKey = getPrivateKey(identityName);
auto prvBuffer = ABEPrvKey.toBuffer();

// prepare segments
Data result;
Name resultName = Name(request.getName()).appendVersion();
result.setName(resultName);
result.setFreshnessPeriod(5_s);
Block dkBlock = encryptDataContentWithCK(prvBuffer, optionalCert->getPublicKey());
span<const uint8_t> dkSpan = make_span(dkBlock.data(), dkBlock.size());
// the freshness period should be configurable, but this value shouldn't affect much
auto dkSegments = m_segmenter.segment(dkSpan, resultName, m_maxSegmentSize, 4_s);
m_segmentMap.emplace(resultName, dkSegments);
m_face.put(*dkSegments.at(0));
else {
m_trustConfig.findCertificateFromNetwork(m_face, m_validator, supposedKeyName,
[&] (const security::Certificate& cert) {
NDN_LOG_INFO("Validated consumer(decryptor) certificate: " << cert.getName());
auto dkSegments = generateDecryptionKeySegments(Name(request.getName()).appendVersion(), cert);
if (dkSegments.size() > 0) {
m_face.put(*dkSegments.at(0));
}
},
[supposedKeyName] (const std::string& errorInfo) {
NDN_LOG_INFO("Cannot encrypt DKEY: no verified certificate for " << supposedKeyName << ", errorInfo:" << errorInfo);
}
);
};
}
else {
// ignore
}
}

SPtrVector<Data>
AttributeAuthority::generateDecryptionKeySegments(const Name& objName, const security::Certificate& cert)
{
// prepare segments
auto ABEPrvKey = getPrivateKey(cert.getIdentity());
auto prvBuffer = ABEPrvKey.toBuffer();
Block dkBlock = encryptDataContentWithCK(prvBuffer, cert.getPublicKey());
span<const uint8_t> dkSpan = make_span(dkBlock.data(), dkBlock.size());
// the freshness period should be configurable, but this value shouldn't affect much
auto dkSegments = m_segmenter.segment(dkSpan, objName, m_maxSegmentSize, 4_s);

m_segmentMap.emplace(objName, dkSegments);
return dkSegments;
}

void
AttributeAuthority::onPublicParamsRequest(const Interest& interest)
{
Expand All @@ -144,9 +164,9 @@ AttributeAuthority::onPublicParamsRequest(const Interest& interest)
m_face.put(result);
}

CpAttributeAuthority::CpAttributeAuthority(const security::Certificate& identityCert,
Face& face, KeyChain& keyChain)
: AttributeAuthority(identityCert, face, keyChain, ABE_TYPE_CP_ABE)
CpAttributeAuthority::CpAttributeAuthority(const security::Certificate& identityCert, Face& face,
security::Validator& validator, KeyChain& keyChain)
: AttributeAuthority(identityCert, face, validator, keyChain, ABE_TYPE_CP_ABE)
{
}

Expand Down Expand Up @@ -175,9 +195,10 @@ CpAttributeAuthority::getPrivateKey(Name identityName)
return algo::ABESupport::getInstance().cpPrvKeyGen(m_pubParams, m_masterKey, attrs);
}

KpAttributeAuthority::KpAttributeAuthority(const security::Certificate& identityCert,
Face& face, KeyChain& keyChain, size_t maxSegmentSize)
: AttributeAuthority(identityCert, face, keyChain, ABE_TYPE_KP_ABE, maxSegmentSize)
KpAttributeAuthority::KpAttributeAuthority(const security::Certificate& identityCert, Face& face,
security::Validator& validator, KeyChain& keyChain,
size_t maxSegmentSize)
: AttributeAuthority(identityCert, face, validator, keyChain, ABE_TYPE_KP_ABE, maxSegmentSize)
{
}

Expand Down
15 changes: 11 additions & 4 deletions src/attribute-authority.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ class AttributeAuthority : noncopyable
{
protected:
AttributeAuthority(const security::Certificate& identityCert, Face& m_face,
KeyChain& keyChain, const AbeType& abeType,
size_t maxSegmentSize = 1500);
security::Validator& validator, KeyChain& keyChain,
const AbeType& abeType, size_t maxSegmentSize = 1500);

virtual
~AttributeAuthority();
Expand All @@ -49,6 +49,9 @@ class AttributeAuthority : noncopyable
getPrivateKey(Name identityName) = 0;

private:
SPtrVector<Data>
generateDecryptionKeySegments(const Name& objName, const security::Certificate& cert);

void
onDecryptionKeyRequest(const Interest& interest);

Expand All @@ -59,6 +62,7 @@ class AttributeAuthority : noncopyable
security::Certificate m_cert;
Face& m_face;
KeyChain& m_keyChain;
security::Validator& m_validator;
TrustConfig m_trustConfig;
ssize_t m_maxSegmentSize;
std::map<Name, SPtrVector<ndn::Data>> m_segmentMap;
Expand All @@ -77,7 +81,8 @@ class AttributeAuthority : noncopyable
class CpAttributeAuthority: public AttributeAuthority
{
public:
CpAttributeAuthority(const security::Certificate& identityCert, Face& m_face, KeyChain& keyChain);
CpAttributeAuthority(const security::Certificate& identityCert, Face& m_face,
security::Validator& validator, KeyChain& keyChain);

/**
* @brief Add a new policy <decryptor name, decryptor attributes> into the state.
Expand Down Expand Up @@ -111,7 +116,9 @@ class CpAttributeAuthority: public AttributeAuthority
class KpAttributeAuthority: public AttributeAuthority
{
public:
KpAttributeAuthority(const security::Certificate& identityCert, Face& m_face, KeyChain& keyChain, size_t maxSegmentSize = 1500);
KpAttributeAuthority(const security::Certificate& identityCert, Face& m_face,
security::Validator& validator, KeyChain& keyChain,
size_t maxSegmentSize = 1500);

/**
* @brief Add a new policy <decryptor name, decryptor attributes> into the state.
Expand Down
1 change: 0 additions & 1 deletion src/param-fetcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ void
ParamFetcher::onAttributePubParams(const Data& pubParamData)
{
NDN_LOG_INFO("[onAttributePubParams()] Get public parameters");
// auto optionalAAKey = m_trustConfig.findCertificate(m_attrAuthorityPrefix);

m_validator.validate(pubParamData,
[this, pubParamData] (const Data& data) {
Expand Down
Loading

0 comments on commit 75b1c6b

Please sign in to comment.