OKlibrary  0.2.1.6
rijndael.hpp
Go to the documentation of this file.
00001 
00010 #ifndef _RIJNDAEL_H_8uuHgt
00011 #define _RIJNDAEL_H_8uuHgt
00012 
00013 //
00014 // File : rijndael.h
00015 // Creation date : Sun Nov 5 2000 03:21:05 CEST
00016 // Author : Szymon Stefanek (stefanek@tin.it)
00017 //
00018 // Another implementation of the Rijndael cipher.
00019 // This is intended to be an easily usable library file.
00020 // This code is public domain.
00021 // Based on the Vincent Rijmen and K.U.Leuven implementation 2.4.
00022 //
00023 // Oliver Kullmann (O.Kullmann@swansea.ac.uk), 1.1.2006: Coding style improvements
00024 
00025 //
00026 // Original Copyright notice:
00027 //
00028 //    rijndael-alg-fst.c   v2.4   April '2000
00029 //    rijndael-alg-fst.h
00030 //    rijndael-api-fst.c
00031 //    rijndael-api-fst.h
00032 //
00033 //    Optimised ANSI C code
00034 //
00035 //    authors: v1.0: Antoon Bosselaers
00036 //             v2.0: Vincent Rijmen, K.U.Leuven
00037 //             v2.3: Paulo Barreto
00038 //             v2.4: Vincent Rijmen, K.U.Leuven
00039 //
00040 //    This code is placed in the public domain.
00041 //
00042 
00043 //
00044 // This implementation works on 128 , 192 , 256 bit keys
00045 // and on 128 bit blocks
00046 //
00047 
00048 //
00049 // Example of usage:
00050 //
00051 //  // Input data
00052 //  unsigned char key[32];                       // The key
00053 //  initializeYour256BitKey();                   // Obviously initialized with sth
00054 //  const unsigned char * plainText = getYourPlainText(); // Your plain text
00055 //  int plainTextLen = strlen(plainText);        // Plain text length
00056 //
00057 //  // Encrypting
00058 //  Rijndael rin;
00059 //  unsigned char output[plainTextLen + 16];
00060 //
00061 //  rin.init(Rijndael::CBC,Rijndael::Encrypt,key,Rijndael::Key32Bytes);
00062 //  // It is a good idea to check the error code
00063 //  int len = rin.padEncrypt(plainText,len,output);
00064 //  if(len >= 0)useYourEncryptedText();
00065 //  else encryptError(len);
00066 //
00067 //  // Decrypting: we can reuse the same object
00068 //  unsigned char output2[len];
00069 //  rin.init(Rijndael::CBC,Rijndael::Decrypt,key,Rijndael::Key32Bytes));
00070 //  len = rin.padDecrypt(output,len,output2);
00071 //  if(len >= 0)useYourDecryptedText();
00072 //  else decryptError(len);
00073 //
00074 
00075 #include <stdint.h>
00076 
00077 namespace OKlib {
00078   namespace Rijndael {
00079 
00080     const int max_key_columns = 256/32;
00081     const int max_rounds = 14;
00082     const int max_iv_size = 16;
00083 
00084     typedef uint8_t UInt8;
00085     typedef uint32_t UInt32;
00086 
00087     // Error codes
00088     const int rijndael_success = 0;
00089     const int rijndael_unsupported_mode = -1;
00090     const int rijndael_unsupported_direction = -2;
00091     const int rijndael_unsupported_key_length = -3;
00092     const int rijndael_bad_key = -4;
00093     const int rijndael_not_initialized = -5;
00094     const int rijndael_bad_direction = -6;
00095     const int rijndael_corrupted_data = -7;
00096 
00097     class Rijndael
00098     { 
00099     public:
00100       enum Direction { Encrypt , Decrypt };
00101       enum Mode { ECB , CBC , CFB1 };
00102       enum KeyLength { Key16Bytes , Key24Bytes , Key32Bytes };
00103       //
00104       // Creates a Rijndael cipher object
00105       // You have to call init() before you can encrypt or decrypt stuff
00106       //
00107       Rijndael();
00108       ~Rijndael();
00109     protected:
00110       // Internal stuff
00111       enum State { Valid , Invalid };
00112 
00113       State     m_state;
00114       Mode      m_mode;
00115       Direction m_direction;
00116       UInt8     m_initVector[max_iv_size];
00117       UInt32    m_uRounds;
00118       UInt8     m_expandedKey[max_rounds+1][4][4];
00119     public:
00121       // API
00123       
00124       // init(): Initializes the crypt session
00125       // Returns rijndael_success or an error code
00126       // mode      : Rijndael::ECB, Rijndael::CBC or Rijndael::CFB1
00127       //             You have to use the same mode for encrypting and decrypting
00128       // dir       : Rijndael::Encrypt or Rijndael::Decrypt
00129       //             A cipher instance works only in one direction
00130       //             (Well , it could be easily modified to work in both
00131       //             directions with a single init() call, but it looks
00132       //             useless to me...anyway , it is a matter of generating
00133       //             two expanded keys)
00134       // key       : array of unsigned octets , it can be 16 , 24 or 32 bytes long
00135       //             this CAN be binary data (it is not expected to be null terminated)
00136       // keyLen    : Rijndael::Key16Bytes , Rijndael::Key24Bytes or Rijndael::Key32Bytes
00137       // initVector: initialization vector, you will usually use 0 here
00138       int init(Mode mode,Direction dir,const UInt8 *key,KeyLength keyLen,UInt8 * initVector = 0);
00139       // Encrypts the input array (can be binary data)
00140       // The input array length must be a multiple of 16 bytes, the remaining part
00141       // is DISCARDED.
00142       // so it actually encrypts inputLen / 128 blocks of input and puts it in outBuffer
00143       // Input len is in BITS!
00144       // outBuffer must be at least inputLen / 8 bytes long.
00145       // Returns the encrypted buffer length in BITS or an error code < 0 in case of error
00146       int blockEncrypt(const UInt8 *input, int inputLen, UInt8 *outBuffer);
00147       // Encrypts the input array (can be binary data)
00148       // The input array can be any length , it is automatically padded on a 16 byte boundary.
00149       // Input len is in BYTES!
00150       // outBuffer must be at least (inputLen + 16) bytes long
00151       // Returns the encrypted buffer length in BYTES or an error code < 0 in case of error
00152       int padEncrypt(const UInt8 *input, int inputOctets, UInt8 *outBuffer);
00153       // Decrypts the input vector
00154       // Input len is in BITS!
00155       // outBuffer must be at least inputLen / 8 bytes long
00156       // Returns the decrypted buffer length in BITS and an error code < 0 in case of error
00157       int blockDecrypt(const UInt8 *input, int inputLen, UInt8 *outBuffer);
00158       // Decrypts the input vector
00159       // Input len is in BYTES!
00160       // outBuffer must be at least inputLen bytes long
00161       // Returns the decrypted buffer length in BYTES and an error code < 0 in case of error
00162       int padDecrypt(const UInt8 *input, int inputOctets, UInt8 *outBuffer);
00163     protected:
00164       void keySched(UInt8 key[max_key_columns][4]);
00165       void keyEncToDec();
00166       void encrypt(const UInt8 a[16], UInt8 b[16]);
00167       void decrypt(const UInt8 a[16], UInt8 b[16]);
00168     };
00169     
00170   }
00171   
00172 }
00173 
00174 #endif