tools: export non-default key/cert in ndnsec export

refs #5043

Change-Id: Ida6e3c041b850a132160660a58d1f219defedf22
This commit is contained in:
Junxiao Shi committed 2020-05-20 15:01:08 -06:00
1 parent a3c8bd1772
commit bc2e78e074
5 files changed
+109 -47

No files matched your search

+19 -5
View File
@@ -4,18 +4,32 @@ ndnsec-export
Synopsis
--------
**ndnsec-export** [**-h**] [**-o** *file*] [**-P** *passphrase*] *identity*
**ndnsec-export** [**-h**] [**-o** *file*] [**-P** *passphrase*]
[**-i**\|\ **-k**\|\ **-c**] *name*
Description
-----------
:program:`ndnsec-export` exports the default certificate of *identity* and its
private key to a file. It will ask for a passphrase to encrypt the private key.
:program:`ndnsec-export` exports a certificate from the **Public Info Base (PIB)** and
its private key to a file. It will ask for a passphrase to encrypt the private key.
The resulting file can be imported again using :program:`ndnsec-import`.
Options
-------
.. option:: -i, --identity
Interpret *name* as an identity name. The default certificate of the identity will be exported.
This is the default unless **-k** or **-c** is specified.
.. option:: -k, --key
Interpret *name* as a key name. The default certificate of the key will be exported.
.. option:: -c, --cert
Interpret *name* as a certificate name.
.. option:: -o <file>, --output <file>
Write to the specified output file instead of the standard output.
@@ -34,6 +48,6 @@ Export an identity's default certificate and private key into a file::
$ ndnsec-export -o alice.ndnkey /ndn/test/alice
Export an identity's default certificate and private key to the standard output::
Export a specific certificate and its private key to the standard output::
$ ndnsec-export /ndn/test/alice
$ ndnsec-export -c /ndn/edu/ucla/alice/KEY/1%5D%A7g%90%B2%CF%AA/self/%FD%00%00%01r-%D3%DC%2A
+11 -25
View File
@@ -95,7 +95,8 @@ ndnsec_cert_dump(int argc, char** argv)
return 2;
}
if (isIdentityName + isKeyName + isFileName > 1) {
int nIsNameOptions = isIdentityName + isKeyName + isFileName;
if (nIsNameOptions > 1) {
std::cerr << "ERROR: at most one of '--identity', '--key', "
"or '--file' may be specified" << std::endl;
return 2;
@@ -106,35 +107,20 @@ ndnsec_cert_dump(int argc, char** argv)
return 2;
}
security::v2::KeyChain keyChain;
security::v2::Certificate certificate;
try {
if (isIdentityName) {
certificate = keyChain.getPib()
.getIdentity(name)
.getDefaultKey()
.getDefaultCertificate();
}
else if (isKeyName) {
certificate = keyChain.getPib()
.getIdentity(security::v2::extractIdentityFromKeyName(name))
.getKey(name)
.getDefaultCertificate();
}
else if (isFileName) {
if (isFileName) {
try {
certificate = loadCertificate(name);
}
else {
certificate = keyChain.getPib()
.getIdentity(security::v2::extractIdentityFromCertName(name))
.getKey(security::v2::extractKeyNameFromCertName(name))
.getCertificate(name);
catch (const CannotLoadCertificate&) {
std::cerr << "ERROR: Cannot load the certificate from `" << name << "`" << std::endl;
return 1;
}
}
catch (const CannotLoadCertificate&) {
std::cerr << "ERROR: Cannot load the certificate from `" << name << "`" << std::endl;
return 1;
else {
security::v2::KeyChain keyChain;
certificate = getCertificateFromPib(keyChain.getPib(), name,
isIdentityName, isKeyName, nIsNameOptions == 0);
}
if (isPretty) {
+41 -17
View File
@@ -35,7 +35,10 @@ ndnsec_export(int argc, char** argv)
{
namespace po = boost::program_options;
Name identityName;
Name name;
bool isIdentityName = false;
bool isKeyName = false;
bool isCertName = false;
std::string output;
std::string password;
@@ -45,46 +48,69 @@ ndnsec_export(int argc, char** argv)
OPENSSL_cleanse(&password.front(), password.size());
} BOOST_SCOPE_EXIT_END
po::options_description description(
"Usage: ndnsec export [-h] [-o FILE] [-P PASSPHRASE] [-i] IDENTITY\n"
po::options_description visibleOptDesc(
"Usage: ndnsec export [-h] [-o FILE] [-P PASSPHRASE] [-i|-k|-c] NAME\n"
"\n"
"Options");
description.add_options()
visibleOptDesc.add_options()
("help,h", "produce help message")
("identity,i", po::value<Name>(&identityName), "name of the identity to export")
("identity,i", po::bool_switch(&isIdentityName),
"treat the NAME argument as an identity name (e.g., /ndn/edu/ucla/alice)")
("key,k", po::bool_switch(&isKeyName),
"treat the NAME argument as a key name (e.g., /ndn/edu/ucla/alice/KEY/1%5D%A7g%90%B2%CF%AA)")
("cert,c", po::bool_switch(&isCertName),
"treat the NAME argument as a certificate name "
"(e.g., /ndn/edu/ucla/alice/KEY/1%5D%A7g%90%B2%CF%AA/self/%FD%00%00%01r-%D3%DC%2A)")
("output,o", po::value<std::string>(&output)->default_value("-"),
"output file, '-' for stdout (the default)")
("password,P", po::value<std::string>(&password),
"passphrase, will prompt if empty or not specified")
;
po::positional_options_description p;
p.add("identity", 1);
po::options_description hiddenOptDesc;
hiddenOptDesc.add_options()
("name", po::value<Name>(&name));
po::options_description optDesc;
optDesc.add(visibleOptDesc).add(hiddenOptDesc);
po::positional_options_description optPos;
optPos.add("name", 1);
po::variables_map vm;
try {
po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
po::store(po::command_line_parser(argc, argv).options(optDesc).positional(optPos).run(), vm);
po::notify(vm);
}
catch (const std::exception& e) {
std::cerr << "ERROR: " << e.what() << "\n\n"
<< description << std::endl;
<< visibleOptDesc << std::endl;
return 2;
}
if (vm.count("help") > 0) {
std::cout << description << std::endl;
std::cout << visibleOptDesc << std::endl;
return 0;
}
if (vm.count("identity") == 0) {
std::cerr << "ERROR: you must specify an identity" << std::endl;
if (vm.count("name") == 0) {
std::cerr << "ERROR: you must specify a name" << std::endl;
return 2;
}
security::v2::KeyChain keyChain;
int nIsNameOptions = isIdentityName + isKeyName + isCertName;
if (nIsNameOptions > 1) {
std::cerr << "ERROR: at most one of '--identity', '--key', "
"or '--cert' may be specified" << std::endl;
return 2;
}
else if (nIsNameOptions == 0) {
isIdentityName = true;
}
auto id = keyChain.getPib().getIdentity(identityName);
security::v2::KeyChain keyChain;
auto cert = getCertificateFromPib(keyChain.getPib(), name,
isIdentityName, isKeyName, isCertName);
if (password.empty()) {
int count = 3;
@@ -97,9 +123,7 @@ ndnsec_export(int argc, char** argv)
}
}
// TODO: export all certificates, selected key pair, selected certificate
auto safeBag = keyChain.exportSafeBag(id.getDefaultKey().getDefaultCertificate(),
password.data(), password.size());
auto safeBag = keyChain.exportSafeBag(cert, password.data(), password.size());
if (output == "-")
io::save(*safeBag, std::cout);
+22
View File
@@ -68,6 +68,28 @@ getPassword(std::string& password, const std::string& prompt, bool shouldConfirm
#endif // NDN_CXX_HAVE_GETPASS
}
security::v2::Certificate
getCertificateFromPib(const security::pib::Pib& pib, const Name& name,
bool isIdentityName, bool isKeyName, bool isCertName)
{
if (isIdentityName) {
return pib.getIdentity(name)
.getDefaultKey()
.getDefaultCertificate();
}
else if (isKeyName) {
return pib.getIdentity(security::v2::extractIdentityFromKeyName(name))
.getKey(name)
.getDefaultCertificate();
}
else if (isCertName) {
return pib.getIdentity(security::v2::extractIdentityFromCertName(name))
.getKey(security::v2::extractKeyNameFromCertName(name))
.getCertificate(name);
}
NDN_CXX_UNREACHABLE;
}
security::v2::Certificate
loadCertificate(const std::string& fileName)
{
+16
View File
@@ -33,6 +33,22 @@
namespace ndn {
namespace ndnsec {
/**
* @brief Get certificate of given name from PIB.
* @param pib PIB instance, obtained from keyChain.getPib().
* @param name identity name, key name, or cert name.
* @param isIdentityName interpret @p name as identity name.
* @param isKeyName interpret @p name as key name.
* @param isCertName interpret @p name as certificate name.
* @pre exactly one of @p isIdentityName , @p isKeyName , @p isCertName must be true.
* @return a certificate.
* @throw std::invalid_argument name is invalid.
* @throw Pib::Error certificate does not exist.
*/
security::v2::Certificate
getCertificateFromPib(const security::pib::Pib& pib, const Name& name,
bool isIdentityName, bool isKeyName, bool isCertName);
class CannotLoadCertificate : public std::runtime_error
{
public: