wave-crypto.h

Go to the documentation of this file.
00001 /*
00002  * wave-crypto.h
00003  *
00004  * Copyright (C) 2007,2009,2011  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Simple API for cryptography.  These are helper functions layered on top of
00032  * the RSA APIs.
00033  */
00034 
00035 #ifndef WAVEPACKET_CRYPTO_H__
00036 #define WAVEPACKET_CRYPTO_H__
00037 
00038 // includes --------------------------------------------------------------------
00039 #include "common/common.h"
00040 #include "threadsafe/smart_ptr.h"
00041 
00042 
00043 namespace crypto {
00044 
00045 /// \ingroup lib
00046 /*@{*/
00047 
00048 ////////////////////////////////////////////////////////////////////////////////
00049 ///
00050 ///     \defgroup crypto Cryptography Libraries
00051 ///
00052 ///     Provides basic encryption support.
00053 ///
00054 ///     Simple objects to abstract:
00055 ///       - RSA Keys (public/private pair)
00056 ///       - RSA Public Key (just the public key from an RSA pair)
00057 ///       - DES Key (used for fast symmetric encryption)
00058 ///
00059 ///     These are optimized for usability (and correctness) over efficiency! 
00060 ///     If you are
00061 ///     doing hardcore crypto you should use the RSA APIs directly.  For
00062 ///     instance, these APIs aren't clever about memory management, they
00063 ///     allocate and de-allocate as needed.
00064 ///
00065 ///     Encrypted strings have simple encoding applied so they are safe to
00066 ///     pass around as strings (no null characters and should be MIME-friendly).
00067 ///     Decryption routines assume the string is encoded and they will decode
00068 ///     first.  In theory these could be split out but in practice I expect
00069 ///     most people to just treat the encrypted strings opaquely anyway.
00070 ///
00071 ///     These APIs are best for applications that are using crypto tactically
00072 ///     in just a few rarely-used places.
00073 ///
00074 ///     Seed the randomizer before calling any crypto APIs
00075 ///
00076 ///     Because the RSA libraries are confusing (or at least, I wasn't clever
00077 ///     enough to determine if there was a standard way of serializing keys or
00078 ///     not),
00079 ///     I don't think the results
00080 ///     of these can be mixed with other libraries.  That is, you can't take
00081 ///     the encrypted value from this API and decrypt it using another API.  All
00082 ///     encryption/decryption must happen using these APIs (although that can
00083 ///     happen across processes and machines, etc.).
00084 ///
00085 ///     These aren't designed for streaming.  These are designed for
00086 ///     encryption of small blocks of data (a couple of KB or so at most).
00087 ///     These APIs are designed for user-readable null-terminated strings, not
00088 ///     arbitrary binary data.
00089 ///
00090 ///     Typical usage is to create a DESKey for use in encrypting data,
00091 ///     and only use the public/private keys to safely exchange the DES key.
00092 ///
00093 ///     Example:
00094 ///
00095 ///     Generate RSAKey on host 1:
00096 /// \code
00097 ///             smart_ptr<RSAKey> rsa = RSAKey::create();       // expensive!
00098 ///             smart_ptr<RSAPublicKey> pubkey = rsa->getPublicKey();
00099 ///             std::string serialized = pubkey->serialize();
00100 ///
00101 ///             // great, now send serialized version of public key to host 2
00102 ///             send_string_to("host2", serialized);
00103 /// \endcode
00104 ///
00105 ///     Then, on host 2:
00106 /// \code
00107 ///             // receive string from remote host
00108 ///             std::string serialized = get_string_from("host1");
00109 ///
00110 ///             // deserialize into local version of their public key
00111 ///             smart_ptr<RSAPublicKey> pubkey =
00112 ///                 RSAPublicKey::create(serialized.c_str());
00113 ///
00114 ///             // create a new secret symmetric encryption key
00115 ///             smart_ptr<DESKey> secret = DESKey::create();
00116 ///             std::string des_serial = secret->serialize();
00117 ///
00118 ///             // encrypt DES key (secret) with host 1's public key
00119 ///             std::string encrypted = pubkey->encrypt(des_serial.c_str());
00120 ///
00121 ///             // send secret to host 1
00122 ///             send_string_to("host1", encrypted);
00123 /// \endcode
00124 ///
00125 ///     Then, back on host 1:
00126 /// \code
00127 ///             // receive encrypted secret from host 2
00128 ///             std::string encrypted = get_string_from("host2");
00129 ///
00130 ///             // decrypt using our private key
00131 ///             std::string serialized = rsa->decrypt(encrypted.c_str());
00132 ///
00133 ///             // deserialize DES key so we have a local copy
00134 ///             smart_ptr<DESKey> secret = DESKey::create(serialized.c_str());
00135 ///
00136 ///             // now I can communicate with host 2 using shared secret key
00137 ///             std::string password = secret->encrypt("This is my password!");
00138 ///             send_string_to("host2", password);
00139 /// \endcode
00140 ///
00141 ///     Don't get too excited about these, because you are still vulnerable to
00142 ///     attack/cracking during the initial handshake phase (how do you trust
00143 ///     the machine you are handing your public key to?).  But these are
00144 ///     intended to make it harder to crack non-critical data, for instance
00145 ///     game data where you want to make it more expensive but not necessarily
00146 ///     impossible to crack other players' packets.
00147 ///
00148 ///     Put another way, the code above is vulnerable to man-in-the-middle
00149 ///     attacks but is good protection against passive listeners.
00150 ///
00151 ///     Also, someday this library may beef up the handshake process, at which
00152 ///     point the other code could be more generally useful and secure.
00153 ////////////////////////////////////////////////////////////////////////////////
00154 /*@{*/
00155 
00156 
00157 /// public key suitable for encrypting
00158 ///
00159 /// Get these from a private/public RSAKey or by serializing
00160 ///  and deserializing
00161 class RSAPublicKey {
00162 public:
00163         // virtual destructor --------------------------------------------------
00164         virtual ~RSAPublicKey(void) throw();
00165 
00166         // crypto::RSAPublicKey class interface methods ------------------------
00167         /// return a serialized (string) version of the public key
00168         virtual std::string serialize(void) = 0;
00169 
00170         /// return the given text encrypted with the public key
00171         virtual std::string encrypt(IN const char * plaintext) = 0;
00172 
00173         // static factory methods ----------------------------------------------
00174         /// factory to create public key from serialized (string) version
00175         static smart_ptr<RSAPublicKey> create(IN const char * serialized);
00176 };
00177 
00178 
00179 /// private/public key pair.
00180 class RSAKey {
00181 public:
00182         // virtual destructor --------------------------------------------------
00183         virtual ~RSAKey(void) throw();
00184 
00185         // crypto::RSAKey class interface methods ------------------------------
00186         /// return the public key for the public/private pair
00187         virtual smart_ptr<RSAPublicKey> getPublicKey(void) = 0;
00188 
00189         /// decrypt a string encrypted with the public key, using the private key
00190         virtual std::string decrypt(IN const char * encrypted) = 0;
00191 
00192         // static factory methods ----------------------------------------------
00193         /// create new RSA public/private key pair (note: very expensive!)
00194         static smart_ptr<RSAKey> create(void);
00195 };
00196 
00197 
00198 
00199 /// fast symmetric encryption
00200 class DESKey {
00201 public:
00202         // virtual destructor --------------------------------------------------
00203         virtual ~DESKey(void) throw();
00204 
00205         // crypto::DESKey class interface methods -----------------------------
00206         /// return a serialized (string) version of the DES key
00207         virtual std::string serialize(void) = 0;
00208 
00209         /// encrypt the given plaintext string using the DES key
00210         /// (pads if necessary to fill out to minSize)
00211         virtual std::string encrypt(IN const char * plaintext,
00212                                         IN int minSize) = 0;
00213 
00214         /// decrypt the given string using the DES key (returns original plaintext)
00215         virtual std::string decrypt(IN const char * encrypted) = 0;
00216 
00217         // static factory methods ----------------------------------------------
00218         /// create new DES key
00219         static smart_ptr<DESKey> create(void);
00220 
00221         /// factory to create DES key from serialized (string) version
00222         static smart_ptr<DESKey> create(IN const char * serialized);
00223 };
00224 
00225 
00226 /// quick one-way encryption (SHA1 algorithm, see
00227 /// http://en.wikipedia.org/wiki/SHA-1)
00228 std::string getSHA1(IN const char * data);
00229 
00230 
00231 /// given binary data, encode into base64 ascii string
00232 std::string encodeBase64(IN const byte_t * data, IN long bytes,
00233                                 IN bool encodeLength = true);
00234 
00235 
00236 typedef std::vector<byte_t> vec_byte_t;
00237 
00238 /// given base64 ascii string, decode into byte array
00239 void decodeBase64(IN const char * base64,
00240                                 OUT vec_byte_t& data);
00241 
00242 
00243 /*@}*/  // end of documentation group
00244 
00245 
00246 };      // crypto namespace
00247 
00248 
00249 #endif  // WAVEPACKET_CRYPTO_H__
00250