- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List

# RandomGenerator.h

    00001 /*
    00002  *  Phusion Passenger - http://www.modrails.com/
    00003  *  Copyright (c) 2010 Phusion
    00004  *
    00005  *  "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
    00006  *
    00007  *  Permission is hereby granted, free of charge, to any person obtaining a copy
    00008  *  of this software and associated documentation files (the "Software"), to deal
    00009  *  in the Software without restriction, including without limitation the rights
    00010  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    00011  *  copies of the Software, and to permit persons to whom the Software is
    00012  *  furnished to do so, subject to the following conditions:
    00013  *
    00014  *  The above copyright notice and this permission notice shall be included in
    00015  *  all copies or substantial portions of the Software.
    00016  *
    00017  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00018  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00019  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    00020  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00021  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    00022  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    00023  *  THE SOFTWARE.
    00024  */
    00025 #ifndef _PASSENGER_RANDOM_GENERATOR_H_
    00026 #define _PASSENGER_RANDOM_GENERATOR_H_
    00027
    00028 #include <string>
    00029
    00030 #include <boost/noncopyable.hpp>
    00031 #include <boost/shared_ptr.hpp>
    00032 #include <oxt/system_calls.hpp>
    00033
    00034 #include "StaticString.h"
    00035 #include "Exceptions.h"
    00036 #include "Utils/StrIntUtils.h"
    00037
    00038
    00039 /**
    00040  * A random
    00041  */
    00042 namespace Passenger {
    00043
    00044 using namespace std;
    00045 using namespace boost;
    00046 using namespace oxt;
    00047
    00048 /**
    00049  * A random data generator. Data is generated using /dev/urandom, and
    00050  * is cryptographically secure. Unlike rand() and friends,
    00051  * RandomGenerator does not require seeding.
    00052  *
    00053  * The reason why RandomGenerator isn't a singleton is because opening
    00054  * /dev/urandom is *very* slow on Mac OS X and OpenBSD. Each object of
    00055  * this class caches the /dev/urandom file handle.
    00056  *
    00057  * This class is thread-safe as long as there are no concurrent
    00058  * calls to reopen() or close().
    00059  */
    00060 class RandomGenerator: public boost::noncopyable {
    00061 private:
    00062         FILE *handle;
    00063
    00064 public:
    00065         RandomGenerator(bool open = true) {
    00066                 handle = NULL;
    00067                 if (open) {
    00068                         reopen();
    00069                 }
    00070         }
    00071
    00072         ~RandomGenerator() {
    00073                 this_thread::disable_syscall_interruption dsi;
    00074                 close();
    00075         }
    00076
    00077         void reopen() {
    00078                 close();
    00079                 handle = syscalls::fopen("/dev/urandom", "r");
    00080                 if (handle == NULL) {
    00081                         throw FileSystemException("Cannot open /dev/urandom",
    00082                                 errno, "/dev/urandom");
    00083                 }
    00084         }
    00085
    00086         void close() {
    00087                 if (handle != NULL) {
    00088                         syscalls::fclose(handle);
    00089                         handle = NULL;
    00090                 }
    00091         }
    00092
    00093         StaticString generateBytes(void *buf, unsigned int size) {
    00094                 size_t ret = syscalls::fread(buf, 1, size, handle);
    00095                 if (ret != size) {
    00096                         throw IOException("Cannot read sufficient data from /dev/urandom");
    00097                 }
    00098                 return StaticString((const char *) buf, size);
    00099         }
    00100
    00101         string generateByteString(unsigned int size) {
    00102                 char buf[size];
    00103                 generateBytes(buf, size);
    00104                 return string(buf, size);
    00105         }
    00106
    00107         string generateHexString(unsigned int size) {
    00108                 char buf[size];
    00109                 generateBytes(buf, size);
    00110                 return toHex(StaticString(buf, size));
    00111         }
    00112
    00113         /**
    00114          * Generates a random string of <em>size</em> bytes which is also
    00115          * valid ASCII. The result consists only of the characters A-Z,
    00116          * a-z and 0-9, and therefore the total number of possibilities
    00117          * given a size of N is 62**N. However not every character has an
    00118          * equal chance of being chosen: a-i have 5/256 chance of being
    00119          * chosen, while other characters have 4/256 chance of being chosen.
    00120          * Therefore, to match the entropy of a random binary string of
    00121          * size N, one should choose a <em>size</em> which yields slightly
    00122          * more possibilities than 2**N.
    00123          */
    00124         string generateAsciiString(unsigned int size) {
    00125                 char buf[size];
    00126                 generateAsciiString(buf, size);
    00127                 return string(buf, size);
    00128         }
    00129
    00130         void generateAsciiString(char *_buf, unsigned int size) {
    00131                 static const char chars[] = {
    00132                         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    00133                         'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    00134                         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    00135                         'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    00136                         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
    00137                 };
    00138                 unsigned char *buf = (unsigned char *) _buf;
    00139                 generateBytes(buf, size);
    00140                 for (unsigned int i = 0; i < size; i++) {
    00141                         buf[i] = chars[buf[i] % sizeof(chars)];
    00142                 }
    00143         }
    00144
    00145         int generateInt() {
    00146                 int ret;
    00147                 generateBytes(&ret, sizeof(ret));
    00148                 return ret;
    00149         }
    00150
    00151         unsigned int generateUint() {
    00152                 return (unsigned int) generateInt();
    00153         }
    00154 };
    00155
    00156 typedef shared_ptr<RandomGenerator> RandomGeneratorPtr;
    00157
    00158 } // namespace Passenger
    00159
    00160 #endif /* _PASSENGER_RANDOM_GENERATOR_H_ */