aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2009-02-19 23:44:57 +0000
committerMike Buland <eichlan@xagasoft.com>2009-02-19 23:44:57 +0000
commit4309066dff46f52690998bbd1f60ec8b1631f142 (patch)
tree07b6092622c909351f20590e7ee96d07f5b2d010
parent3f958097632256329cdbaf2219e2ba15325e9c52 (diff)
downloadlibbu++-4309066dff46f52690998bbd1f60ec8b1631f142.tar.gz
libbu++-4309066dff46f52690998bbd1f60ec8b1631f142.tar.bz2
libbu++-4309066dff46f52690998bbd1f60ec8b1631f142.tar.xz
libbu++-4309066dff46f52690998bbd1f60ec8b1631f142.zip
We have the new Bu::CryptoHash base class and Bu::Md5 is here and ready
to rock. sha1 is still only a shell, I dunno if/when I'm going to implement that one. So far Bu::Md5 is 100% compatible with md5sum in all tests performed so far, in fact the test program's output is compatible with md5sum in every way (and it's so cute and little too!) Oh, minor update for stdstream and the formatter, they can handle more handy types now.
-rw-r--r--src/cryptohash.cpp15
-rw-r--r--src/cryptohash.h22
-rw-r--r--src/formatter.cpp6
-rw-r--r--src/formatter.h1
-rw-r--r--src/md5.cpp191
-rw-r--r--src/md5.h40
-rw-r--r--src/sha1.cpp161
-rw-r--r--src/sha1.h42
-rw-r--r--src/tests/md5.cpp27
-rw-r--r--src/tests/stdstream.cpp4
10 files changed, 507 insertions, 2 deletions
diff --git a/src/cryptohash.cpp b/src/cryptohash.cpp
new file mode 100644
index 0000000..0fa2a25
--- /dev/null
+++ b/src/cryptohash.cpp
@@ -0,0 +1,15 @@
1#include "bu/cryptohash.h"
2
3Bu::CryptoHash::CryptoHash()
4{
5}
6
7Bu::CryptoHash::~CryptoHash()
8{
9}
10
11void Bu::CryptoHash::addData( const Bu::FString &sData )
12{
13 addData( sData.getStr(), sData.getSize() );
14}
15
diff --git a/src/cryptohash.h b/src/cryptohash.h
new file mode 100644
index 0000000..01d4634
--- /dev/null
+++ b/src/cryptohash.h
@@ -0,0 +1,22 @@
1#ifndef BU_CRYPTO_HASH_H
2#define BU_CRYPTO_HASH_H
3
4#include "bu/fstring.h"
5
6namespace Bu
7{
8 class CryptoHash
9 {
10 public:
11 CryptoHash();
12 virtual ~CryptoHash();
13
14 virtual void reset() = 0;
15 virtual void setSalt( const Bu::FString &sSalt ) = 0;
16 virtual void addData( const char *sData, int iSize ) = 0;
17 virtual void addData( const Bu::FString &sData );
18 virtual FString getResult() = 0;
19 };
20};
21
22#endif
diff --git a/src/formatter.cpp b/src/formatter.cpp
index 1ec3c39..36e49c8 100644
--- a/src/formatter.cpp
+++ b/src/formatter.cpp
@@ -159,6 +159,12 @@ Bu::Formatter &Bu::operator<<( Bu::Formatter &rOut, const char *sStr )
159 return rOut; 159 return rOut;
160} 160}
161 161
162Bu::Formatter &Bu::operator<<( Bu::Formatter &rOut, char *sStr )
163{
164 rOut.writeAligned( sStr, strlen( sStr ) );
165 return rOut;
166}
167
162Bu::Formatter &Bu::operator<<( Bu::Formatter &rOut, const Bu::FString &sStr ) 168Bu::Formatter &Bu::operator<<( Bu::Formatter &rOut, const Bu::FString &sStr )
163{ 169{
164 rOut.writeAligned( sStr ); 170 rOut.writeAligned( sStr );
diff --git a/src/formatter.h b/src/formatter.h
index 4bab505..d9066cb 100644
--- a/src/formatter.h
+++ b/src/formatter.h
@@ -185,6 +185,7 @@ namespace Bu
185 Formatter &operator<<( Formatter &rOut, const Formatter::Fmt &f ); 185 Formatter &operator<<( Formatter &rOut, const Formatter::Fmt &f );
186 Formatter &operator<<( Formatter &rOut, Formatter::Special s ); 186 Formatter &operator<<( Formatter &rOut, Formatter::Special s );
187 Formatter &operator<<( Formatter &rOut, const char *sStr ); 187 Formatter &operator<<( Formatter &rOut, const char *sStr );
188 Formatter &operator<<( Formatter &rOut, char *sStr );
188 Formatter &operator<<( Formatter &rOut, const Bu::FString &sStr ); 189 Formatter &operator<<( Formatter &rOut, const Bu::FString &sStr );
189 Formatter &operator<<( Formatter &rOut, signed char c ); 190 Formatter &operator<<( Formatter &rOut, signed char c );
190 Formatter &operator<<( Formatter &rOut, char c ); 191 Formatter &operator<<( Formatter &rOut, char c );
diff --git a/src/md5.cpp b/src/md5.cpp
new file mode 100644
index 0000000..aa965ed
--- /dev/null
+++ b/src/md5.cpp
@@ -0,0 +1,191 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include "md5.h"
5
6// This performs a wrapping bitwise shift, kinda' fun!
7
8#define bit_roll( num, cnt ) \
9 (((num) << (cnt)) | (((num) >> (32 - (cnt))) & ~(-1<<(cnt))))
10
11//#define md5_cmn( q, a, b, x, s, t ) (bit_roll((a + q + x + t), s) + b)
12
13// The following are handy wrappers for the cmn function
14#define md5_ff( a, b, c, d, x, s, t ) \
15 (md5_cmn((b & c) | ((~b) & d), a, b, x, s, t))
16
17#define md5_gg( a, b, c, d, x, s, t ) \
18 (md5_cmn((b & d) | (c & (~d)), a, b, x, s, t))
19
20#define md5_hh( a, b, c, d, x, s, t ) \
21 (md5_cmn(b ^ c ^ d, a, b, x, s, t))
22
23#define md5_ii( a, b, c, d, x, s, t ) \
24 (md5_cmn(c ^ (b | (~d)), a, b, x, s, t))
25
26inline long md5_cmn( long q, long a, long b, long x, long s, long t )
27{
28 return bit_roll((a + q + x + t), s) + b;
29}
30
31Bu::Md5::Md5()
32{
33 reset();
34}
35
36Bu::Md5::~Md5()
37{
38}
39
40void Bu::Md5::reset()
41{
42 // These are the magic seed numbers...
43
44 sum[0] = 1732584193;
45 sum[1] = -271733879;
46 sum[2] = -1732584194;
47 sum[3] = 271733878;
48
49 iBytes = 0;
50 memset( inbuf, 0, 4*16 );
51 iFill = 0;
52}
53
54void Bu::Md5::setSalt( const Bu::FString & /*sSalt*/ )
55{
56}
57
58void Bu::Md5::addData( const char *sData, int iSize )
59{
60 int iInPos = 0;
61 for(;;)
62 {
63 for( ; iFill < 16*4 && iInPos < iSize; iFill++, iInPos++ )
64 {
65 inbuf[iFill>>2] |= ((long)sData[iInPos]) << ((iFill*8)%32);
66 }
67 if( iFill < 16*4 )
68 break;
69 compBlock( inbuf, sum );
70 memset( inbuf, 0, 4*16 );
71 iFill = 0;
72 }
73 iBytes += iSize;
74}
75
76Bu::FString Bu::Md5::getResult()
77{
78 static const char hex_tab[] = {"0123456789abcdef"};
79 char str[33];
80
81 long lsum[4];
82 memcpy( lsum, sum, 4*4 );
83 long lbuf[16];
84 memcpy( lbuf, inbuf, 4*16 );
85
86 lbuf[iFill>>2] |= 0x80 << ((iFill*8)%32);
87 uint64_t iBits = iBytes*8;
88 if( iBytes > 0 && iFill>>2 >= 14 )
89 {
90 compBlock( lbuf, lsum );
91 memset( lbuf, 0, 4*16 );
92 memcpy( lbuf+14, &iBits, 8 );
93 compBlock( lbuf, lsum );
94 }
95 else
96 {
97 memcpy( lbuf+14, &iBits, 8 );
98 compBlock( lbuf, lsum );
99 }
100
101 int k = 0;
102 for( int i = 0; i < 16; i++ )
103 {
104 str[k++] = hex_tab[(lsum[i>>2] >> ((i%4)*8+4)) & 0xF];
105 str[k++] = hex_tab[(lsum[i>>2] >> ((i%4)*8 )) & 0xF];
106 }
107
108 return Bu::FString( str, 32 );
109}
110
111void Bu::Md5::compBlock( long *x, long *lsum )
112{
113 long a = lsum[0];
114 long b = lsum[1];
115 long c = lsum[2];
116 long d = lsum[3];
117
118 a = md5_ff(a, b, c, d, x[ 0], 7 , -680876936);
119 d = md5_ff(d, a, b, c, x[ 1], 12, -389564586);
120 c = md5_ff(c, d, a, b, x[ 2], 17, 606105819);
121 b = md5_ff(b, c, d, a, x[ 3], 22, -1044525330);
122 a = md5_ff(a, b, c, d, x[ 4], 7 , -176418897);
123 d = md5_ff(d, a, b, c, x[ 5], 12, 1200080426);
124 c = md5_ff(c, d, a, b, x[ 6], 17, -1473231341);
125 b = md5_ff(b, c, d, a, x[ 7], 22, -45705983);
126 a = md5_ff(a, b, c, d, x[ 8], 7 , 1770035416);
127 d = md5_ff(d, a, b, c, x[ 9], 12, -1958414417);
128 c = md5_ff(c, d, a, b, x[10], 17, -42063);
129 b = md5_ff(b, c, d, a, x[11], 22, -1990404162);
130 a = md5_ff(a, b, c, d, x[12], 7 , 1804603682);
131 d = md5_ff(d, a, b, c, x[13], 12, -40341101);
132 c = md5_ff(c, d, a, b, x[14], 17, -1502002290);
133 b = md5_ff(b, c, d, a, x[15], 22, 1236535329);
134
135 a = md5_gg(a, b, c, d, x[ 1], 5 , -165796510);
136 d = md5_gg(d, a, b, c, x[ 6], 9 , -1069501632);
137 c = md5_gg(c, d, a, b, x[11], 14, 643717713);
138 b = md5_gg(b, c, d, a, x[ 0], 20, -373897302);
139 a = md5_gg(a, b, c, d, x[ 5], 5 , -701558691);
140 d = md5_gg(d, a, b, c, x[10], 9 , 38016083);
141 c = md5_gg(c, d, a, b, x[15], 14, -660478335);
142 b = md5_gg(b, c, d, a, x[ 4], 20, -405537848);
143 a = md5_gg(a, b, c, d, x[ 9], 5 , 568446438);
144 d = md5_gg(d, a, b, c, x[14], 9 , -1019803690);
145 c = md5_gg(c, d, a, b, x[ 3], 14, -187363961);
146 b = md5_gg(b, c, d, a, x[ 8], 20, 1163531501);
147 a = md5_gg(a, b, c, d, x[13], 5 , -1444681467);
148 d = md5_gg(d, a, b, c, x[ 2], 9 , -51403784);
149 c = md5_gg(c, d, a, b, x[ 7], 14, 1735328473);
150 b = md5_gg(b, c, d, a, x[12], 20, -1926607734);
151
152 a = md5_hh(a, b, c, d, x[ 5], 4 , -378558);
153 d = md5_hh(d, a, b, c, x[ 8], 11, -2022574463);
154 c = md5_hh(c, d, a, b, x[11], 16, 1839030562);
155 b = md5_hh(b, c, d, a, x[14], 23, -35309556);
156 a = md5_hh(a, b, c, d, x[ 1], 4 , -1530992060);
157 d = md5_hh(d, a, b, c, x[ 4], 11, 1272893353);
158 c = md5_hh(c, d, a, b, x[ 7], 16, -155497632);
159 b = md5_hh(b, c, d, a, x[10], 23, -1094730640);
160 a = md5_hh(a, b, c, d, x[13], 4 , 681279174);
161 d = md5_hh(d, a, b, c, x[ 0], 11, -358537222);
162 c = md5_hh(c, d, a, b, x[ 3], 16, -722521979);
163 b = md5_hh(b, c, d, a, x[ 6], 23, 76029189);
164 a = md5_hh(a, b, c, d, x[ 9], 4 , -640364487);
165 d = md5_hh(d, a, b, c, x[12], 11, -421815835);
166 c = md5_hh(c, d, a, b, x[15], 16, 530742520);
167 b = md5_hh(b, c, d, a, x[ 2], 23, -995338651);
168
169 a = md5_ii(a, b, c, d, x[ 0], 6 , -198630844);
170 d = md5_ii(d, a, b, c, x[ 7], 10, 1126891415);
171 c = md5_ii(c, d, a, b, x[14], 15, -1416354905);
172 b = md5_ii(b, c, d, a, x[ 5], 21, -57434055);
173 a = md5_ii(a, b, c, d, x[12], 6 , 1700485571);
174 d = md5_ii(d, a, b, c, x[ 3], 10, -1894986606);
175 c = md5_ii(c, d, a, b, x[10], 15, -1051523);
176 b = md5_ii(b, c, d, a, x[ 1], 21, -2054922799);
177 a = md5_ii(a, b, c, d, x[ 8], 6 , 1873313359);
178 d = md5_ii(d, a, b, c, x[15], 10, -30611744);
179 c = md5_ii(c, d, a, b, x[ 6], 15, -1560198380);
180 b = md5_ii(b, c, d, a, x[13], 21, 1309151649);
181 a = md5_ii(a, b, c, d, x[ 4], 6 , -145523070);
182 d = md5_ii(d, a, b, c, x[11], 10, -1120210379);
183 c = md5_ii(c, d, a, b, x[ 2], 15, 718787259);
184 b = md5_ii(b, c, d, a, x[ 9], 21, -343485551);
185
186 lsum[0] = a + lsum[0];
187 lsum[1] = b + lsum[1];
188 lsum[2] = c + lsum[2];
189 lsum[3] = d + lsum[3];
190}
191
diff --git a/src/md5.h b/src/md5.h
new file mode 100644
index 0000000..c548041
--- /dev/null
+++ b/src/md5.h
@@ -0,0 +1,40 @@
1#ifndef BU_MD5_H
2#define BU_MD5_H
3
4#include "bu/cryptohash.h"
5
6namespace Bu
7{
8 /**
9 * Class for easily calculating MD5 sums of just about any data.
10 *@author Mike Buland
11 */
12 class Md5 : public Bu::CryptoHash
13 {
14 public:
15 /** Build an MD5 sum builder. */
16 Md5();
17
18 /** Deconstruct */
19 virtual ~Md5();
20
21 virtual void reset();
22 virtual void setSalt( const Bu::FString &sSalt );
23 virtual void addData( const char *sData, int iSize );
24 using Bu::CryptoHash::addData;
25 virtual FString getResult();
26
27 private:
28 /**
29 * Compute one block of input data.
30 */
31 void compBlock( long *x, long *lsum );
32
33 long inbuf[16];
34 long iFill;
35 long sum[4];
36 uint64_t iBytes;
37 };
38};
39
40#endif
diff --git a/src/sha1.cpp b/src/sha1.cpp
new file mode 100644
index 0000000..8270c3b
--- /dev/null
+++ b/src/sha1.cpp
@@ -0,0 +1,161 @@
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4
5#include "sha1.h"
6
7Sha1::Sha1() :
8 H0( 0x67452301 ),
9 H1( 0xefcdab89 ),
10 H2( 0x98badcfe ),
11 H3( 0x10325476 ),
12 H4( 0xc3d2e1f0 ),
13 unprocessedBytes( 0 ),
14 size( 0 )
15{
16}
17
18Sha1::~Sha1()
19{
20}
21
22void Sha1::process()
23{
24 int t;
25 uint32_t a, b, c, d, e, K, f, W[80];
26
27 // starting values
28 a = H0;
29 b = H1;
30 c = H2;
31 d = H3;
32 e = H4;
33
34 // copy and expand the message block
35 for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24)
36 +(bytes[t*4 + 1] << 16)
37 +(bytes[t*4 + 2] << 8)
38 + bytes[t*4 + 3];
39 for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 );
40
41 /* main loop */
42 uint32_t temp;
43 for( t = 0; t < 80; t++ )
44 {
45 if( t < 20 ) {
46 K = 0x5a827999;
47 f = (b & c) | ((~b) & d);
48 } else if( t < 40 ) {
49 K = 0x6ed9eba1;
50 f = b ^ c ^ d;
51 } else if( t < 60 ) {
52 K = 0x8f1bbcdc;
53 f = (b & c) | (b & d) | (c & d);
54 } else {
55 K = 0xca62c1d6;
56 f = b ^ c ^ d;
57 }
58 temp = lrot(a,5) + f + e + W[t] + K;
59 e = d;
60 d = c;
61 c = lrot(b,30);
62 b = a;
63 a = temp;
64 //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e );
65 }
66
67 /* add variables */
68 H0 += a;
69 H1 += b;
70 H2 += c;
71 H3 += d;
72 H4 += e;
73
74 //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 );
75 /* all bytes have been processed */
76 unprocessedBytes = 0;
77}
78
79void Sha1::update( const char* data, int num )
80{
81 // add these bytes to the running total
82 size += num;
83
84 // repeat until all data is processed
85 while( num > 0 )
86 {
87 // number of bytes required to complete block
88 int needed = 64 - unprocessedBytes;
89
90 // number of bytes to copy (use smaller of two)
91 int toCopy = (num < needed) ? num : needed;
92
93 // Copy the bytes
94 memcpy( bytes + unprocessedBytes, data, toCopy );
95
96 // Bytes have been copied
97 num -= toCopy;
98 data += toCopy;
99 unprocessedBytes += toCopy;
100
101 // there is a full block
102 if( unprocessedBytes == 64 ) process();
103 }
104}
105
106unsigned char* Sha1::getDigest()
107{
108 // save the message size
109 uint32_t totalBitsL = size << 3;
110 uint32_t totalBitsH = size >> 29;
111
112 // add 0x80 to the message
113 update( "\x80", 1 );
114
115 unsigned char footer[64] = {
116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
120
121 // block has no room for 8-byte filesize, so finish it
122 if( unprocessedBytes > 56 )
123 update( (char*)footer, 64 - unprocessedBytes);
124
125 // how many zeros do we need
126 int neededZeros = 56 - unprocessedBytes;
127
128 // store file size (in bits) in big-endian format
129 toBigEndian( totalBitsH, footer + neededZeros );
130 toBigEndian( totalBitsL, footer + neededZeros + 4 );
131
132 // finish the final block
133 update( (char*)footer, neededZeros + 8 );
134
135 // allocate memory for the digest bytes
136 unsigned char* digest = new unsigned char[20];
137
138 // copy the digest bytes
139 toBigEndian( H0, digest );
140 toBigEndian( H1, digest + 4 );
141 toBigEndian( H2, digest + 8 );
142 toBigEndian( H3, digest + 12 );
143 toBigEndian( H4, digest + 16 );
144
145 // return the digest
146 return digest;
147}
148
149uint32_t Sha1::lrot( uint32_t x, int bits )
150{
151 return (x<<bits) | (x>>(32 - bits));
152};
153
154void Sha1::toBigEndian( uint32_t num, unsigned char* byte )
155{
156 byte[0] = (unsigned char)(num>>24);
157 byte[1] = (unsigned char)(num>>16);
158 byte[2] = (unsigned char)(num>>8);
159 byte[3] = (unsigned char)num;
160}
161
diff --git a/src/sha1.h b/src/sha1.h
new file mode 100644
index 0000000..ab6081d
--- /dev/null
+++ b/src/sha1.h
@@ -0,0 +1,42 @@
1/* sha1.h
2
3Copyright (c) 2005 Michael D. Leonhard
4
5http://tamale.net/
6
7This file is licensed under the terms described in the
8accompanying LICENSE file.
9*/
10
11#ifndef SHA1_H
12#define SHA1_H
13
14#include <stdint.h>
15
16/**
17 * Calculates SHA-1 sums. This is based strongly on code from Michael D.
18 * Leonhard who released his code under the terms of the MIT license, thank you!
19 */
20class Sha1
21{
22public:
23 Sha1();
24 ~Sha1();
25
26 void update( const char* data, int num );
27 unsigned char* getDigest();
28
29 // utility methods
30 static uint32_t lrot( uint32_t x, int bits );
31 static void toBigEndian( uint32_t in, unsigned char* out );
32
33private:
34 // fields
35 uint32_t H0, H1, H2, H3, H4;
36 unsigned char bytes[64];
37 int unprocessedBytes;
38 uint32_t size;
39 void process();
40};
41
42#endif
diff --git a/src/tests/md5.cpp b/src/tests/md5.cpp
new file mode 100644
index 0000000..dea957b
--- /dev/null
+++ b/src/tests/md5.cpp
@@ -0,0 +1,27 @@
1#include "bu/sio.h"
2#include "bu/file.h"
3#include "bu/md5.h"
4
5using Bu::sio;
6
7int main( int argc, char *argv[] )
8{
9 argv++, argc--;
10 for(; *argv; argv++ )
11 {
12 Bu::File fIn( *argv, Bu::File::Read );
13 Bu::Md5 m;
14
15 char buf[1000];
16 for(;;)
17 {
18 int iRead = fIn.read( buf, 1000 );
19 m.addData( buf, iRead );
20 if( iRead < 1000 )
21 break;
22 }
23
24 sio << m.getResult() << " *" << *argv << sio.nl;
25 }
26}
27
diff --git a/src/tests/stdstream.cpp b/src/tests/stdstream.cpp
index cb22e22..0949a8c 100644
--- a/src/tests/stdstream.cpp
+++ b/src/tests/stdstream.cpp
@@ -24,8 +24,8 @@ int main()
24 sio << 0.123 << sio.nl; 24 sio << 0.123 << sio.nl;
25 sio << true << " and then " << false << sio.nl; 25 sio << true << " and then " << false << sio.nl;
26 26
27 //for( int j = 2; j <= 36; j++ ) 27 for( int j = 2; j <= 36; j++ )
28 // sio << "radix(" << j << ") = " << Fmt().radix( j ) << 255 << sio.nl; 28 sio << "radix(" << j << ") = " << Fmt().radix( j ).width( 8 ).align( Fmt::Right ) << 255 << sio.nl;
29 29
30 return 0; 30 return 0;
31} 31}