• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdenetwork
  • Sitemap
  • Contact Us
 

kopete/protocols/messenger/libpapillon

challengetask.cpp

Go to the documentation of this file.
00001 /*
00002    challengetask.cpp - Answer to challenge string given by Notification Server.
00003 
00004    Copyright (c) 2006 by Michaƫl Larouche <larouche@kde.org>
00005 
00006    Portions used from Kopete with Gregg's approval on LGPL license:
00007    Copyright (c) 2005 by Gregg Edghill       <gregg.edghill@gmail.com>
00008 
00009    *************************************************************************
00010    *                                                                       *
00011    * This library is free software; you can redistribute it and/or         *
00012    * modify it under the terms of the GNU Lesser General Public            *
00013    * License as published by the Free Software Foundation; either          *
00014    * version 2 of the License, or (at your option) any later version.      *
00015    *                                                                       *
00016    *************************************************************************
00017 */
00018 #include "Papillon/Tasks/ChallengeTask"
00019 
00020 // Qt includes
00021 #include <QtCore/QByteArray>
00022 #include <QtCore/QCryptographicHash>
00023 #include <QtCore/QDataStream>
00024 #include <QtCore/QLatin1String>
00025 #include <QtCore/QStringList>
00026 #include <QtCore/QVector>
00027 #include <QtDebug>
00028 
00029 // Papillon includes
00030 #include "Papillon/NetworkMessage"
00031 #include "Papillon/Connection"
00032 
00033 namespace Papillon
00034 {
00035 
00036 const QString challengeProductKey = QString("O4BG@C7BWLYQX?5G");
00037 const QString challengeProductId = QString("PROD01065C%ZFN6F");
00038 
00039 class ChallengeTask::Private
00040 {
00041 public:
00042     Private()
00043     {}
00044 
00048      qint64 createHashKey(const QVector<qint32>& md5Integers, const QVector<qint32>& challengeIntegers);
00052     QString hexSwap(const QString& in);
00053 };
00054 
00055 ChallengeTask::ChallengeTask(Papillon::Task *parent)
00056  : Papillon::Task(parent), d(new Private)
00057 {}
00058 
00059 ChallengeTask::~ChallengeTask()
00060 {
00061     delete d;
00062 }
00063 
00064 bool ChallengeTask::take(NetworkMessage *networkMessage)
00065 {
00066     if( networkMessage->command() == QLatin1String("CHL") )
00067     {
00068         QString challenge = networkMessage->arguments()[0];
00069         
00070         QString challengeHash = createChallengeHash(challenge);
00071 
00072         NetworkMessage *challengeResult = new NetworkMessage(NetworkMessage::PayloadMessage | NetworkMessage::TransactionMessage);
00073         challengeResult->setCommand( QLatin1String("QRY") );
00074         challengeResult->setTransactionId( QString::number( connection()->transactionId() ) );
00075         challengeResult->setPayloadData( challengeHash.toUtf8() );
00076 
00077         challengeResult->setArguments( challengeProductId );
00078 
00079         send(challengeResult);
00080 
00081         return true;
00082     }
00083 
00084     return false;
00085 }
00086 
00087 
00088 QString ChallengeTask::createChallengeHash(const QString &challengeString)
00089 {
00090     // Step One: THe MD5 Hash.
00091 
00092     // Combine the received challenge string with the product key.
00093     QByteArray challengeByteArray = (challengeString + challengeProductKey).toUtf8();
00094 
00095     // Generate the MD5 digest (as a string of hexadecimal number, not binary data)
00096     QByteArray digest = QCryptographicHash::hash(challengeByteArray, QCryptographicHash::Md5).toHex();
00097     qDebug() << Q_FUNC_INFO << "md5: " << digest;
00098 
00099     QVector<qint32> md5Integers(4);
00100     for(qint32 i=0; i < md5Integers.count(); i++)
00101     {
00102         md5Integers[i] = d->hexSwap(digest.mid(i*8, 8)).toUInt(0, 16) & 0x7FFFFFFF;
00103         qDebug() << Q_FUNC_INFO << ("0x" + d->hexSwap(digest.mid(i*8, 8))) << " " << md5Integers[i];
00104     }
00105 
00106     // Step Two: Create the challenge string key
00107 
00108     QString challengeKey = challengeString + challengeProductId;
00109     // Pad to multiple of 8.
00110     challengeKey = challengeKey.leftJustified(challengeKey.length() + (8 - challengeKey.length() % 8), '0');
00111 
00112     qDebug() << Q_FUNC_INFO << "challenge key: " << challengeKey;
00113 
00114     QVector<qint32> challengeIntegers(challengeKey.length() / 4);
00115     for(qint32 i=0; i < challengeIntegers.count(); i++)
00116     {
00117         QString sNum = challengeKey.mid(i*4, 4), sNumHex;
00118 
00119         // Go through the number string, determining the hex equivalent of each value
00120         // and add that to our new hex string for this number.
00121         for(int j=0; j < sNum.length(); j++) {
00122             sNumHex += QString::number((int)sNum[j].toLatin1(), 16);
00123         }
00124 
00125         // swap because of the byte ordering issue.
00126         sNumHex = d->hexSwap(sNumHex);
00127         // Assign the converted number.
00128         challengeIntegers[i] = sNumHex.toInt(0, 16);
00129         qDebug() << Q_FUNC_INFO << sNum << (": 0x"+sNumHex) << " " << challengeIntegers[i];
00130     }
00131 
00132     // Step Three: Create the 64-bit hash key.
00133 
00134     // Get the hash key using the specified arrays.
00135     qint64 key = d->createHashKey(md5Integers, challengeIntegers);
00136     qDebug() << Q_FUNC_INFO << "key: " << key;
00137 
00138     // Step Four: Create the final hash key.
00139 
00140     QString upper = QString::number(QString(digest.mid(0, 16)).toULongLong(0, 16)^key, 16);
00141     if(upper.length() % 16 != 0)
00142         upper = upper.rightJustified(upper.length() + (16 - upper.length() % 16), '0');
00143 
00144     QString lower = QString::number(QString(digest.mid(16, 16)).toULongLong(0, 16)^key, 16);
00145     if(lower.length() % 16 != 0)
00146         lower = lower.rightJustified(lower.length() + (16 - lower.length() % 16), '0');
00147 
00148     return (upper + lower);
00149 }
00150 
00151 qint64 ChallengeTask::Private::createHashKey(const QVector<qint32>& md5Integers, const QVector<qint32>& challengeIntegers)
00152 {
00153     qDebug() << Q_FUNC_INFO << "Creating 64-bit key.";
00154 
00155     qint64 magicNumber = 0x0E79A9C1L, high = 0L, low = 0L;
00156         
00157     for(int i=0; i < challengeIntegers.count(); i += 2)
00158     {
00159         qint64 temp = ((challengeIntegers[i] * magicNumber) % 0x7FFFFFFF) + high;
00160         temp = ((temp * md5Integers[0]) + md5Integers[1]) % 0x7FFFFFFF;
00161 
00162         high = (challengeIntegers[i + 1] + temp) % 0x7FFFFFFF;
00163         high = ((high * md5Integers[2]) + md5Integers[3]) % 0x7FFFFFFF;
00164 
00165         low += high + temp;
00166     }
00167 
00168     high = (high + md5Integers[1]) % 0x7FFFFFFF;
00169     low  = (low  + md5Integers[3]) % 0x7FFFFFFF;
00170 
00171     QByteArray tempArray;
00172     tempArray.reserve(8);
00173 
00174     QDataStream buffer(&tempArray,QIODevice::ReadWrite);
00175     buffer.setByteOrder(QDataStream::LittleEndian);
00176     buffer << (qint32)high;
00177     buffer << (qint32)low;
00178 
00179     buffer.device()->reset();
00180     buffer.setByteOrder(QDataStream::BigEndian);
00181     qint64 key;
00182     buffer >> key;
00183     
00184     return key;
00185 }
00186 
00187 QString ChallengeTask::Private::hexSwap(const QString& in)
00188 {
00189     QString sHex = in, swapped;
00190     while(sHex.length() > 0)
00191     {
00192         swapped = swapped + sHex.mid(sHex.length() - 2, 2);
00193         sHex = sHex.remove(sHex.length() - 2, 2);
00194     }
00195     return swapped;
00196 }
00197 
00198 }
00199 
00200 #include "challengetask.moc"

kopete/protocols/messenger/libpapillon

Skip menu "kopete/protocols/messenger/libpapillon"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdenetwork

Skip menu "kdenetwork"
  • kget
  • kopete
  •   kopete
  •   libkopete
  •       libpapillon
  • krfb
Generated for kdenetwork by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal