kopete/protocols/messenger/libpapillon
challengetask.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "Papillon/Tasks/ChallengeTask"
00019
00020
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
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
00091
00092
00093 QByteArray challengeByteArray = (challengeString + challengeProductKey).toUtf8();
00094
00095
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
00107
00108 QString challengeKey = challengeString + challengeProductId;
00109
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
00120
00121 for(int j=0; j < sNum.length(); j++) {
00122 sNumHex += QString::number((int)sNum[j].toLatin1(), 16);
00123 }
00124
00125
00126 sNumHex = d->hexSwap(sNumHex);
00127
00128 challengeIntegers[i] = sNumHex.toInt(0, 16);
00129 qDebug() << Q_FUNC_INFO << sNum << (": 0x"+sNumHex) << " " << challengeIntegers[i];
00130 }
00131
00132
00133
00134
00135 qint64 key = d->createHashKey(md5Integers, challengeIntegers);
00136 qDebug() << Q_FUNC_INFO << "key: " << key;
00137
00138
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"