Change the logic in credential challenge: credential cert can under different prefix
Change-Id: Ieab9d5e111c84da8ad7896b9fac8f28887da9f2d
diff --git a/src/challenge-module/challenge-credential.cpp b/src/challenge-module/challenge-credential.cpp
index 0e5a053..2a35395 100644
--- a/src/challenge-module/challenge-credential.cpp
+++ b/src/challenge-module/challenge-credential.cpp
@@ -32,13 +32,17 @@
const std::string ChallengeCredential::FAILURE_INVALID_FORMAT = "failure-invalid-format";
const std::string ChallengeCredential::FAILURE_INVALID_CREDENTIAL = "failure-invalid-credential";
-const std::string ChallengeCredential::JSON_CREDENTIAL = "signed-cert";
+const std::string ChallengeCredential::JSON_CREDENTIAL_CERT = "issued-cert";
+const std::string ChallengeCredential::JSON_CREDENTIAL_SELF = "self-signed";
ChallengeCredential::ChallengeCredential(const std::string& configPath)
- : ChallengeModule("CREDENTIAL")
- , m_configFile(configPath)
+ : ChallengeModule("Credential")
{
- parseConfigFile();
+ if (configPath == "") {
+ m_configFile = std::string(SYSCONFDIR) + "/ndncert/challenge-credential.conf";
+ }
+ else
+ m_configFile = configPath;
}
void
@@ -70,37 +74,52 @@
JsonSection
ChallengeCredential::processSelectInterest(const Interest& interest, CertificateRequest& request)
{
+ if (m_trustAnchors.empty()) {
+ parseConfigFile();
+ }
+
// interest format: /caName/CA/_SELECT/{"request-id":"id"}/CREDENTIAL/{"credential":"..."}/<signature>
request.setChallengeType(CHALLENGE_TYPE);
- JsonSection credentialJson = getJsonFromNameComponent(interest.getName(),
- request.getCaName().size() + 4);
- std::istringstream ss(credentialJson.get<std::string>(JSON_CREDENTIAL));
+ JsonSection credentialJson = getJsonFromNameComponent(interest.getName(), request.getCaName().size() + 4);
- security::v2::Certificate credential;
+ // load credential parameters
+ std::istringstream ss1(credentialJson.get<std::string>(JSON_CREDENTIAL_CERT));
+ security::v2::Certificate cert;
try {
- credential = *(io::load<security::v2::Certificate>(ss));
+ cert = *(io::load<security::v2::Certificate>(ss1));
}
catch (const std::exception& e) {
- _LOG_TRACE("Cannot load credential parameter" << e.what());
+ _LOG_TRACE("Cannot load credential parameter: cert" << e.what());
request.setStatus(FAILURE_INVALID_FORMAT);
return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_INVALID_FORMAT);
}
+ ss1.str("");
+ ss1.clear();
- if (credential.getContent() != request.getCert().getContent()
- || credential.getKeyName() != request.getCert().getKeyName()) {
- request.setStatus(FAILURE_INVALID_CREDENTIAL);
- return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_INVALID_CREDENTIAL);
+ std::istringstream ss2(credentialJson.get<std::string>(JSON_CREDENTIAL_SELF));
+ security::v2::Certificate self;
+ try {
+ self = *(io::load<security::v2::Certificate>(ss2));
}
- Name signingKeyName = credential.getSignature().getKeyLocator().getName();
+ catch (const std::exception& e) {
+ _LOG_TRACE("Cannot load credential parameter: self-signed cert" << e.what());
+ request.setStatus(FAILURE_INVALID_FORMAT);
+ return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_INVALID_FORMAT);
+ }
+ ss2.str("");
+ ss2.clear();
+ // verify two parameters
+ Name signingKeyName = cert.getSignature().getKeyLocator().getName();
for (auto anchor : m_trustAnchors) {
if (anchor.getKeyName() == signingKeyName) {
- if (security::verifySignature(credential, anchor)) {
+ if (security::verifySignature(cert, anchor) && security::verifySignature(self, cert)) {
request.setStatus(SUCCESS);
return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, SUCCESS);
}
}
}
+
request.setStatus(FAILURE_INVALID_CREDENTIAL);
return genResponseChallengeJson(request.getRequestId(), CHALLENGE_TYPE, FAILURE_INVALID_CREDENTIAL);
}
@@ -116,7 +135,8 @@
ChallengeCredential::getSelectRequirements()
{
std::list<std::string> result;
- result.push_back("Please input the bytes of a same key certificate signed by trust anchor");
+ result.push_back("Please input the bytes of a certificate issued by the trusted CA");
+ result.push_back("Please input the bytes of a self-signed certificate for the corresponding key");
return result;
}
@@ -134,8 +154,9 @@
{
JsonSection result;
BOOST_ASSERT(status == WAIT_SELECTION);
- BOOST_ASSERT(paramList.size() == 1);
- result.put(JSON_CREDENTIAL, paramList.front());
+ BOOST_ASSERT(paramList.size() == 2);
+ result.put(JSON_CREDENTIAL_CERT, paramList.front());
+ result.put(JSON_CREDENTIAL_SELF, paramList.back());
return result;
}
diff --git a/src/challenge-module/challenge-credential.hpp b/src/challenge-module/challenge-credential.hpp
index 07f4b88..a617f18 100644
--- a/src/challenge-module/challenge-credential.hpp
+++ b/src/challenge-module/challenge-credential.hpp
@@ -32,6 +32,10 @@
* could proof his/her possession of an existing certificate from other certificate, th
* requester could finish the challenge.
*
+ * The requester needs to provide the proof of the possession of a certificate issued by
+ * a trust anchor. The challenge require the requester to pass the BASE64 certificate and
+ * a BASE64 self-signed certificate whose key is the same as the key in certificate.
+ *
* The main process of this challenge module is:
* 1. Requester provides a certificate signed by that trusted certificate as credential.
* 2. The challenge module will verify the signature of the credential.
@@ -42,7 +46,7 @@
class ChallengeCredential : public ChallengeModule
{
public:
- ChallengeCredential(const std::string& configPath = "challenge-credential.conf");
+ ChallengeCredential(const std::string& configPath = "");
PUBLIC_WITH_TESTS_ELSE_PROTECTED:
JsonSection
@@ -72,7 +76,8 @@
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
static const std::string FAILURE_INVALID_CREDENTIAL;
static const std::string FAILURE_INVALID_FORMAT;
- static const std::string JSON_CREDENTIAL;
+ static const std::string JSON_CREDENTIAL_CERT;
+ static const std::string JSON_CREDENTIAL_SELF;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
std::list<security::v2::Certificate> m_trustAnchors;
diff --git a/tests/unit-tests/challenge-credential.t.cpp b/tests/unit-tests/challenge-credential.t.cpp
index 8a0cfe5..772c57f 100644
--- a/tests/unit-tests/challenge-credential.t.cpp
+++ b/tests/unit-tests/challenge-credential.t.cpp
@@ -32,8 +32,9 @@
BOOST_AUTO_TEST_CASE(LoadConfig)
{
ChallengeCredential challenge("./tests/unit-tests/challenge-credential.conf.test");
- BOOST_CHECK_EQUAL(challenge.CHALLENGE_TYPE, "CREDENTIAL");
+ BOOST_CHECK_EQUAL(challenge.CHALLENGE_TYPE, "Credential");
+ challenge.parseConfigFile();
BOOST_CHECK_EQUAL(challenge.m_trustAnchors.size(), 1);
auto cert = challenge.m_trustAnchors.front();
BOOST_CHECK_EQUAL(cert.getName(),
@@ -44,23 +45,29 @@
{
// create trust anchor
ChallengeCredential challenge("./tests/unit-tests/challenge-credential.conf.test");
- auto identity0 = addIdentity(Name("/trust"));
- auto key0 = identity0.getDefaultKey();
- auto trustAnchor = key0.getDefaultCertificate();
+ auto identity = addIdentity(Name("/trust"));
+ auto key = identity.getDefaultKey();
+ auto trustAnchor = key.getDefaultCertificate();
+ challenge.parseConfigFile();
challenge.m_trustAnchors.front() = trustAnchor;
// create certificate request
- auto identity = addIdentity(Name("/example"));
- auto key = identity.getDefaultKey();
- auto cert = key.getDefaultCertificate();
- CertificateRequest request(Name("/example"), "123", cert);
+ auto identityA = addIdentity(Name("/example"));
+ auto keyA = identityA.getDefaultKey();
+ auto certA = key.getDefaultCertificate();
+ CertificateRequest request(Name("/example"), "123", certA);
+
+ // create requester's existing cert
+ auto identityB = addIdentity(Name("/trust/cert"));
+ auto keyB = identityB.getDefaultKey();
+ auto certB = key.getDefaultCertificate();
// using trust anchor to sign cert request to get credential
- Name credentialName = cert.getKeyName();
+ Name credentialName = certB.getKeyName();
credentialName.append("Credential").appendVersion();
- security::v2::Certificate credential = cert;
+ security::v2::Certificate credential = certB;
credential.setName(credentialName);
- credential.setContent(cert.getContent());
+ credential.setContent(certB.getContent());
m_keyChain.sign(credential, signingByCertificate(trustAnchor));
// generate SELECT interest
@@ -71,15 +78,20 @@
ss.str("");
ss.clear();
- io::save<security::v2::Certificate>(credential, ss);
std::list<std::string> paramList;
- std::string jsonString = ss.str();
- paramList.push_back(jsonString);
- JsonSection credentialJson = challenge.genSelectParamsJson(ChallengeModule::WAIT_SELECTION, paramList);
- BOOST_CHECK_EQUAL(credentialJson.get<std::string>(ChallengeCredential::JSON_CREDENTIAL), jsonString);
+ io::save<security::v2::Certificate>(credential, ss);
+ std::string paramString = ss.str();
+ paramList.push_back(paramString);
ss.str("");
ss.clear();
+ io::save<security::v2::Certificate>(certB, ss);
+ paramString = ss.str();
+ paramList.push_back(paramString);
+ ss.str("");
+ ss.clear();
+ JsonSection credentialJson = challenge.genSelectParamsJson(ChallengeModule::WAIT_SELECTION, paramList);
+
boost::property_tree::write_json(ss, credentialJson);
Block jsonContent = makeStringBlock(ndn::tlv::NameComponent, ss.str());