Panda3D
|
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 }