Panda3D
|
00001 // Filename: encrypt_string.cxx 00002 // Created by: drose (30Jan07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "encrypt_string.h" 00016 00017 #ifdef HAVE_OPENSSL 00018 #include "encryptStream.h" 00019 #include "virtualFileSystem.h" 00020 #include "config_express.h" 00021 00022 //////////////////////////////////////////////////////////////////// 00023 // Function: encrypt_string 00024 // Access: Published 00025 // Description: Encrypts the indicated source string using the given 00026 // password, and the algorithm specified by 00027 // encryption-algorithm. Returns the encrypted string. 00028 //////////////////////////////////////////////////////////////////// 00029 string 00030 encrypt_string(const string &source, const string &password, 00031 const string &algorithm, int key_length, int iteration_count) { 00032 ostringstream dest; 00033 00034 { 00035 OEncryptStream encrypt; 00036 if (!algorithm.empty()) { 00037 encrypt.set_algorithm(algorithm); 00038 } 00039 if (key_length > 0) { 00040 encrypt.set_key_length(key_length); 00041 } 00042 if (iteration_count >= 0) { 00043 encrypt.set_iteration_count(iteration_count); 00044 } 00045 encrypt.open(&dest, false, password); 00046 encrypt.write(source.data(), source.length()); 00047 00048 if (encrypt.fail()) { 00049 return string(); 00050 } 00051 } 00052 00053 return dest.str(); 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: decrypt_string 00058 // Access: Published 00059 // Description: Decrypts the previously-encrypted string using the 00060 // given password (which must be the same password 00061 // passed to encrypt()). The return value is the 00062 // decrypted string. 00063 // 00064 // Note that a decryption error, including an incorrect 00065 // password, cannot easily be detected, and the return 00066 // value may simply be a garbage string. 00067 //////////////////////////////////////////////////////////////////// 00068 string 00069 decrypt_string(const string &source, const string &password) { 00070 istringstream source_stream(source); 00071 ostringstream dest_stream; 00072 00073 if (!decrypt_stream(source_stream, dest_stream, password)) { 00074 return string(); 00075 } 00076 00077 return dest_stream.str(); 00078 } 00079 00080 //////////////////////////////////////////////////////////////////// 00081 // Function: encrypt_file 00082 // Access: Published 00083 // Description: Encrypts the data from the source file using the 00084 // given password. The source file is read in its 00085 // entirety, and the encrypted results are written to 00086 // the dest file, overwriting its contents. The return 00087 // value is bool on success, or false on failure. 00088 //////////////////////////////////////////////////////////////////// 00089 EXPCL_PANDAEXPRESS bool 00090 encrypt_file(const Filename &source, const Filename &dest, const string &password, 00091 const string &algorithm, int key_length, int iteration_count) { 00092 Filename source_filename = source; 00093 if (!source_filename.is_binary() && !source_filename.is_text()) { 00094 // The default is binary, if not specified otherwise. 00095 source_filename.set_binary(); 00096 } 00097 00098 Filename dest_filename = Filename::binary_filename(dest); 00099 pofstream dest_stream; 00100 if (!dest_filename.open_write(dest_stream)) { 00101 express_cat.info() << "Couldn't open file " << dest_filename << "\n"; 00102 return false; 00103 } 00104 00105 // Try to open the file from disk first, instead of using the vfs, 00106 // so we can get the newline conversion with a text file. This is a 00107 // little weird if you have a vfs file shadowing a disk file, but 00108 // whatever. 00109 if (source_filename.is_text()) { 00110 pifstream source_stream; 00111 if (source_filename.open_read(source_stream)) { 00112 bool result = encrypt_stream(source_stream, dest_stream, password, 00113 algorithm, key_length, iteration_count); 00114 return result; 00115 } 00116 } 00117 00118 // OK, couldn't read the disk file, or it wasn't set in text mode. 00119 // Read the file from the vfs, and sorry--no text conversion for 00120 // you. 00121 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00122 istream *source_stream = vfs->open_read_file(source_filename, true); 00123 if (source_stream == NULL) { 00124 express_cat.info() << "Couldn't open file " << source_filename << "\n"; 00125 return false; 00126 } 00127 00128 bool result = encrypt_stream(*source_stream, dest_stream, password, 00129 algorithm, key_length, iteration_count); 00130 vfs->close_read_file(source_stream); 00131 return result; 00132 } 00133 00134 //////////////////////////////////////////////////////////////////// 00135 // Function: decrypt_file 00136 // Access: Published 00137 // Description: Decrypts the data from the source file using the 00138 // given password (which must match the same password 00139 // passed to encrypt()). The source file is read in its 00140 // entirety, and the decrypted results are written to 00141 // the dest file, overwriting its contents. The return 00142 // value is bool on success, or false on failure. 00143 // 00144 // Note that a decryption error, including an incorrect 00145 // password, cannot easily be detected, and the output 00146 // may simply be a garbage string. 00147 //////////////////////////////////////////////////////////////////// 00148 EXPCL_PANDAEXPRESS bool 00149 decrypt_file(const Filename &source, const Filename &dest, const string &password) { 00150 Filename source_filename = Filename::binary_filename(source); 00151 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00152 istream *source_stream = vfs->open_read_file(source_filename, true); 00153 if (source_stream == NULL) { 00154 express_cat.info() << "Couldn't open file " << source_filename << "\n"; 00155 return false; 00156 } 00157 00158 Filename dest_filename = Filename::binary_filename(dest); 00159 pofstream dest_stream; 00160 if (!dest_filename.open_write(dest_stream)) { 00161 express_cat.info() << "Couldn't open file " << dest_filename << "\n"; 00162 vfs->close_read_file(source_stream); 00163 return false; 00164 } 00165 00166 bool result = decrypt_stream(*source_stream, dest_stream, password); 00167 vfs->close_read_file(source_stream); 00168 return result; 00169 } 00170 00171 //////////////////////////////////////////////////////////////////// 00172 // Function: encrypt_stream 00173 // Access: Published 00174 // Description: Encrypts the data from the source stream using the 00175 // given password. The source stream is read from its 00176 // current position to the end-of-file, and the 00177 // encrypted results are written to the dest stream. 00178 // The return value is bool on success, or false on 00179 // failure. 00180 //////////////////////////////////////////////////////////////////// 00181 bool 00182 encrypt_stream(istream &source, ostream &dest, const string &password, 00183 const string &algorithm, int key_length, int iteration_count) { 00184 OEncryptStream encrypt; 00185 if (!algorithm.empty()) { 00186 encrypt.set_algorithm(algorithm); 00187 } 00188 if (key_length > 0) { 00189 encrypt.set_key_length(key_length); 00190 } 00191 if (iteration_count >= 0) { 00192 encrypt.set_iteration_count(iteration_count); 00193 } 00194 encrypt.open(&dest, false, password); 00195 00196 static const size_t buffer_size = 4096; 00197 char buffer[buffer_size]; 00198 00199 source.read(buffer, buffer_size); 00200 size_t count = source.gcount(); 00201 while (count != 0) { 00202 encrypt.write(buffer, count); 00203 source.read(buffer, buffer_size); 00204 count = source.gcount(); 00205 } 00206 encrypt.close(); 00207 00208 return (!source.fail() || source.eof()) && (!encrypt.fail()); 00209 } 00210 00211 //////////////////////////////////////////////////////////////////// 00212 // Function: decrypt_stream 00213 // Access: Published 00214 // Description: Decrypts the data from the previously-encrypted 00215 // source stream using the given password (which must be 00216 // the same password passed to encrypt()). The source 00217 // stream is read from its current position to the 00218 // end-of-file, and the decrypted results are written to 00219 // the dest stream. The return value is bool on 00220 // success, or false on failure. 00221 // 00222 // Note that a decryption error, including an incorrect 00223 // password, cannot easily be detected, and the output 00224 // may simply be a garbage string. 00225 //////////////////////////////////////////////////////////////////// 00226 bool 00227 decrypt_stream(istream &source, ostream &dest, const string &password) { 00228 IDecryptStream decrypt(&source, false, password); 00229 00230 static const size_t buffer_size = 4096; 00231 char buffer[buffer_size]; 00232 00233 decrypt.read(buffer, buffer_size); 00234 size_t count = decrypt.gcount(); 00235 while (count != 0) { 00236 dest.write(buffer, count); 00237 decrypt.read(buffer, buffer_size); 00238 count = decrypt.gcount(); 00239 } 00240 00241 return (!decrypt.fail() || decrypt.eof()) && (!dest.fail()); 00242 } 00243 00244 #endif // HAVE_OPENSSL