Panda3D

pencrypt.cxx

00001 // Filename: pencrypt.cxx
00002 // Created by:  drose (01Sep04)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "filename.h"
00016 #include "encrypt_string.h"
00017 #include "pnotify.h"
00018 
00019 #ifndef HAVE_GETOPT
00020   #include "gnu_getopt.h"
00021 #else
00022   #ifdef PHAVE_GETOPT_H
00023     #include <getopt.h>
00024   #endif
00025 #endif
00026 
00027 string password;
00028 bool got_password = false;
00029 string algorithm;
00030 bool got_algorithm = false;
00031 int key_length = -1;
00032 bool got_key_length = false;
00033 int iteration_count = -1;
00034 bool got_iteration_count = false;
00035 
00036 void 
00037 usage() {
00038   cerr
00039     << "\nUsage:\n"
00040     << "   pencrypt [opts] file [file2 file3 ...]\n"
00041     << "   pencrypt -o dest_file file\n\n"
00042     
00043     << "This program will apply an encryption algorithm to a file (or multiple files),\n"
00044     << "creating an encrypted version of each file which can only be recovered using\n"
00045     << "pdecrypt and the same password that was supplied to pencrypt.  The compressed\n"
00046     << "versions are written to a file with the same name as the original, but the\n"
00047     << "extension .pe added to the filename, and the original file is removed\n"
00048     << "(unless the version with -o is used, in which case you can encrypt only one\n"
00049     << "file, you specify the destination file name, and the original file is not\n"
00050     << "removed).\n\n"
00051 
00052 
00053     << "Note that if you are adding files to a Panda multifile (.mf file) with\n"
00054     << "the multify command, it is not necessary to encrypt them separately;\n"
00055     << "multify has an inline encryption option.\n\n"
00056 
00057     << "Options:\n\n"
00058 
00059     << "  -p \"password\"\n"
00060     << "      Specifies the password to use for encryption.  There are no\n"
00061     << "      restrictions on the password length or contents, but longer passwords\n"
00062     << "      are more secure.  If this is not specified, the user is prompted from\n"
00063     << "      standard input.\n\n"
00064 
00065     << "  -t  Read the file as a text file.  This will automatically convert\n"
00066     << "      universal end-of-line characters into a newline character, ascii\n"
00067     << "      10.\n\n"
00068 
00069     << "  -a \"algorithm\"\n"
00070     << "      Specifies the particular encryption algorithm to use.  The complete\n"
00071     << "      set of available algorithms is defined by the current version of\n"
00072     << "      OpenSSL.  The default algorithm is taken from the encryption-\n"
00073     << "      algorithm config variable.\n\n"
00074 
00075     << "  -k key_length\n"
00076     << "      Specifies the key length, in bits, for the selected encryption\n"
00077     << "      algorithm.  This only makes sense for those algorithms that support\n"
00078     << "      a variable key length.  The default value is taken from the\n"
00079     << "      encryption-key-length config variable.\n\n"
00080 
00081     << "  -i iteration_count\n"
00082     << "      Specifies the number of times the password is hashed to generate\n"
00083     << "      a key.  The only purpose of this is to make it computationally\n"
00084     << "      more expensive for an attacker to search the key space exhaustively.\n"
00085     << "      This should be a multiple of 1,000 and should not exceed about 65\n"
00086     << "      million; the value 0 indicates just one application of the hashing\n"
00087     << "      algorithm.  The default value is taken from the encryption-iteration-\n"
00088     << "      count config variable.\n\n";
00089 }
00090 
00091 int
00092 main(int argc, char *argv[]) {
00093   extern char *optarg;
00094   extern int optind;
00095   const char *optstr = "o:p:ta:k:i:h";
00096 
00097   Filename dest_filename;
00098   bool got_dest_filename = false;
00099   bool text_file = false;
00100 
00101   int flag = getopt(argc, argv, optstr);
00102 
00103   while (flag != EOF) {
00104     switch (flag) {
00105     case 'o':
00106       dest_filename = Filename::from_os_specific(optarg);
00107       got_dest_filename = true;
00108       break;
00109 
00110     case 't':
00111       text_file = true;
00112       break;
00113 
00114     case 'p':
00115       password = optarg;
00116       got_password = true;
00117       break;
00118 
00119     case 'a':
00120       algorithm = optarg;
00121       got_algorithm = true;
00122       break;
00123 
00124     case 'k':
00125       key_length = atoi(optarg);
00126       got_key_length = true;
00127       break;
00128 
00129     case 'i':
00130       iteration_count = atoi(optarg);
00131       got_iteration_count = true;
00132       break;
00133 
00134     case 'h':
00135     case '?':
00136     default:
00137       usage();
00138       return 1;
00139     }
00140     flag = getopt(argc, argv, optstr);
00141   }
00142 
00143   argc -= (optind-1);
00144   argv += (optind-1);
00145 
00146   if (argc < 2) {
00147     usage();
00148     return 1;
00149   }
00150 
00151   if (got_dest_filename && argc > 2) {
00152     cerr << "Only one input file allowed in conjunction with -o.\n";
00153     return 1;
00154   }
00155 
00156   bool all_ok = true;
00157   for (int i = 1; i < argc; i++) {
00158     Filename source_file = Filename::from_os_specific(argv[i]);
00159     if (source_file.get_extension() == "pe") {
00160       cerr << source_file << " already ends .pe; skipping.\n";
00161     } else {
00162       Filename dest_file = dest_filename;
00163       if (!got_dest_filename) {
00164         dest_file = source_file.get_fullpath() + ".pe";
00165       }
00166 
00167       // Open source file
00168       pifstream read_stream;
00169       if (text_file) {
00170         source_file.set_text();
00171       } else {
00172         source_file.set_binary();
00173       }
00174       if (!source_file.open_read(read_stream)) {
00175         cerr << "Couldn't read: " << source_file << endl;
00176         all_ok = false;
00177 
00178       } else {
00179         // Open destination file
00180         pofstream write_stream;
00181         dest_file.set_binary();
00182         if (!dest_file.open_write(write_stream, true)) {
00183           cerr << "Failed to open: " << dest_file << endl;
00184           all_ok = false;
00185 
00186         } else {
00187           // Prompt for password.
00188           if (!got_password) {
00189             cerr << "Enter password: ";
00190             getline(cin, password);
00191             got_password = true;
00192           }
00193 
00194           cerr << dest_file << "\n";
00195           bool success = encrypt_stream(read_stream, write_stream, password,
00196                                         algorithm, key_length, iteration_count);
00197           
00198           read_stream.close();
00199           write_stream.close();
00200           
00201           if (!success) {
00202             cerr << "Failure writing " << dest_file << "\n";
00203             all_ok = false;
00204             dest_file.unlink();
00205             
00206           } else {
00207             if (!got_dest_filename) {
00208               source_file.unlink();
00209             }
00210           }
00211         }
00212       }
00213     }
00214   }
00215 
00216   if (all_ok) {
00217     return 0;
00218   } else {
00219     return 1;
00220   }
00221 }
 All Classes Functions Variables Enumerations