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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A hierarchy of directories and files that appears to be one continuous file system,...
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,...
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
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,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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