blob: 98c2f5c835f6d61e09b69d676755f5d5cd397aba [file] [log] [blame]
#include <ndn-cpp-dev/data.hpp>
#include <ndn-cpp-dev/security/key-chain.hpp>
#include <ndn-cpp-dev/util/random.hpp>
#include <ndn-cpp-dev/security/identity-certificate.hpp>
#include <ndn-cpp-dev/security/certificate-subject-description.hpp>
#include <ndn-cpp-dev/security/signature-sha256-with-rsa.hpp>
#include <ndn-cpp-dev/util/io.hpp>
#include <boost/algorithm/string.hpp>
#include <exception>
namespace
{
class CertTool: public ndn::KeyChain
{
typedef SecPublicInfo::Error InfoError;
typedef SecTpm::Error TpmError;
public:
CertTool()
{
}
std::pair<ndn::shared_ptr<ndn::IdentityCertificate> , bool>
getCertificate(ndn::Name certificateName)
{
try
{
ndn::shared_ptr<ndn::IdentityCertificate> cert=
ndn::KeyChain::getCertificate(certificateName);
return std::make_pair(cert , true);
}
catch(TpmError& e)
{
std::cerr<<"Certificate Not Found"<<std::endl;
return std::make_pair(
ndn::make_shared<ndn::IdentityCertificate>() , false);
}
}
/* Return Certificate Name */
ndn::Name
createIdentity(const ndn::Name identityName, const ndn::Name signee,
bool isUnSigned=false)
{
ndn::KeyChain::deleteIdentity(identityName);
ndn::KeyChain::addIdentity(identityName);
ndn::Name keyName;
try
{
keyName = ndn::KeyChain::getDefaultKeyNameForIdentity(identityName);
}
catch(InfoError& e)
{
keyName = ndn::KeyChain::generateRSAKeyPairAsDefault(identityName, true);
}
ndn::shared_ptr<ndn::PublicKey> pubKey;
try
{
pubKey = ndn::KeyChain::getPublicKey(keyName);
}
catch(InfoError& e)
{
return identityName;
}
ndn::Name certName;
try
{
certName = ndn::KeyChain::getDefaultCertificateNameForKey(keyName);
}
catch(InfoError& e)
{
ndn::shared_ptr<ndn::IdentityCertificate> certificate =
ndn::make_shared<ndn::IdentityCertificate>();
ndn::Name certificateName = keyName.getPrefix(-1);
certificateName.append("KEY").append(
keyName.get(-1)).append("ID-CERT").appendVersion();
certificate->setName(certificateName);
certificate->setNotBefore(ndn::getNow());
certificate->setNotAfter(ndn::getNow() + 63072000 /* 2 years*/);
certificate->setPublicKeyInfo(*pubKey);
certificate->addSubjectDescription(
ndn::CertificateSubjectDescription("2.5.4.41",
keyName.toUri()));
certificate->encode();
if ( !isUnSigned )
{
try
{
signByIdentity(*certificate,signee);
}
catch(InfoError& e)
{
try
{
ndn::KeyChain::deleteIdentity(identityName);
}
catch(InfoError& e)
{
}
return identityName;
}
ndn::KeyChain::addCertificate(*(certificate));
}
certName=certificate->getName();
}
return certName;
}
template<typename T>
void
signByIdentity(T& packet, const ndn::Name& identityName)
{
ndn::KeyChain::signByIdentity(packet,identityName);
}
bool
loadCertificate(std::string inputFile)
{
ndn::shared_ptr<ndn::IdentityCertificate> cert =
ndn::io::load<ndn::IdentityCertificate>(
inputFile.c_str(), ndn::io::BASE_64);
try
{
ndn::KeyChain::deleteCertificate(cert->getName());
ndn::KeyChain::addCertificate(*(cert));
return true;
}
catch(InfoError& e)
{
std::cout << e.what() <<std::endl;
return false;
}
}
};
}
void
createCertificateAndDump(std::string identity, std::string signee,
std::string outputFile)
{
ndn::Name certName;
CertTool ct;
if( boost::iequals(signee, "self") || boost::iequals(signee, "unsigned"))
{
certName=ct.createIdentity(ndn::Name(identity),ndn::Name(identity));
}
else
{
certName=ct.createIdentity(ndn::Name(identity),ndn::Name(signee));
}
std::pair<ndn::shared_ptr<ndn::IdentityCertificate> , bool> cert =
ct.getCertificate(certName);
if( cert.second )
{
std::cout<<*(cert.first)<<std::endl;
std::ofstream outFile(outputFile.c_str());
ndn::io::save(*(cert.first),outFile,ndn::io::BASE_64);
}
else
{
std::cerr<<"Certificate not created or signee not found"<<std::endl;
}
}
void
signCertificateAndDump(std::string signee,
std::string inputFile, std::string outputFile)
{
ndn::shared_ptr<ndn::IdentityCertificate> cert =
ndn::io::load<ndn::IdentityCertificate>(
inputFile.c_str(), ndn::io::BASE_64);
try
{
CertTool ct;
ct.signByIdentity(*(cert), ndn::Name(signee));
std::cout<<*(cert)<<std::endl;
std::ofstream outFile(outputFile.c_str());
ndn::io::save(*(cert),outFile,ndn::io::BASE_64);
}
catch(std::exception& e)
{
std::cout << e.what() <<std::endl;
}
}
void
loadCertificate(std::string inputFile)
{
try
{
CertTool ct;
if (ct.loadCertificate(inputFile) )
{
std::cout<<"Certificate Loaded in Key Chain"<<std::endl;
}
}
catch(std::exception& e)
{
std::cout << e.what() <<std::endl;
}
}
static int
usage(const std::string& program)
{
std::cout << "Usage: " << program << " [OPTIONS...]"<<std::endl;
std::cout << " Cert Tool options...." << std::endl;
std::cout << " -(c|s|l) , Create or Sign or Load identity's certificate" << std::endl;
std::cout << " -i , --identityName New/singing identity name" <<std::endl;
std::cout << " -I , --signeeIdentity Identity Name of signer or self for self signing or unsigned" <<std::endl;
std::cout << " -f , --inputFile Input file name for -s option"<<std::endl;
std::cout << " -o , --outputFile Output file name where certificate will be dumped"<<std::endl;
std::cout << " -h , Display this help message" << std::endl;
exit(EXIT_FAILURE);
}
int main(int argc, char **argv)
{
bool isCreate=false;
bool isSign=false;
bool isLoad=false;
int operationCount=0;
std::string programName(argv[0]);
std::string inputFile;
std::string outputFile;
std::string identityName;
std::string signeeIdentityName;
int opt;
while ((opt = getopt(argc, argv, "cslf:I:i:f:o:h")) != -1)
{
switch (opt)
{
case 'c':
isCreate=true;
operationCount++;
break;
case 's':
isSign=true;
operationCount++;
break;
case 'l':
isLoad=true;
operationCount++;
break;
case 'f':
inputFile=optarg;
break;
case 'o':
outputFile=optarg;
break;
case 'i':
identityName=optarg;
case 'I':
signeeIdentityName=optarg;
break;
case 'h':
default:
usage(programName);
return EXIT_FAILURE;
}
}
if( operationCount > 1)
{
std::cerr<<"Can not perform more than one operation at once !"<<std::endl;
usage(programName);
}
if ( isCreate )
{
if ( identityName.empty() ||
signeeIdentityName.empty() || outputFile.empty())
{
usage(programName);
}
createCertificateAndDump(identityName,signeeIdentityName, outputFile);
}
if( isSign )
{
if ( signeeIdentityName.empty() ||
inputFile.empty() || outputFile.empty())
{
usage(programName);
}
signCertificateAndDump(signeeIdentityName, inputFile, outputFile);
}
if( isLoad )
{
if ( inputFile.empty() )
{
usage(programName);
}
loadCertificate(inputFile);
}
return EXIT_SUCCESS;
}