blob: 7e50a11094d36b67bcb832359373d73d5b207346 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Zhiyi Zhang457f09a2018-01-05 13:45:38 -08002/*
3 * Copyright (c) 2013-2018 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Yingdi Yu8d7468f2014-02-21 14:49:45 -080020 */
21
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080022#include "ndnsec.hpp"
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -080023#include "util.hpp"
Yingdi Yu8d7468f2014-02-21 14:49:45 -080024
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080025namespace ndn {
26namespace ndnsec {
27
Yingdi Yub61f5402014-02-26 17:46:11 -080028int
29ndnsec_key_gen(int argc, char** argv)
Yingdi Yu8d7468f2014-02-21 14:49:45 -080030{
31 using namespace ndn;
32 namespace po = boost::program_options;
33
Alexander Afanasyev35109a12017-01-04 15:39:06 -080034 Name identityName;
Yingdi Yub61f5402014-02-26 17:46:11 -080035 bool isDefault = true;
Zhiyi Zhang457f09a2018-01-05 13:45:38 -080036 bool isUserSpecified = false;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080037 char keyType = 'r';
Zhiyi Zhang457f09a2018-01-05 13:45:38 -080038 char keyIdTypeChoice = 'r';
39 std::string specifiedKeyId;
40 Name::Component specifiedKeyIdComponent;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080041 std::string outputFilename;
Zhiyi Zhang457f09a2018-01-05 13:45:38 -080042 KeyIdType keyIdType = KeyIdType::RANDOM;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080043
Yingdi Yuba8604d2014-10-13 19:03:12 -070044 po::options_description description("General Usage\n"
45 " ndnsec key-gen [-h] [-n] identity\n"
46 "General options");
Yingdi Yub61f5402014-02-26 17:46:11 -080047 description.add_options()
Yingdi Yu8d7468f2014-02-21 14:49:45 -080048 ("help,h", "produce help message")
Alexander Afanasyev35109a12017-01-04 15:39:06 -080049 ("identity,i", po::value<Name>(&identityName),
Yingdi Yuba8604d2014-10-13 19:03:12 -070050 "identity name, for example, /ndn/edu/ucla/alice")
51 ("not_default,n",
52 "optional, if not specified, the target identity will be set as "
53 "the default identity of the system")
Zhiyi Zhang457f09a2018-01-05 13:45:38 -080054 ("type,t", po::value<char>(&keyType),
Alexander Afanasyev35109a12017-01-04 15:39:06 -080055 "optional, key type, r for RSA key (default), e for EC key")
Zhiyi Zhang457f09a2018-01-05 13:45:38 -080056 ("key_id_type,k", po::value<char>(&keyIdTypeChoice),
57 "optional, key id type, r for 64-bit random number (default), h for SHA256 of the public key")
58 ("key_id", po::value<std::string>(&specifiedKeyId),
59 "optional, user-specified key id, cannot be used with key_id_type")
Yingdi Yuba8604d2014-10-13 19:03:12 -070060 // ("size,s", po::value<int>(&keySize)->default_value(2048),
61 // "optional, key size, 2048 (default)")
Yingdi Yu8d7468f2014-02-21 14:49:45 -080062 ;
63
64 po::positional_options_description p;
65 p.add("identity", 1);
Yingdi Yu8d7468f2014-02-21 14:49:45 -080066
Yingdi Yub61f5402014-02-26 17:46:11 -080067 po::variables_map vm;
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -080068 try {
Alexander Afanasyev82c359c2017-01-04 14:48:07 -080069 po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -080070 po::notify(vm);
71 }
72 catch (const std::exception& e) {
73 std::cerr << "ERROR: " << e.what() << std::endl;
74 std::cerr << description << std::endl;
75 return 1;
76 }
Yingdi Yub61f5402014-02-26 17:46:11 -080077
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -080078 if (vm.count("help") != 0) {
79 std::cerr << description << std::endl;
80 return 0;
81 }
Yingdi Yu8d7468f2014-02-21 14:49:45 -080082
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -080083 if (vm.count("identity") == 0) {
Zhiyi Zhang457f09a2018-01-05 13:45:38 -080084 std::cerr << "identity must be specified\n" << description << std::endl;
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -080085 return 1;
86 }
Yingdi Yu8d7468f2014-02-21 14:49:45 -080087
Alexander Afanasyev35109a12017-01-04 15:39:06 -080088 if (vm.count("not_default") != 0) {
Yingdi Yub61f5402014-02-26 17:46:11 -080089 isDefault = false;
Alexander Afanasyev35109a12017-01-04 15:39:06 -080090 }
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -080091
Zhiyi Zhang457f09a2018-01-05 13:45:38 -080092 if (vm.count("key_id_type") != 0) {
93 if (keyIdTypeChoice == 'r') {
94 // KeyIdType has already been set to KeyIdType::RANDOM
95 }
96 else if (keyIdTypeChoice == 'h') {
97 keyIdType = KeyIdType::SHA256;
98 }
99 else {
100 std::cerr << "Unrecognized key id type\n" << description << std::endl;
101 return 1;
102 }
103 if (vm.count("key_id") != 0) {
104 std::cerr << "key_id cannot be used with key_id_type\n" << description << std::endl;
105 return 1;
106 }
107 }
108
109 if (vm.count("key_id") != 0) {
110 isUserSpecified = true;
111 specifiedKeyIdComponent = name::Component::fromEscapedString(specifiedKeyId);
112 if (specifiedKeyIdComponent.empty()) {
113 std::cerr << "Key id cannot be an empty name component\n" << description << std::endl;
114 return 1;
115 }
116 if (!specifiedKeyIdComponent.isGeneric()) {
117 std::cerr << "Key id must be a generic name component\n" << description << std::endl;
118 return 1;
119 }
120 }
121
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -0800122 try {
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800123 unique_ptr<KeyParams> params;
Zhiyi Zhang457f09a2018-01-05 13:45:38 -0800124 if (keyType == 'r') {
125 if (isUserSpecified) {
126 params = make_unique<RsaKeyParams>(specifiedKeyIdComponent);
127 }
128 else {
129 params = make_unique<RsaKeyParams>(detail::RsaKeyParamsInfo::getDefaultSize(), keyIdType);
130 }
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800131 }
Zhiyi Zhang457f09a2018-01-05 13:45:38 -0800132 else if (keyType == 'e') {
133 if (isUserSpecified) {
134 params = make_unique<EcKeyParams>(specifiedKeyIdComponent);
135 }
136 else {
137 params = make_unique<EcKeyParams>(detail::EcKeyParamsInfo::getDefaultSize(), keyIdType);
138 }
139 }
140 else {
141 std::cerr << "Unrecognized key type\n" << description << std::endl;
142 return 1;
143 }
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800144
145 security::v2::KeyChain keyChain;
146 security::Identity identity;
147 security::Key key;
148 try {
149 identity = keyChain.getPib().getIdentity(identityName);
150 key = keyChain.createKey(identity, *params);
151 }
152 catch (const security::Pib::Error&) {
153 // identity doesn't exist, so create it and generate key
154 identity = keyChain.createIdentity(identityName, *params);
155 key = identity.getDefaultKey();
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -0800156 }
157
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800158 if (isDefault) {
159 keyChain.setDefaultKey(identity, key);
160 keyChain.setDefaultIdentity(identity);
161 }
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -0800162
Alexander Afanasyev35109a12017-01-04 15:39:06 -0800163 io::save(key.getDefaultCertificate(), std::cout);
Alexander Afanasyev2a047eb2014-11-30 22:45:02 -0800164 }
165 catch (const std::exception& e) {
166 std::cerr << "Error: " << e.what() << std::endl;
167 }
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800168 return 0;
169}
170
Alexander Afanasyev82c359c2017-01-04 14:48:07 -0800171} // namespace ndnsec
172} // namespace ndn