Panda3D
encrypt_string.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 encrypt_string.cxx
10  * @author drose
11  * @date 2007-01-30
12  */
13 
14 #include "encrypt_string.h"
15 
16 #ifdef HAVE_OPENSSL
17 #include "encryptStream.h"
18 #include "virtualFileSystem.h"
19 #include "config_express.h"
20 
21 using std::istream;
22 using std::istringstream;
23 using std::ostream;
24 using std::ostringstream;
25 using std::string;
26 
27 /**
28  * Encrypts the indicated source string using the given password, and the
29  * algorithm specified by encryption-algorithm. Returns the encrypted string.
30  */
31 string
32 encrypt_string(const string &source, const string &password,
33  const string &algorithm, int key_length, int iteration_count) {
34  ostringstream dest;
35 
36  {
37  OEncryptStream encrypt;
38  if (!algorithm.empty()) {
39  encrypt.set_algorithm(algorithm);
40  }
41  if (key_length > 0) {
42  encrypt.set_key_length(key_length);
43  }
44  if (iteration_count >= 0) {
45  encrypt.set_iteration_count(iteration_count);
46  }
47  encrypt.open(&dest, false, password);
48  encrypt.write(source.data(), source.length());
49 
50  if (encrypt.fail()) {
51  return string();
52  }
53  }
54 
55  return dest.str();
56 }
57 
58 /**
59  * Decrypts the previously-encrypted string using the given password (which
60  * must be the same password passed to encrypt()). The return value is the
61  * decrypted string.
62  *
63  * Note that a decryption error, including an incorrect password, cannot
64  * easily be detected, and the return value may simply be a garbage string.
65  */
66 string
67 decrypt_string(const string &source, const string &password) {
68  istringstream source_stream(source);
69  ostringstream dest_stream;
70 
71  if (!decrypt_stream(source_stream, dest_stream, password)) {
72  return string();
73  }
74 
75  return dest_stream.str();
76 }
77 
78 /**
79  * Encrypts the data from the source file using the given password. The
80  * source file is read in its entirety, and the encrypted results are written
81  * to the dest file, overwriting its contents. The return value is bool on
82  * success, or false on failure.
83  */
84 EXPCL_PANDA_EXPRESS bool
85 encrypt_file(const Filename &source, const Filename &dest, const string &password,
86  const string &algorithm, int key_length, int iteration_count) {
88  Filename source_filename = source;
89  if (!source_filename.is_binary_or_text()) {
90  // The default is binary, if not specified otherwise.
91  source_filename.set_binary();
92  }
93  istream *source_stream = vfs->open_read_file(source_filename, true);
94  if (source_stream == nullptr) {
95  express_cat.info() << "Couldn't open file " << source_filename << "\n";
96  return false;
97  }
98 
99  Filename dest_filename = Filename::binary_filename(dest);
100  ostream *dest_stream = vfs->open_write_file(dest_filename, true, true);
101  if (dest_stream == nullptr) {
102  express_cat.info() << "Couldn't open file " << dest_filename << "\n";
103  vfs->close_read_file(source_stream);
104  return false;
105  }
106 
107  bool result = encrypt_stream(*source_stream, *dest_stream, password,
108  algorithm, key_length, iteration_count);
109  vfs->close_read_file(source_stream);
110  vfs->close_write_file(dest_stream);
111  return result;
112 }
113 
114 /**
115  * Decrypts the data from the source file using the given password (which must
116  * match the same password passed to encrypt()). The source file is read in
117  * its entirety, and the decrypted results are written to the dest file,
118  * overwriting its contents. The return value is bool on success, or false on
119  * failure.
120  *
121  * Note that a decryption error, including an incorrect password, cannot
122  * easily be detected, and the output may simply be a garbage string.
123  */
124 EXPCL_PANDA_EXPRESS bool
125 decrypt_file(const Filename &source, const Filename &dest, const string &password) {
126  Filename source_filename = Filename::binary_filename(source);
128  istream *source_stream = vfs->open_read_file(source_filename, false);
129  if (source_stream == nullptr) {
130  express_cat.info() << "Couldn't open file " << source_filename << "\n";
131  return false;
132  }
133 
134  Filename dest_filename = dest;
135  if (!dest_filename.is_binary_or_text()) {
136  // The default is binary, if not specified otherwise.
137  dest_filename.set_binary();
138  }
139  ostream *dest_stream = vfs->open_write_file(dest_filename, true, true);
140  if (dest_stream == nullptr) {
141  express_cat.info() << "Couldn't open file " << dest_filename << "\n";
142  vfs->close_read_file(source_stream);
143  return false;
144  }
145 
146  bool result = decrypt_stream(*source_stream, *dest_stream, password);
147  vfs->close_read_file(source_stream);
148  vfs->close_write_file(dest_stream);
149  return result;
150 }
151 
152 /**
153  * Encrypts the data from the source stream using the given password. The
154  * source stream is read from its current position to the end-of-file, and the
155  * encrypted results are written to the dest stream. The return value is bool
156  * on success, or false on failure.
157  */
158 bool
159 encrypt_stream(istream &source, ostream &dest, const string &password,
160  const string &algorithm, int key_length, int iteration_count) {
161  OEncryptStream encrypt;
162  if (!algorithm.empty()) {
163  encrypt.set_algorithm(algorithm);
164  }
165  if (key_length > 0) {
166  encrypt.set_key_length(key_length);
167  }
168  if (iteration_count >= 0) {
169  encrypt.set_iteration_count(iteration_count);
170  }
171  encrypt.open(&dest, false, password);
172 
173  static const size_t buffer_size = 4096;
174  char buffer[buffer_size];
175 
176  source.read(buffer, buffer_size);
177  size_t count = source.gcount();
178  while (count != 0) {
179  encrypt.write(buffer, count);
180  source.read(buffer, buffer_size);
181  count = source.gcount();
182  }
183  encrypt.close();
184 
185  return (!source.fail() || source.eof()) && (!encrypt.fail());
186 }
187 
188 /**
189  * Decrypts the data from the previously-encrypted source stream using the
190  * given password (which must be the same password passed to encrypt()). The
191  * source stream is read from its current position to the end-of-file, and the
192  * decrypted results are written to the dest stream. The return value is bool
193  * on success, or false on failure.
194  *
195  * Note that a decryption error, including an incorrect password, cannot
196  * easily be detected, and the output may simply be a garbage string.
197  */
198 bool
199 decrypt_stream(istream &source, ostream &dest, const string &password) {
200  IDecryptStream decrypt(&source, false, password);
201 
202  static const size_t buffer_size = 4096;
203  char buffer[buffer_size];
204 
205  decrypt.read(buffer, buffer_size);
206  size_t count = decrypt.gcount();
207  while (count != 0) {
208  dest.write(buffer, count);
209  decrypt.read(buffer, buffer_size);
210  count = decrypt.gcount();
211  }
212 
213  return (!decrypt.fail() || decrypt.eof()) && (!dest.fail());
214 }
215 
216 #endif // HAVE_OPENSSL
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
bool is_binary_or_text() const
Returns true either is_binary() or is_text() is true; that is, that the filename has been specified a...
Definition: filename.I:445
A hierarchy of directories and files that appears to be one continuous file system,...
static void close_write_file(std::ostream *stream)
Closes a file opened by a previous call to open_write_file().
std::ostream * open_write_file(const Filename &filename, bool auto_wrap, bool truncate)
Convenience function; returns a newly allocated ostream if the file exists and can be written,...
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
std::istream * open_read_file(const Filename &filename, bool auto_unwrap) const
Convenience function; returns a newly allocated istream if the file exists and can be read,...
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
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.