[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: [PATCH] SHA1 in kdelibs/kdecore/kmdcodec
From: Szombathelyi "György" <gyurco () freemail ! hu>
Date: 2004-11-06 23:20:29
Message-ID: 200411070020.29671.gyurco () freemail ! hu
[Download RAW message or body]
Hello!
What about adding an SHA1 implementation to kmdcodec? There are at least four
independent SHA1 code in the various KDE modules, it would be good to have
only one. I took the implementation from Kopete.
The patch also contains the modifications in kwallet to use the new code.
Should I commit?
Bye,
György
____________________________________________________________________
Miert fizetsz az internetert? Korlatlan, ingyenes internet hozzaferes a FreeStarttol.
Probald ki most! http://www.freestart.hu
["sha1.diff" (text/x-diff)]
Index: kdecore/kmdcodec.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdecore/kmdcodec.cpp,v
retrieving revision 1.62
diff -u -p -u -r1.62 kmdcodec.cpp
@@ -1500,3 +1495,273 @@ void KMD4::transform( Q_UINT32 buf[4], Q
buf[2] += c;
buf[3] += d;
}
+
+/****************************************************************************
+ SHA1 - from a public domain implementation by Steve Reid (steve@edmweb.com)
+****************************************************************************/
+
+KSHA1::KSHA1()
+{
+ init();
+}
+
+KSHA1::KSHA1(const char *in, int len)
+{
+ init();
+ update(in, len);
+}
+
+KSHA1::KSHA1(const QByteArray& in)
+{
+ init();
+ update( in );
+}
+
+KSHA1::KSHA1(const QCString& in)
+{
+ init();
+ update( in );
+}
+
+void KSHA1::update(const QByteArray& in)
+{
+ update(in.data(), int(in.size()));
+}
+
+void KSHA1::update(const QCString& in)
+{
+ update(in.data(), int(in.length()));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void KSHA1::update(const unsigned char *in, int len)
+{
+ if (len < 0)
+ len = qstrlen(reinterpret_cast<const char*>(in));
+
+ if (!len)
+ return;
+
+ if (m_finalized) {
+ kdWarning() << "KSHA1::update called after state was finalized!" << endl;
+ return;
+ }
+ Q_UINT32 i, j;
+
+ j = (m_count[0] >> 3) & 63;
+ if((m_count[0] += len << 3) < ((Q_UINT32)len << 3))
+ m_count[1]++;
+
+ m_count[1] += (len >> 29);
+
+ if((j + len) > 63) {
+ memcpy(&m_buffer[j], in, (i = 64-j));
+ transform(m_state, m_buffer);
+ for ( ; i + 63 < (Q_UINT32)len; i += 64) {
+ transform(m_state, &in[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&m_buffer[j], &in[i], len - i);
+
+}
+
+bool KSHA1::update(QIODevice& file)
+{
+ char buffer[1024];
+ int len;
+
+ while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > \
0) + update(buffer, len);
+
+ return file.atEnd();
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void KSHA1::finalize()
+{
+ Q_UINT32 i, j;
+ unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((m_count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); // Endian independent
+ }
+ update((unsigned char *)"\200", 1);
+ while ((m_count[0] & 504) != 448) {
+ update((unsigned char *)"\0", 1);
+ }
+ update(finalcount, 8); // Should cause a transform()
+ for (i = 0; i < 20; i++) {
+ m_digest[i] = (unsigned char) ((m_state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+
+ // Wipe variables
+ i = j = 0;
+ memset(m_buffer, 0, 64);
+ memset(m_state, 0, 20);
+ memset(m_count, 0, 8);
+ memset(&finalcount, 0, 8);
+
+ m_finalized = true;
+}
+
+bool KSHA1::verify( const KSHA1::Digest& digest)
+{
+ finalize();
+ return (0 == memcmp(rawDigest(), digest, sizeof(KSHA1::Digest)));
+}
+
+bool KSHA1::verify( const QCString& hexdigest)
+{
+ finalize();
+ return (0 == strcmp(hexDigest().data(), hexdigest));
+}
+
+const KSHA1::Digest& KSHA1::rawDigest()
+{
+ finalize();
+ return m_digest;
+}
+
+void KSHA1::rawDigest( KSHA1::Digest& bin )
+{
+ finalize();
+ memcpy( bin, m_digest, sizeof(m_digest) );
+}
+
+QCString KSHA1::hexDigest()
+{
+ QCString s(41);
+
+ finalize();
+ sprintf(s.data(), \
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + \
m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], + \
m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], + \
m_digest[12], m_digest[13], m_digest[14], m_digest[15], m_digest[16], + \
m_digest[17], m_digest[18], m_digest[19]); + return s;
+}
+
+void KSHA1::hexDigest(QCString& s)
+{
+ finalize();
+ s.resize(41);
+ sprintf(s.data(), \
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + \
m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], + \
m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], + \
m_digest[12], m_digest[13], m_digest[14], m_digest[15], m_digest[16], + \
m_digest[17], m_digest[18], m_digest[19]); +}
+
+QCString KSHA1::base64Digest()
+{
+ QByteArray ba(sizeof(m_digest));
+
+ finalize();
+ memcpy(ba.data(), m_digest, sizeof(m_digest));
+ return KCodecs::base64Encode(ba);
+}
+
+
+void KSHA1::init()
+{
+ d = 0;
+ reset();
+}
+
+/*
+ * Start SHA1 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void KSHA1::reset()
+{
+ m_finalized = false;
+
+ m_state[0] = 0x67452301;
+ m_state[1] = 0xEFCDAB89;
+ m_state[2] = 0x98BADCFE;
+ m_state[3] = 0x10325476;
+ m_state[4] = 0xC3D2E1F0;
+ m_count[0] = m_count[1] = 0;
+
+ memset ( m_buffer, 0, sizeof(*m_buffer));
+ memset ( m_digest, 0, sizeof(*m_digest));
+}
+
+inline Q_UINT32 KSHA1::rotate_left (Q_UINT32 x, Q_UINT32 n)
+{
+ return (x << n) | (x >> (32-n)) ;
+}
+
+#define blk(i) (block[i&15] = \
rotate_left(block[(i+13)&15]^block[(i+8)&15]^block[(i+2)&15]^block[i&15],1)) +
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+block[i]+0x5A827999+rotate_left(v,5);w=rotate_left(w,30); +#define \
R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rotate_left(v,5);w=rotate_left(w,30);
+#define R2(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0x6ED9EBA1+rotate_left(v,5);w=rotate_left(w,30); +#define \
R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rotate_left(v,5);w=rotate_left(w,30);
+#define R4(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0xCA62C1D6+rotate_left(v,5);w=rotate_left(w,30); +
+/*
+ * The core of the MD4 algorithm
+ */
+void KSHA1::transform( Q_UINT32 state[5], const unsigned char buffer[64] )
+{
+ Q_UINT32 a, b, c, d, e;
+ Q_UINT32 block[16];
+
+ KFromToBigEndian( block, (Q_UINT32*) buffer, 16 );
+ // Copy context->state[] to working vars
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ // 4 rounds of 20 operations each. Loop unrolled.
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ // Add the working vars back into context.state[]
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ // Wipe variables
+ a = b = c = d = e = 0;
+ memset( block, 0, sizeof(block) );
+}
+
+#undef R0
+#undef R1
+#undef R2
+#undef R3
+#undef R4
+#undef blk
Index: kdecore/kmdcodec.h
===================================================================
RCS file: /home/kde/kdelibs/kdecore/kmdcodec.h,v
retrieving revision 1.56
diff -u -p -u -r1.56 kmdcodec.h
--- kdecore/kmdcodec.h 5 Nov 2004 22:10:54 -0000 1.56
+++ kdecore/kmdcodec.h 6 Nov 2004 23:17:31 -0000
@@ -744,5 +742,166 @@ private:
KMD4Private* d;
};
+/**
+ * @short An adapted C++ implementation of the SHA1 Secure Hash algorithm.
+ * @since 3.4
+ *
+ * The class usage is the same as KMD5.
+ */
+class KDECORE_EXPORT KSHA1
+{
+public:
+
+ typedef unsigned char Digest[20];
+
+ KSHA1();
+
+ /**
+ * Constructor that updates the digest for the given string.
+ *
+ * @param in C string or binary data
+ * @param len if negative, calculates the length by using
+ * strlen on the first parameter, otherwise
+ * it trusts the given length (does not stop on NUL byte).
+ */
+ KSHA1(const char* in, int len = -1);
+
+ /**
+ * @overload
+ *
+ * Same as above except it accepts a QByteArray as its argument.
+ */
+ KSHA1(const QByteArray& a );
+
+ /**
+ * @overload
+ *
+ * Same as above except it accepts a QByteArray as its argument.
+ */
+ KSHA1(const QCString& a );
+
+ /**
+ * Updates the message to be digested. Be sure to add all data
+ * before you read the digest. After reading the digest, you
+ * can <b>not</b> add more data!
+ *
+ * @param in message to be added to digest
+ * @param len the length of the given message.
+ */
+ void update(const char* in, int len = -1) { update(reinterpret_cast<const unsigned \
char*>(in), len); } +
+ /**
+ * @overload
+ */
+ void update(const unsigned char* in, int len = -1);
+
+ /**
+ * @overload
+ *
+ * @param in message to be added to the digest (QByteArray).
+ */
+ void update(const QByteArray& in );
+
+ /**
+ * @overload
+ *
+ * @param in message to be added to the digest (QByteArray).
+ */
+ void update(const QCString& in );
+
+ /**
+ * @overload
+ *
+ * reads the data from an I/O device, i.e. from a file (QFile).
+ *
+ * NOTE that the file must be open for reading.
+ *
+ * @param file a pointer to FILE as returned by calls like f{d,re}open
+ *
+ * @returns false if an error occurred during reading.
+ */
+ bool update(QIODevice& file);
+
+ /**
+ * Calling this function will reset the calculated message digest.
+ * Use this method to perform another message digest calculation
+ * without recreating the KMD4 object.
+ */
+ void reset();
+
+ /**
+ * @return the raw representation of the digest
+ */
+ const Digest& 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( KSHA1::Digest& bin );
+
+ /**
+ * Returns the value of the calculated message digest in
+ * a hexadecimal representation.
+ */
+ QCString hexDigest ();
+
+ /**
+ * @overload
+ */
+ void hexDigest(QCString&);
+
+ /**
+ * Returns the value of the calculated message digest in
+ * a base64-encoded representation.
+ */
+ QCString base64Digest ();
+
+ /**
+ * returns true if the calculated digest for the given
+ * message matches the given one.
+ */
+ bool verify( const KSHA1::Digest& digest);
+
+ /**
+ * @overload
+ */
+ bool verify(const QCString&);
+
+protected:
+ /**
+ * Performs the real update work.
+ */
+ void transform(Q_UINT32 state[5], const unsigned char buffer[64]);
+
+ /**
+ * finalizes the digest
+ */
+ void finalize();
+
+private:
+ KSHA1(const KSHA1& u);
+ KSHA1& operator=(const KSHA1& md);
+
+ void init();
+
+ Q_UINT32 rotate_left( Q_UINT32 x, Q_UINT32 n );
+
+private:
+ Q_UINT32 m_state[5];
+ Q_UINT32 m_count[2];
+ unsigned char m_buffer[64];
+
+ Digest m_digest;
+ bool m_finalized;
+
+ class KSHA1Private;
+ KSHA1Private* d;
+};
#endif
Index: kwallet/backend/Makefile.am
===================================================================
RCS file: /home/kde/kdelibs/kwallet/backend/Makefile.am,v
retrieving revision 1.18
diff -u -p -u -r1.18 Makefile.am
--- kwallet/backend/Makefile.am 5 Sep 2003 21:43:05 -0000 1.18
+++ kwallet/backend/Makefile.am 6 Nov 2004 23:17:32 -0000
@@ -8,7 +8,6 @@ libkwalletbackend_la_LIBADD = $(LIB_QT)
libkwalletbackend_la_SOURCES = blockcipher.cc \
blowfish.cc \
cbc.cc \
- sha1.cc \
kwalletentry.cc \
kwalletbackend.cc
@@ -17,7 +16,6 @@ libkwalletbackend_la_METASOURCES = AUTO
noinst_HEADERS = blowfishtables.h \
cbc.h \
- sha1.h \
blockcipher.h \
kwalletentry.h \
kwalletbackend.h \
Index: kwallet/backend/kwalletbackend.cc
===================================================================
RCS file: /home/kde/kdelibs/kwallet/backend/kwalletbackend.cc,v
retrieving revision 1.55
diff -u -p -u -r1.55 kwalletbackend.cc
--- kwallet/backend/kwalletbackend.cc 6 Nov 2004 11:47:46 -0000 1.55
+++ kwallet/backend/kwalletbackend.cc 6 Nov 2004 23:17:32 -0000
@@ -34,7 +34,6 @@
#include <qregexp.h>
#include "blowfish.h"
-#include "sha1.h"
#include "cbc.h"
#include <assert.h>
@@ -149,58 +148,58 @@ static int getRandomBlock(QByteArray& ra
// this should be SHA-512 for release probably
static int password2hash(const QByteArray& password, QByteArray& hash) {
- SHA1 sha;
- int shasz = sha.size() / 8;
+ KSHA1 sha;
+ int shasz = sizeof(KSHA1::Digest);
assert(shasz >= 20);
QByteArray block1(shasz);
- sha.process(password.data(), QMIN(password.size(), 16));
+ sha.update(password.data(), QMIN(password.size(), 16));
// To make brute force take longer
for (int i = 0; i < 2000; i++) {
- memcpy(block1.data(), sha.hash(), shasz);
+ memcpy(block1.data(), sha.rawDigest(), shasz);
sha.reset();
- sha.process(block1.data(), shasz);
+ sha.update(block1);
}
sha.reset();
if (password.size() > 16) {
- sha.process(password.data() + 16, QMIN(password.size() - 16, 16));
+ sha.update(password.data() + 16, QMIN(password.size() - 16, 16));
QByteArray block2(shasz);
// To make brute force take longer
for (int i = 0; i < 2000; i++) {
- memcpy(block2.data(), sha.hash(), shasz);
+ memcpy(block2.data(), sha.rawDigest(), shasz);
sha.reset();
- sha.process(block2.data(), shasz);
+ sha.update(block2);
}
sha.reset();
if (password.size() > 32) {
- sha.process(password.data() + 32, QMIN(password.size() - 32, 16));
+ sha.update(password.data() + 32, QMIN(password.size() - 32, 16));
QByteArray block3(shasz);
// To make brute force take longer
for (int i = 0; i < 2000; i++) {
- memcpy(block3.data(), sha.hash(), shasz);
+ memcpy(block3.data(), sha.rawDigest(), shasz);
sha.reset();
- sha.process(block3.data(), shasz);
+ sha.update(block3);
}
sha.reset();
if (password.size() > 48) {
- sha.process(password.data() + 48, password.size() - 48);
+ sha.update(password.data() + 48, password.size() - 48);
QByteArray block4(shasz);
// To make brute force take longer
for (int i = 0; i < 2000; i++) {
- memcpy(block4.data(), sha.hash(), shasz);
+ memcpy(block4.data(), sha.rawDigest(), shasz);
sha.reset();
- sha.process(block4.data(), shasz);
+ sha.update(block4);
}
sha.reset();
@@ -408,9 +407,8 @@ int Backend::open(const QByteArray& pass
}
// compute the hash ourself
- SHA1 sha;
- sha.process(t, fsize);
- const char *testhash = (const char *)sha.hash();
+ KSHA1 sha(t, fsize);
+ const char *testhash = (const char *)sha.rawDigest();
// compare hashes
int sz = encrypted.size();
@@ -538,12 +536,10 @@ int Backend::sync(const QByteArray& pass
qf->writeBlock(hashes, hashes.size());
// calculate the hash of the file
- SHA1 sha;
+ KSHA1 sha(decrypted);
BlowFish _bf;
CipherBlockChain bf(&_bf);
- sha.process(decrypted.data(), decrypted.size());
-
// prepend and append the random data
QByteArray wholeFile;
long blksz = bf.blockSize();
@@ -581,7 +577,7 @@ int Backend::sync(const QByteArray& pass
wholeFile[(int)(i+blksz+4+decrypted.size())] = randBlock[(int)(i+blksz)];
}
- const char *hash = (const char *)sha.hash();
+ const char *hash = (const char *)sha.rawDigest();
for (int i = 0; i < 20; i++) {
wholeFile[(int)(newsize - 20 + i)] = hash[i];
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic