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