tools: export non-default key/cert in ndnsec export
refs #5043 Change-Id: Ida6e3c041b850a132160660a58d1f219defedf22
This commit is contained in:
1 parent
a3c8bd1772
commit
bc2e78e074
5 files changed
+109
-47
No files matched your search
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user