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 }
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
Definition: filename.cxx:1863
bool unlink() const
Permanently deletes the file associated with the filename, if possible.
Definition: filename.cxx:2319
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
void set_text()
Indicates that the filename represents a text file.
Definition: filename.I:424
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
Definition: filename.I:338
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
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
Definition: filename.cxx:1899
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void preprocess_argv(int &argc, char **&argv)
Processes the argc, argv pair as needed before passing it to getopt().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.