Source: kmdcodec.h


Annotated List
Files
Globals
Hierarchy
Index
/*
   Copyright (C) 2000-2001 Dawit Alemayehu 
   Copyright (C) 2001 Rik Hemsley (rikkus) 

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License (LGPL) as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   This KMD5 class is based on a C++ implementation of
   "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by
   Mordechai T. Abzug,	Copyright (c) 1995.  This implementation
   passes the test-suite as defined by RFC 1321.

   RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992.
   RSA Data Security, Inc. Created 1991. All rights reserved.

   The encoding and decoding utilities in KCodecs with the exception of
   quoted-printable were ported from the HTTPClient java package by Ronald
   Tschalär Copyright (C) 1996-1999. The quoted-printable codec as described
   in RFC 2045, section 6.7. is by Rik Hemsley (C) 2001.
*/

#ifndef _KMDBASE_H
#define _KMDBASE_H

#define KBase64 KCodecs

#include 
#include 
#include 

typedef char HASH[16];
typedef char HASHHEX[33];

/**
 * A wrapper class for the most commonly used encoding and
 * decoding algorithms.  Currently there is support for encoding
 * and decoding input using base64, uu and the quoted-printable
 * specifications.
 *
 * @sect Useage:
 *
 * The convienence functions are well suited for encoding
 * and decoding a relatively small input.
 *
 * 
 * QCString input = "Aladdin:open sesame";
 * QCString result = KCodecs::base64Encode(input);
 * printf ("Result: %c", result.data());
 *
 * Output should be
 * Result: QWxhZGRpbjpvcGVuIHNlc2FtZQ==
 * 
* * @short A collection of commonly used encoding and decoding algorithms. * @author Dawit Alemayehu * @author Rik Hemsley */ class KCodecs { public: /** * Encodes the given data using the quoted-printable algorithm. * Equivalent to quotedPrintableEncode(in, true). * * @param in data to be encoded. * @return quoted-printable encoded data. */ static QCString quotedPrintableEncode(const QByteArray & in); /** * Encodes the given data using the quoted-printable algorithm. * * @param in data to be encoded. * @param useCRLF if true the input data is expected to have * CRLF line breaks and the output will have CRLF line breaks, too. * @return quoted-printable encoded data. */ static QCString quotedPrintableEncode(const QByteArray & in, bool useCRLF); /** * Decodes a quoted-printable encoded string. * Accepts data with CRLF or standard unix line breaks * * @param in the data to be decoded. * @return decoded data. */ static QByteArray quotedPrintableDecode(const QCString & in); /** * Encodes the given data using the uuencode algorithm. * * The output is split into lines starting with the number of * encoded octets in the line and ending with a newline. No * line is longer than 45 octets (60 characters), excluding the * line terminator. * * @param in the data to be uuencoded * @return a uuencoded data. */ static QCString uuencode( const QByteArray& in ); /** * Encodes the given data using the uuencode algorithm. * * Use this function if you want the result of the encoding * to be placed in another array and cut down the number of * copy opertation that have to be performed in the process. * * NOTE: the output array is always first reset for * sanity and then resized appropriatly. Hence, any data * that is present in the output array will be lost. * * @param in the data to be uuencoded. * @param out the container for the uudecoded data. */ static void uuencode( const QByteArray& in, QByteArray& out ); /** * Encodes the given string using the uuencode algorithm. * * @param str the string to be uuencoded. * @return a uuencoded string. */ static QCString uuencode( const QCString& str ); /** * Decodes the given data using the uuencode algorithm. * * Any 'begin' and 'end' lines liks those generated by * *nix utilities will automatically be ignored. * * @param in the data uuencoded data to be decoded. * @return the decoded data. */ static QCString uudecode( const QByteArray& in ); /** * Decodes the given data using the uudecode algorithm. * * Use this function if you want the result of the decoding * to be placed in another array and cut down the number of * copy opertation that have to be performed in the process. * * Any 'begin' and 'end' lines liks those generated by * *nix utilities will automatically be ignored. * * IMPORTANT: the output array is first reset and then * resized appropriately. Hence, any data that is present in * the output array will be lost. * * @param in the uuencoded-data to be decoded. * @param out the container for the uudecoded data. */ static void uudecode( const QByteArray& in, QByteArray& out ); /** * Decodes a uuencoded string. * * @param str the string to be decoded. * @return a uudecoded string. */ static QCString uudecode( const QCString& str ); /** * Encodes the given data using the base64 algorithm. * * The boolean argument determines if the encoded data is * going to be restricted to 76 characters or less per line * as specified by RFC 2045. If @p insertLFs is true, then * there will be 76 characters or less per line. * * @param in the data to be encoded. * @param insertLFs limit the number of characters per line. * @return a base64 encoded data. */ static QCString base64Encode( const QByteArray& in, bool insertLFs ); /** * @deprecated. * * Use @ref base64Encode(const QByteArray&, bool) * with the boolean argument set to false. */ // BC: Merge in KDE 3.x with the above function by // defaulting boolean argument to false. static QCString base64Encode( const QByteArray& in ); /** * Encodes the given data using the base64 algorithm. * * Use this function whenever you are dealing with very * large data or a stream of data. The boolean argument * determines if the encoded data is going to be restricted * to 76 characters or less per line as specified by RFC 2045. * If @p insertLFs is true, then there will be 76 characters or * less per line. * * NOTE: the output array is always first reset for * sanity and then resized appropriatly. Hence, any data * that is present in the output array will be lost. * * @param in the data to be encoded using base64. * @param insertLFs limit the number of characters per line. * @param out the container for the encoded data. */ static void base64Encode( const QByteArray& in, QByteArray& out, bool insertLFs ); /** * @deprecated. * * Use @ref base64Encode(const QByteArray&, QByteArray&, bool) * with the boolean argument set to false. */ // BC: Merge in KDE 3.x with the above function by // defaulting boolean argument to false. static void base64Encode( const QByteArray& in, QByteArray& out ); /** * Encodes the given string using the base64 algorithm. * * The boolean argument determines if the encoded data is * going to be restricted to 76 characters or less per line * as specified by RFC 2045. If @p insertLFs is true, then * there will be 76 characters or less per line. * * @param str the string to be encoded. * @param insertLFs limit the number of characters per line. * @return the decoded string. */ static QCString base64Encode( const QCString& str, bool insertLFs ); /** * @deprecated. * * Use @ref base64Encode(const QCString&, bool) * with the boolean argument set to false. */ // BC: Merge in KDE 3.x with the above function by // defaulting boolean argument to false. static QCString base64Encode( const QCString& str ); /** * Decodes the given data that was encoded using the * base64 algorithm. * * @param in the base64-encoded data to be decoded. * @return the decoded data. */ static QCString base64Decode( const QByteArray& in ); /** * Decodes the given data that was encoded with the base64 * algorithm. * * Use this function if you want the result of the decoding * to be placed in another array and cut down the number of * copy opertation that have to be performed in the process. * * IMPORTANT: the output array is first reset and then * resized appropriately. Hence, any data that is present in * the output array will be lost. * * @param in the encoded data to be decoded. * @param out the container for the decoded data. */ static void base64Decode( const QByteArray& in, QByteArray& out ); /** * Decodes a string encoded with the base64 algorithm. * * @param str the base64-encoded string. * @return the decoded string. */ static QCString base64Decode( const QCString& str ); /** * Encodes the QString data using the base64 algorithm. * * NOTE: This function is ONLY provided for convenience * and backward compatability! Using it can result in an incorrectly * encoded data since the conversion of the QString input to latin-1 * can and will result in data loss if the input data contains non- * latin1 characters. As such it is highly recommended that you avoid * this function unless you are absolutely certain that your input * does not contain any non-latin1 character!! */ static QString base64Encode( const QString& str ); /** * Decodes the encoded QString data using the base64 algorithm. * * NOTE: This function is ONLY provided for convenience * and backward compatability! Using it can result in an incorrectly * decoded data since the conversion of the QString input to latin-1 * can and will result in data loss if the input data contains non- * latin1 characters. As such it is highly recommended that you avoid * this function unless you are absolutely certain that your input * does not contain any non-latin1 character!! */ static QString base64Decode( const QString& str ); /** * Encodes the QString data using the uuencode algorithm. * * NOTE: This function is ONLY provided for convenience * and backward compatability! Using it can result in an incorrectly * encoded data since the conversion of the QString input to latin-1 * can and will result in data loss if the input data contains non- * latin1 characters. As such it is highly recommended that you avoid * this function unless you are absolutely certain that your input * does not contain any non-latin1 character!! */ static QString uuencode( const QString& str ); /** * Decodes the QString data using the uuencode algorithm. * * NOTE: This function is ONLY provided for convenience * and backward compatability! Using it can result in an incorrectly * decoded data since the conversion of the QString input to latin-1 * can and will result in data loss if the input data contains non- * latin1 characters. As such it is highly recommended that you avoid * this function unless you are absolutely certain that your input * does not contain any non-latin1 character!! */ static QString uudecode( const QString& str ); /** * @deprecated. Use @ref base64Encode(const QString&) instead. */ static QString encodeString( const QString& data ); /** * @deprecated. Use @ref base64Decode(const QString&) instead. */ static QString decodeString( const QString& data ); private: KCodecs(); private: static char UUEncMap[64]; static char UUDecMap[128]; static char Base64EncMap[64]; static char Base64DecMap[128]; static char hexChars[16]; static const unsigned int maxQPLineLength; }; /** * Provides an easy to use C++ implementation of RSA's * MD5 algorithm. * * The default constructor is designed to provide much the same * functionality as the most commonly used C-implementation while * the other three constructors are meant to further simplify the * message digest calculations by calculating the result in one * single step. Additionally, you have the ability to obtain the * result in either raw (16-bytes) or hexidecimal formats (33-bytes) * using @ref rawDigest and @ref hexDigest respectivelly, you can also * reuse a single instance to make multiple message digest calculations * by simply invoking @reset(). * * @sect Useage: * * A common useage of this class: * *
 *  HASH rawResult;
 *  HASHHEX hexResult;
 *  QCString test1 = "This is a simple test.";
 *
 *  KMD5 context( test1 );
 *  context.rawDigest( rawResult );
 *  context.hexDigest( hexResult );
 *  printf ( "Raw Digest output: %s", rawResult );
 *  printf ( "Hex Digest output: %s", hexResult );
 * 
* * To cut down on the unnecessary overhead of creating multiple KMD5 objects, * you can simply invoke @ref reset() to resue the same object in making another * calculation: * *
 *  context.reset();
 *  context.update( QCString("TWO") );
 *  context.update( QCString("THREE") );
 *  printf ( "Raw Digest output: %s", static_cast(context.rawDigest()) );
 *  printf ( "Hex Digest output: %s", context.hexDigest() );
 * 
* * NOTE: Invoke @ref reset() deletes the previously calculated message * digest value. Thus, be sure to copy the previous result before you * reuse the same object! Also, if you use one of the convienence * constructors you must first invoke reset(), before calling any of the * update functions. Otherwise, the call to @ref update will fail. * * Here is an of KMD5 useage much along the same lines of how one would * use the commonly available C-implementations of the MD5 algorithm: * *
 *  KMD5 context;
 *  context.update(QCString("ONE"));
 *  context.update(QCString("TWO"));
 *  context.update(QCString("THREE"));
 *  context.finalize();
 *  printf ( "Raw Digest output: %s", static_cast(context.rawDigest()) );
 *  printf ( "Hex Digest output: %s", context.hexDigest() );
 * 
* * @short An adapted C++ implementation of RSA Data Securities MD5 algorithm. * @author Dawit Alemayehu */ class KMD5 { public: /** * HEX hexidecimal representation of the message digest * BIN binary representation of the message digest */ enum DigestType { BIN, HEX }; /** * ERR_NONE no error occured. [default] * ERR_ALREADY_FINALIZED @ref finalize() has already been invoked. * ERR_NOT_YET_FINALIZED @ref hexDigest() or @ref rawDigest() invoked before @ref finalize(). * ERR_CANNOT_READ_FILE indicates a problem while trying to read the given file. * ERR_CANNOT_CLOSE_FILE indicates a problem while trying to close the given file. */ enum ErrorType { ERR_NONE, ERR_ALREADY_FINALIZED, ERR_NOT_YET_FINALIZED, ERR_CANNOT_READ_FILE, ERR_CANNOT_CLOSE_FILE }; /** * Default constructor that only performs initialization. * Unlike the other constructors */ KMD5(); /** * Constructor that initializes, computes, and finalizes * the message digest for the given string. * * NOTE: This is a convience constructor. It is provided to * allow compatiability with the C implementation of this digest. */ KMD5(Q_UINT8 * in); /** * Constructor that initializes, computes, and finalizes * the message digest for the given file. * * NOTE: This is a convience constructor. As such it does * not allow the update of the message after it has been * invoked. If you need to update the message after creating * the constructor, */ KMD5(FILE *file); /** * Same as above except it accepts a QByteArray as its argument. */ KMD5(const QByteArray& a ); /** * Same as above except it accepts a QCString as its argument. */ KMD5(const QCString& in); /** * @deprcated. Use @ref KMD5(const QCString& in) instead! * * IMPORTANT: This constructor has been depricated and * will be removed in future release. This is done to avoid * loss of data from misuse of the function since it first * converts the given data into Latin-1. Additionally, this * conversion is very slow! */ KMD5(const QString& in); /** * Updates the message to be digested. * * @param input message to be added to the digest (QByteArray). */ void update (const QByteArray& in ); /** * Same as above except it accepts a pointer to FILE. * * NOTE that the file must have been already opened. If you * want the file to be automatically closed, set @p closeFile * to TRUE. * * @param file a pointer to FILE as returned by calls like f{d,re}open * @param closeFile if true closes the file using fclose. */ void update (FILE *file, bool closeFile = false ); /** * Updates the message to be digested. * * @param input message to be added to digest (unsigned char*) * @param len the length of the given message. */ void update (Q_UINT8 * in, int len = -1 ); /** * Same as above except it accepts a QCString as its argument. */ void update ( const QCString& in ); /** * Same as above except it accepts a QString as its argument. * * IMPORTANT: This function is ONLY provided for convenience * and backward compatability! Using it can result in an incorrect * digest caclculation since the conversion of the QString input to * latin-1 can and will result in data loss if the input data contains * non-latin1 characters. As such it is highly recommended that you * avoid this function unless you are absolutely certain that your * input does not contain any non-latin1 character!! */ void update ( const QString& in ); /** * Finalizes the message digest calculation. * * If you used the default constructor, you must invoke this function * before you can obtain the calculated digest value. */ void finalize(); /** * Compares the message digest supplied messaged digest @p msg_digest * with the one calculated for the input QCString @p input. * * NOTE: Calling this function will reset any previously calcualted * digests. If you want to verify your token with the current digest * value, use @ref verify( const char*, DigestType ) instead. * * @param input the message to be added to the digest value * @param msg_digest the digest to compare the result against * @param type the format of the result for comparison (binary or hexidecimal). * * @return true if the digests match, otherwise false. */ bool verify( const QCString& in, const char * msg_digest, DigestType type = HEX ); /** * Same as above except it takes a QString argument as its input. * * IMPORTANT: This function is ONLY provided for convenience * and backward compatability! Using it can result in an incorrect * verification since the conversion of the QString input to latin-1 * can and will result in data loss if the input data contains non- * latin1 characters. As such it is highly recommended that you * avoid this function unless you are absolutely certain that your * input does not contain any non-latin1 character!! */ bool verify( const QString& in, const char * msg_digest, DigestType type = HEX ); /** * Same as above except it takes a pointer to a FILE as its input. * * NOTE: Calling this function will reset any previously * calcualted digests. If you want to verify your token with the * current digest value, use @ref verify(const char*, DigestType) * instead. */ bool verify( FILE* f, const char * msg_digest, DigestType type = HEX ); /** * Compares the given string with with the current message digest. * * Unlike the other verification functions this one does not reset * the calculated message digest if one is already present. Rather * it simply compares the given digest value against the calculated * one. * * NOTE: This function will return false if there was an error * calculating the message digest as well as when the verification * fails. You can use @ref hasErrored() to determine which is the case. * * @param msg_digest the digest to compare the result against * @param type the format of the result for comparison (binary * or hexidecimal). * * @return true if the digests match, otherwise false. */ bool verify( const char* msg_digest, DigestType type = HEX ); /** * Re-initializes internal paramters. * * Note that calling this function will reset all internal variables * and hence any calculated message digest. Invoke this function only * when you reuse the same object to perform another message digest * calculation. */ void reset(); /** * Returns the raw 16-byte binary value of the message * digest. * * NOTE: you are responsible for making a copy of this * string. * * @return the raw represenation of the digest or NULL * if there was error calculating the digest. */ Q_UINT8* rawDigest (); /** * Fills the given array with the binary representation of the * message digest. * * Use this method if you do not want to worry about making * copy of the digest once you obtain it. * * @param bin an array of 16 characters ( char[16] ) */ void rawDigest( HASH bin ); /** * Returns the value of the calculated message digest in * a hexcidecimal representation. * * The 32-byte hexidecimal value is terminated by a NULL * character to form a properly terminated string. Also * note that that if * * NOTE: You are responsible for making a copy of * this string! * * @return the hex represenation of the digest or NULL if * there was error calculating the digest. */ char * hexDigest (); /** * Fills the given array with the hexcidecimal representation of * the message digest. * * Use this method if you do not want to worry about making * copy of the digest once you obtain it. Also note that this * method appends a NULL charater to the end of the array to * form a properly terminated string. This is the reason why * the hexDigest is 33 characters long. * * @param bin an array of 33 characters ( char[33] ) */ void hexDigest( HASHHEX hex ); /** * Indicates whether the message digest calculation failed or * succeeded. Use @ref error() to determine the error type. * * @return false if errors are present, otherwise true */ bool hasErrored() const { return (m_error != ERR_NONE); } /** * Returns the type of error that occurred. * * @return the error type. See @ref ErrorType for details. */ int error() const { return m_error; } protected: /** * Initializer called by all constructors */ void init(); /** * Performs the real update work. Note * that length is implied to be 64. */ void transform( Q_UINT8 * buffer ); /** * Returns true if the current message digest matches @p msg_digest. */ bool isDigestMatch( const char * msg_digest, DigestType type ); private: void encode( Q_UINT8 *output, Q_UINT32 *in, Q_UINT32 len ); void decode( Q_UINT32 *output, Q_UINT8 *in, Q_UINT32 len ); Q_UINT32 rotate_left( Q_UINT32 x, Q_UINT32 n ); Q_UINT32 F( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); Q_UINT32 G( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); Q_UINT32 H( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); Q_UINT32 I( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); void FF( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ); void GG( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ); void HH( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ); void II( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ); private: Q_UINT32 m_state[4]; Q_UINT32 m_count[2]; Q_UINT8 m_buffer[64]; Q_UINT8 m_digest[16]; ErrorType m_error; bool m_finalized; struct KMD5Private; KMD5Private* d; }; #endif

Generated by: dfaure on kde.faure.org on Thu Jan 17 22:15:01 2002, using kdoc 2.0a53.