Panda3D

encrypt_string.cxx

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
 All Classes Functions Variables Enumerations