diff options
Diffstat (limited to 'kbiff/kbiffcrypt.cpp')
-rw-r--r-- | kbiff/kbiffcrypt.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/kbiff/kbiffcrypt.cpp b/kbiff/kbiffcrypt.cpp new file mode 100644 index 0000000..66ce0b0 --- /dev/null +++ b/kbiff/kbiffcrypt.cpp @@ -0,0 +1,72 @@ +/* + * kbiffcrypt.cpp + * Copyright (C) 2005 Michael Hendricks <michael@palmcluster.org> + * + * This file contains the implementation of the functions in + * the KBiffCrypt namespace. + * + * $Id$ + */ +#include "kbiffcrypt.h" + +#include <kmdcodec.h> +#include <qcstring.h> + +QString KBiffCrypt::hmac_md5(const QString& text, const QString& k) +{ + // If the original key is too long, the new key will be a hash of + // the original key. Then the new key might have NULL bytes in it, + // so we can't use QCString + QByteArray key = (QByteArray)k.utf8(); + + KMD5 context; // for calculating MD5 sums + KMD5::Digest digest; // intermediate storage for MD5 sums + + // inner and outer padding (key XORd with ipad and opad, respectively) + QByteArray k_ipad(64); + QByteArray k_opad(64); + + + // if key is longer than 64 bytes reset it to key=MD5(key) + if (key.size() > 64) { + // cast to a QCString because we don't want to hash the + // trailing NULL byte + KMD5 tctx((QCString)key); + + key.duplicate((char*)tctx.rawDigest(), 16); + } + + /* the HMAC-MD5 transform looks like this: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * text is the data being protected + */ + + // XOR key with ipad and opad values, copying + // the pad values after the key's end + for (unsigned int i=0; i<64; i++) { + if( i < key.size() ) { + k_ipad[i] = key[i] ^ 0x36; + k_opad[i] = key[i] ^ 0x5c; + } else { + k_ipad[i] = 0x36; + k_opad[i] = 0x5c; + } + } + + // perform inner MD5 + context.reset(); // init context for 1st pass + context.update(k_ipad); // start with inner pad + context.update(text.utf8()); // then text of datagram + context.rawDigest(digest); // finish up 1st pass + + // perform outer MD5 + context.reset(); // init context for 2nd pass + context.update(k_opad); // start with outer pad + context.update(digest, 16); // then results of 1st hash + return context.hexDigest(); // finish up 2nd pass and return +} |