129int main(
int argc,
char *argv[])
133 fprintf(stderr,
"Called '%s' with %d arguments:\n", (argc>0?argv[0]:
"exe"), argc-1);
134 for(
int i=1; i<argc; i++) {
135 fprintf(stderr,
"[%d] '%s'\n", i, argv[i]);
137 fprintf(stderr,
"\n");
145 const std::string command = argv[argi++];
147 if( command ==
"pack") {
148 std::vector<std::string> enc_pub_keys;
149 std::string sign_sec_key_fname;
150 jau::io::secure_string sign_sec_key_passphrase;
151 std::string target_path;
153 std::string plaintext_version =
"0";
154 std::string plaintext_version_parent =
"0";
156 std::string plaintext_fname_output;
157 bool verbose =
false;
158 std::string fname_output = jau::io::fs::to_named_fd(1);
159 std::string fname_input = jau::io::fs::to_named_fd(0);
160 for(; argi < argc; ++argi) {
161 if( 0 == strcmp(
"-epk", argv[argi]) && argi + 1 < argc ) {
162 enc_pub_keys.emplace_back(argv[++argi] );
163 }
else if( 0 == strcmp(
"-ssk", argv[argi]) && argi + 1 < argc ) {
164 sign_sec_key_fname = argv[++argi];
165 }
else if( 0 == strcmp(
"-sskp", argv[argi]) && argi + 1 < argc ) {
166 char* argv_pp = argv[++argi];
167 size_t pp_len = strlen(argv_pp);
168 sign_sec_key_passphrase = jau::io::secure_string(argv_pp, pp_len);
169 ::explicit_bzero(argv_pp, pp_len);
170 }
else if( 0 == strcmp(
"-target_path", argv[argi]) && argi + 1 < argc ) {
171 target_path = argv[++argi];
172 }
else if( 0 == strcmp(
"-subject", argv[argi]) && argi + 1 < argc ) {
173 subject = argv[++argi];
174 }
else if( 0 == strcmp(
"-version", argv[argi]) && argi + 1 < argc ) {
175 plaintext_version = argv[++argi];
176 }
else if( 0 == strcmp(
"-version_parent", argv[argi]) && argi + 1 < argc ) {
177 plaintext_version_parent = argv[++argi];
178 }
else if( 0 == strcmp(
"-hash", argv[argi]) && argi + 1 < argc ) {
179 plaintext_hash_algo = argv[++argi];
180 }
else if( 0 == strcmp(
"-hashout", argv[argi]) && argi + 1 < argc ) {
181 plaintext_fname_output = argv[++argi];
182 }
else if( 0 == strcmp(
"-out", argv[argi]) && argi + 1 < argc ) {
183 fname_output = argv[++argi];
184 }
else if( 0 == strcmp(
"-verbose", argv[argi]) ) {
187 }
else if( argi == argc - 1 ) {
188 fname_input = argv[argi];
191 if( target_path.empty() ) {
192 target_path = fname_input;
194 if( 0 == enc_pub_keys.size() ||
195 sign_sec_key_fname.empty() )
197 jau_PLAIN_PRINT(
true,
"Pack: Error: Arguments incomplete");
202 std::unique_ptr<jau::io::ByteStream> input = jau::io::to_ByteInStream(fname_input);
203 if(
nullptr == input ) {
204 jau_PLAIN_PRINT(
true,
"Pack: Error: source '%s' failed to open", fname_input);
209 enc_pub_keys, sign_sec_key_fname, sign_sec_key_passphrase,
210 *input, target_path, subject,
211 plaintext_version, plaintext_version_parent,
213 plaintext_hash_algo, fname_output);
214 if( !plaintext_fname_output.empty() ) {
218 jau_PLAIN_PRINT(
true,
"Pack: Encrypted %s to %s", fname_input, fname_output);
219 jau_PLAIN_PRINT(
true,
"Pack: %s", ph.
to_string(
true,
true));
220 jau_PLAIN_PRINT(
true,
"Pack: %s", cpl->
toString());
224 if( command ==
"unpack") {
225 std::vector<std::string> sign_pub_keys;
226 std::string dec_sec_key_fname;
227 jau::io::secure_string dec_sec_key_passphrase;
229 std::string plaintext_fname_output;
230 bool verbose =
false;
231 std::string fname_output = jau::io::fs::to_named_fd(1);
232 std::string fname_input = jau::io::fs::to_named_fd(0);
233 for(; argi < argc; ++argi) {
234 if( 0 == strcmp(
"-spk", argv[argi]) && argi + 1 < argc ) {
235 sign_pub_keys.emplace_back(argv[++argi] );
236 }
else if( 0 == strcmp(
"-dsk", argv[argi]) && argi + 1 < argc ) {
237 dec_sec_key_fname = argv[++argi];
238 }
else if( 0 == strcmp(
"-dskp", argv[argi]) && argi + 1 < argc ) {
239 char* argv_pp = argv[++argi];
240 size_t pp_len = strlen(argv_pp);
241 dec_sec_key_passphrase = jau::io::secure_string(argv_pp, pp_len);
242 ::explicit_bzero(argv_pp, pp_len);
243 }
else if( 0 == strcmp(
"-hash", argv[argi]) && argi + 1 < argc ) {
244 plaintext_hash_algo = argv[++argi];
245 }
else if( 0 == strcmp(
"-hashout", argv[argi]) && argi + 1 < argc ) {
246 plaintext_fname_output = argv[++argi];
247 }
else if( 0 == strcmp(
"-out", argv[argi]) && argi + 1 < argc ) {
248 fname_output = argv[++argi];
249 }
else if( 0 == strcmp(
"-verbose", argv[argi]) ) {
252 }
else if( argi == argc - 1 ) {
253 fname_input = argv[argi];
256 if( 0 == sign_pub_keys.size() ||
257 dec_sec_key_fname.empty() )
259 jau_PLAIN_PRINT(
true,
"Unpack: Error: Arguments incomplete");
264 std::unique_ptr<jau::io::ByteStream> input = jau::io::to_ByteInStream(fname_input);
265 if(
nullptr == input ) {
266 jau_PLAIN_PRINT(
true,
"Unpack: Error: source '%s' failed to open", fname_input);
273 plaintext_hash_algo, fname_output);
274 if( !plaintext_fname_output.empty() ) {
279 jau_PLAIN_PRINT(
true,
"Unpack: Decypted %s to %s", fname_input, fname_output);
280 jau_PLAIN_PRINT(
true,
"Unpack: %s", ph.
to_string(
true,
true));
281 jau_PLAIN_PRINT(
true,
"Unpack: %s", cpl->
toString());
285 if( command ==
"hash") {
287 bool verbose =
false;
288 std::string fname_output = jau::io::fs::to_named_fd(1);
289 std::string fname_input = jau::io::fs::to_named_fd(0);
290 for(; argi < argc; ++argi) {
291 if( 0 == strcmp(
"-hash", argv[argi]) && argi + 1 < argc ) {
292 hash_algo = argv[++argi];
293 }
else if( 0 == strcmp(
"-out", argv[argi]) && argi + 1 < argc ) {
294 fname_output = argv[++argi];
295 }
else if( 0 == strcmp(
"-verbose", argv[argi]) ) {
298 }
else if( argi == argc - 1 ) {
299 fname_input = argv[argi];
302 uint64_t bytes_hashed = 0;
304 if(
nullptr != hash ) {
305 std::string hash_str = jau::toHexString(hash->data(), hash->size(), jau::lb_endian_t::little);
308 jau_PLAIN_PRINT(
true,
"Hash: algo '%s', bytes %s, '%s' of '%s'", hash_algo, jau::to_decstring(bytes_hashed),
309 hash_str, fname_input);
315 if( command ==
"hashcheck") {
316 bool verbose =
false;
317 std::string fname_input =
"/dev/stdin";
318 for(; argi < argc; ++argi) {
319 if( 0 == strcmp(
"-verbose", argv[argi]) ) {
322 }
else if( argi == argc - 1 ) {
323 fname_input = argv[argi];
326 std::ifstream in(fname_input, std::ios::in | std::ios::binary);
328 jau_PLAIN_PRINT(
true,
"HashCheck: Error: Couldn't open file '%s'", fname_input);
332 std::string hash_line0;
333 while( std::getline(in, hash_line0) ) {
335 std::string hash_algo;
336 std::string hash_value1;
337 std::string hashed_file;
338 char* haystack =
const_cast<char*
>( hash_line0.data() );
340 char* p = std::strstr(haystack,
" ");
342 jau_PLAIN_PRINT(
true,
"HashCheck: Error: %s:%d: No separator to hash value found", fname_input, line_no);
346 hash_algo = std::string(haystack);
350 char* p = std::strstr(haystack,
" *");
352 jau_PLAIN_PRINT(
true,
"HashCheck: Error: %s:%d: No separator to hashed file found", fname_input, line_no);
356 hash_value1 = std::string(haystack);
359 hashed_file = std::string(haystack);
361 jau::io::fs::file_stats hashed_file_stats(hashed_file);
362 if( hashed_file_stats.has_fd() ) {
363 jau_PLAIN_PRINT(
true,
"HashCheck: Ignored: %s:%d: Named file descriptor: %s",
364 fname_input, line_no, hashed_file_stats.toString());
368 const std::string hash_line1 = hash_algo+
" "+hash_value1+
" *"+hashed_file;
369 uint64_t bytes_hashed = 0;
371 if(
nullptr == hash2 ) {
372 jau_PLAIN_PRINT(
true,
"HashCheck: Error: %s:%d: Bad format: %s", fname_input, line_no, hash_line1);
375 const std::string hash_value2 = jau::toHexString(hash2->data(), hash2->size(), jau::lb_endian_t::little);
376 if( hash_value2 != hash_value1 ) {
377 const std::string hash_line2 = hash_algo+
" "+hash_value2+
" *"+hashed_file;
378 jau_PLAIN_PRINT(
true,
"HashCheck: Error: %s:%d: Hash value mismatch", fname_input, line_no);
379 jau_PLAIN_PRINT(
true,
"- expected: %s", hash_line1);
380 jau_PLAIN_PRINT(
true,
"- produced: %s", hash_line2);
382 }
else if( verbose ) {
383 jau_PLAIN_PRINT(
true,
"HashCheck: OK: %s:%d: %s", fname_input, line_no, hash_line1);
388 fprintf(stderr,
"Unknown command\n");