diff options
author | Mike Buland <eichlan@xagasoft.com> | 2009-02-19 23:44:57 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2009-02-19 23:44:57 +0000 |
commit | 4309066dff46f52690998bbd1f60ec8b1631f142 (patch) | |
tree | 07b6092622c909351f20590e7ee96d07f5b2d010 /src/sha1.cpp | |
parent | 3f958097632256329cdbaf2219e2ba15325e9c52 (diff) | |
download | libbu++-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.
Diffstat (limited to 'src/sha1.cpp')
-rw-r--r-- | src/sha1.cpp | 161 |
1 files changed, 161 insertions, 0 deletions
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 | |||
7 | Sha1::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 | |||
18 | Sha1::~Sha1() | ||
19 | { | ||
20 | } | ||
21 | |||
22 | void 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 | |||
79 | void 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 | |||
106 | unsigned 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 | |||
149 | uint32_t Sha1::lrot( uint32_t x, int bits ) | ||
150 | { | ||
151 | return (x<<bits) | (x>>(32 - bits)); | ||
152 | }; | ||
153 | |||
154 | void 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 | |||