Panda3D

pencrypt.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file pencrypt.cxx
10 * @author drose
11 * @date 2004-09-01
12 */
13
14 #include "filename.h"
15 #include "encrypt_string.h"
16 #include "pnotify.h"
17 #include "panda_getopt.h"
18 #include "preprocess_argv.h"
19
20 using std::cerr;
21 using std::endl;
22
23 std::string password;
24 bool got_password = false;
25 std::string algorithm;
26 bool got_algorithm = false;
27 int key_length = -1;
28 bool got_key_length = false;
29 int iteration_count = -1;
30 bool got_iteration_count = false;
31
32 void
33 usage() {
34 cerr
35 << "\nUsage:\n"
36 << " pencrypt [opts] file [file2 file3 ...]\n"
37 << " pencrypt -o dest_file file\n\n"
38
39 << "This program will apply an encryption algorithm to a file (or multiple files),\n"
40 << "creating an encrypted version of each file which can only be recovered using\n"
41 << "pdecrypt and the same password that was supplied to pencrypt. The compressed\n"
42 << "versions are written to a file with the same name as the original, but the\n"
43 << "extension .pe added to the filename, and the original file is removed\n"
44 << "(unless the version with -o is used, in which case you can encrypt only one\n"
45 << "file, you specify the destination file name, and the original file is not\n"
46 << "removed).\n\n"
47
48
49 << "Note that if you are adding files to a Panda multifile (.mf file) with\n"
50 << "the multify command, it is not necessary to encrypt them separately;\n"
51 << "multify has an inline encryption option.\n\n"
52
53 << "Options:\n\n"
54
55 << " -p \"password\"\n"
56 << " Specifies the password to use for encryption. There are no\n"
57 << " restrictions on the password length or contents, but longer passwords\n"
58 << " are more secure. If this is not specified, the user is prompted from\n"
59 << " standard input.\n\n"
60
61 << " -t Read the file as a text file. This will automatically convert\n"
62 << " universal end-of-line characters into a newline character, ascii\n"
63 << " 10.\n\n"
64
65 << " -a \"algorithm\"\n"
66 << " Specifies the particular encryption algorithm to use. The complete\n"
67 << " set of available algorithms is defined by the current version of\n"
68 << " OpenSSL. The default algorithm is taken from the encryption-\n"
69 << " algorithm config variable.\n\n"
70
71 << " -k key_length\n"
72 << " Specifies the key length, in bits, for the selected encryption\n"
73 << " algorithm. This only makes sense for those algorithms that support\n"
74 << " a variable key length. The default value is taken from the\n"
75 << " encryption-key-length config variable.\n\n"
76
77 << " -i iteration_count\n"
78 << " Specifies the number of times the password is hashed to generate\n"
79 << " a key. The only purpose of this is to make it computationally\n"
80 << " more expensive for an attacker to search the key space exhaustively.\n"
81 << " This should be a multiple of 1,000 and should not exceed about 65\n"
82 << " million; the value 0 indicates just one application of the hashing\n"
83 << " algorithm. The default value is taken from the encryption-iteration-\n"
84 << " count config variable.\n\n";
85 }
86
87 int
88 main(int argc, char **argv) {
89 extern char *optarg;
90 extern int optind;
91 const char *optstr = "o:p:ta:k:i:h";
92
93 Filename dest_filename;
94 bool got_dest_filename = false;
95 bool text_file = false;
96
97 preprocess_argv(argc, argv);
98 int flag = getopt(argc, argv, optstr);
99
100 while (flag != EOF) {
101 switch (flag) {
102 case 'o':
103 dest_filename = Filename::from_os_specific(optarg);
104 got_dest_filename = true;
105 break;
106
107 case 't':
108 text_file = true;
109 break;
110
111 case 'p':
112 password = optarg;
113 got_password = true;
114 break;
115
116 case 'a':
117 algorithm = optarg;
118 got_algorithm = true;
119 break;
120
121 case 'k':
122 key_length = atoi(optarg);
123 got_key_length = true;
124 break;
125
126 case 'i':
127 iteration_count = atoi(optarg);
128 got_iteration_count = true;
129 break;
130
131 case 'h':
132 case '?':
133 default:
134 usage();
135 return 1;
136 }
137 flag = getopt(argc, argv, optstr);
138 }
139
140 argc -= (optind-1);
141 argv += (optind-1);
142
143 if (argc < 2) {
144 usage();
145 return 1;
146 }
147
148 if (got_dest_filename && argc > 2) {
149 cerr << "Only one input file allowed in conjunction with -o.\n";
150 return 1;
151 }
152
153 bool all_ok = true;
154 for (int i = 1; i < argc; i++) {
155 Filename source_file = Filename::from_os_specific(argv[i]);
156 if (source_file.get_extension() == "pe") {
157 cerr << source_file << " already ends .pe; skipping.\n";
158 } else {
159 Filename dest_file = dest_filename;
160 if (!got_dest_filename) {
161 dest_file = source_file.get_fullpath() + ".pe";
162 }
163
164 // Open source file
165 pifstream read_stream;
166 if (text_file) {
167 source_file.set_text();
168 } else {
169 source_file.set_binary();
170 }
171 if (!source_file.open_read(read_stream)) {
172 cerr << "Couldn't read: " << source_file << endl;
173 all_ok = false;
174
175 } else {
176 // Open destination file
177 pofstream write_stream;
178 dest_file.set_binary();
179 if (!dest_file.open_write(write_stream, true)) {
180 cerr << "Failed to open: " << dest_file << endl;
181 all_ok = false;
182
183 } else {
184 // Prompt for password.
185 if (!got_password) {
186 cerr << "Enter password: ";
187 std::getline(std::cin, password);
188 got_password = true;
189 }
190
191 cerr << dest_file << "\n";
192 bool success = encrypt_stream(read_stream, write_stream, password,
193 algorithm, key_length, iteration_count);
194
195 read_stream.close();
196 write_stream.close();
197
198 if (!success) {
199 cerr << "Failure writing " << dest_file << "\n";
200 all_ok = false;
201 dest_file.unlink();
202
203 } else {
204 if (!got_dest_filename) {
205 source_file.unlink();
206 }
207 }
208 }
209 }
210 }
211 }
212
213 if (all_ok) {
214 return 0;
215 } else {
216 return 1;
217 }
218 }
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
Filename::open_read
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
Definition: filename.cxx:1863
Filename::unlink
bool unlink() const
Permanently deletes the file associated with the filename, if possible.
Definition: filename.cxx:2319
Filename::set_binary
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
Filename::set_text
void set_text()
Indicates that the filename represents a text file.
Definition: filename.I:424
Filename::get_fullpath
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
Definition: filename.I:338
Filename::from_os_specific
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition: filename.cxx:328
Filename::open_write
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
Definition: filename.cxx:1899
Filename::get_extension
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
encrypt_string.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
filename.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
panda_getopt.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pnotify.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
preprocess_argv
void preprocess_argv(int &argc, char **&argv)
Processes the argc, argv pair as needed before passing it to getopt().
Definition: preprocess_argv.cxx:30
preprocess_argv.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.