2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../core/juce_StandardHeader.h"
31 #include "../io/files/juce_FileInputStream.h"
34 //==============================================================================
40 MD5::MD5 (const MD5
& other
)
42 memcpy (result
, other
.result
, sizeof (result
));
45 MD5
& MD5::operator= (const MD5
& other
)
47 memcpy (result
, other
.result
, sizeof (result
));
51 //==============================================================================
52 MD5::MD5 (const MemoryBlock
& data
)
54 ProcessContext context
;
55 context
.processBlock (data
.getData(), data
.getSize());
56 context
.finish (result
);
59 MD5::MD5 (const void* data
, const size_t numBytes
)
61 ProcessContext context
;
62 context
.processBlock (data
, numBytes
);
63 context
.finish (result
);
66 MD5::MD5 (const String
& text
)
68 ProcessContext context
;
69 String::CharPointerType
t (text
.getCharPointer());
73 // force the string into integer-sized unicode characters, to try to make it
74 // get the same results on all platforms + compilers.
75 uint32 unicodeChar
= ByteOrder::swapIfBigEndian ((uint32
) t
.getAndAdvance());
77 context
.processBlock (&unicodeChar
, sizeof (unicodeChar
));
80 context
.finish (result
);
83 void MD5::processStream (InputStream
& input
, int64 numBytesToRead
)
85 ProcessContext context
;
87 if (numBytesToRead
< 0)
88 numBytesToRead
= std::numeric_limits
<int64
>::max();
90 while (numBytesToRead
> 0)
92 uint8 tempBuffer
[512];
93 const int bytesRead
= input
.read (tempBuffer
, (int) jmin (numBytesToRead
, (int64
) sizeof (tempBuffer
)));
98 numBytesToRead
-= bytesRead
;
100 context
.processBlock (tempBuffer
, bytesRead
);
103 context
.finish (result
);
106 MD5::MD5 (InputStream
& input
, int64 numBytesToRead
)
108 processStream (input
, numBytesToRead
);
111 MD5::MD5 (const File
& file
)
113 FileInputStream
fin (file
);
115 if (fin
.getStatus().wasOk())
116 processStream (fin
, -1);
125 //==============================================================================
126 namespace MD5Functions
128 void encode (void* const output
, const void* const input
, const int numBytes
) noexcept
130 for (int i
= 0; i
< (numBytes
>> 2); ++i
)
131 static_cast<uint32
*> (output
)[i
] = ByteOrder::swapIfBigEndian (static_cast<const uint32
*> (input
) [i
]);
134 inline uint32
rotateLeft (const uint32 x
, const uint32 n
) noexcept
{ return (x
<< n
) | (x
>> (32 - n
)); }
136 inline uint32
F (const uint32 x
, const uint32 y
, const uint32 z
) noexcept
{ return (x
& y
) | (~x
& z
); }
137 inline uint32
G (const uint32 x
, const uint32 y
, const uint32 z
) noexcept
{ return (x
& z
) | (y
& ~z
); }
138 inline uint32
H (const uint32 x
, const uint32 y
, const uint32 z
) noexcept
{ return x
^ y
^ z
; }
139 inline uint32
I (const uint32 x
, const uint32 y
, const uint32 z
) noexcept
{ return y
^ (x
| ~z
); }
141 void FF (uint32
& a
, const uint32 b
, const uint32 c
, const uint32 d
, const uint32 x
, const uint32 s
, const uint32 ac
) noexcept
143 a
+= F (b
, c
, d
) + x
+ ac
;
144 a
= rotateLeft (a
, s
) + b
;
147 void GG (uint32
& a
, const uint32 b
, const uint32 c
, const uint32 d
, const uint32 x
, const uint32 s
, const uint32 ac
) noexcept
149 a
+= G (b
, c
, d
) + x
+ ac
;
150 a
= rotateLeft (a
, s
) + b
;
153 void HH (uint32
& a
, const uint32 b
, const uint32 c
, const uint32 d
, const uint32 x
, const uint32 s
, const uint32 ac
) noexcept
155 a
+= H (b
, c
, d
) + x
+ ac
;
156 a
= rotateLeft (a
, s
) + b
;
159 void II (uint32
& a
, const uint32 b
, const uint32 c
, const uint32 d
, const uint32 x
, const uint32 s
, const uint32 ac
) noexcept
161 a
+= I (b
, c
, d
) + x
+ ac
;
162 a
= rotateLeft (a
, s
) + b
;
166 //==============================================================================
167 MD5::ProcessContext::ProcessContext()
169 state
[0] = 0x67452301;
170 state
[1] = 0xefcdab89;
171 state
[2] = 0x98badcfe;
172 state
[3] = 0x10325476;
178 void MD5::ProcessContext::processBlock (const void* const data
, const size_t dataSize
)
180 int bufferPos
= ((count
[0] >> 3) & 0x3F);
182 count
[0] += (uint32
) (dataSize
<< 3);
184 if (count
[0] < ((uint32
) dataSize
<< 3))
187 count
[1] += (uint32
) (dataSize
>> 29);
189 const size_t spaceLeft
= 64 - bufferPos
;
192 if (dataSize
>= spaceLeft
)
194 memcpy (buffer
+ bufferPos
, data
, spaceLeft
);
197 for (i
= spaceLeft
; i
+ 64 <= dataSize
; i
+= 64)
198 transform (static_cast <const char*> (data
) + i
);
203 memcpy (buffer
+ bufferPos
, static_cast <const char*> (data
) + i
, dataSize
- i
);
206 //==============================================================================
207 void MD5::ProcessContext::finish (void* const result
)
209 unsigned char encodedLength
[8];
210 MD5Functions::encode (encodedLength
, count
, 8);
212 // Pad out to 56 mod 64.
213 const int index
= (uint32
) ((count
[0] >> 3) & 0x3f);
215 const int paddingLength
= (index
< 56) ? (56 - index
)
218 uint8 paddingBuffer
[64] = { 0x80 }; // first byte is 0x80, remaining bytes are zero.
219 processBlock (paddingBuffer
, paddingLength
);
221 processBlock (encodedLength
, 8);
223 MD5Functions::encode (result
, state
, 16);
227 void MD5::ProcessContext::transform (const void* const bufferToTransform
)
229 using namespace MD5Functions
;
237 encode (x
, bufferToTransform
, 64);
241 S11
= 7, S12
= 12, S13
= 17, S14
= 22, S21
= 5, S22
= 9, S23
= 14, S24
= 20,
242 S31
= 4, S32
= 11, S33
= 16, S34
= 23, S41
= 6, S42
= 10, S43
= 15, S44
= 21
245 FF (a
, b
, c
, d
, x
[ 0], S11
, 0xd76aa478); FF (d
, a
, b
, c
, x
[ 1], S12
, 0xe8c7b756);
246 FF (c
, d
, a
, b
, x
[ 2], S13
, 0x242070db); FF (b
, c
, d
, a
, x
[ 3], S14
, 0xc1bdceee);
247 FF (a
, b
, c
, d
, x
[ 4], S11
, 0xf57c0faf); FF (d
, a
, b
, c
, x
[ 5], S12
, 0x4787c62a);
248 FF (c
, d
, a
, b
, x
[ 6], S13
, 0xa8304613); FF (b
, c
, d
, a
, x
[ 7], S14
, 0xfd469501);
249 FF (a
, b
, c
, d
, x
[ 8], S11
, 0x698098d8); FF (d
, a
, b
, c
, x
[ 9], S12
, 0x8b44f7af);
250 FF (c
, d
, a
, b
, x
[10], S13
, 0xffff5bb1); FF (b
, c
, d
, a
, x
[11], S14
, 0x895cd7be);
251 FF (a
, b
, c
, d
, x
[12], S11
, 0x6b901122); FF (d
, a
, b
, c
, x
[13], S12
, 0xfd987193);
252 FF (c
, d
, a
, b
, x
[14], S13
, 0xa679438e); FF (b
, c
, d
, a
, x
[15], S14
, 0x49b40821);
254 GG (a
, b
, c
, d
, x
[ 1], S21
, 0xf61e2562); GG (d
, a
, b
, c
, x
[ 6], S22
, 0xc040b340);
255 GG (c
, d
, a
, b
, x
[11], S23
, 0x265e5a51); GG (b
, c
, d
, a
, x
[ 0], S24
, 0xe9b6c7aa);
256 GG (a
, b
, c
, d
, x
[ 5], S21
, 0xd62f105d); GG (d
, a
, b
, c
, x
[10], S22
, 0x02441453);
257 GG (c
, d
, a
, b
, x
[15], S23
, 0xd8a1e681); GG (b
, c
, d
, a
, x
[ 4], S24
, 0xe7d3fbc8);
258 GG (a
, b
, c
, d
, x
[ 9], S21
, 0x21e1cde6); GG (d
, a
, b
, c
, x
[14], S22
, 0xc33707d6);
259 GG (c
, d
, a
, b
, x
[ 3], S23
, 0xf4d50d87); GG (b
, c
, d
, a
, x
[ 8], S24
, 0x455a14ed);
260 GG (a
, b
, c
, d
, x
[13], S21
, 0xa9e3e905); GG (d
, a
, b
, c
, x
[ 2], S22
, 0xfcefa3f8);
261 GG (c
, d
, a
, b
, x
[ 7], S23
, 0x676f02d9); GG (b
, c
, d
, a
, x
[12], S24
, 0x8d2a4c8a);
263 HH (a
, b
, c
, d
, x
[ 5], S31
, 0xfffa3942); HH (d
, a
, b
, c
, x
[ 8], S32
, 0x8771f681);
264 HH (c
, d
, a
, b
, x
[11], S33
, 0x6d9d6122); HH (b
, c
, d
, a
, x
[14], S34
, 0xfde5380c);
265 HH (a
, b
, c
, d
, x
[ 1], S31
, 0xa4beea44); HH (d
, a
, b
, c
, x
[ 4], S32
, 0x4bdecfa9);
266 HH (c
, d
, a
, b
, x
[ 7], S33
, 0xf6bb4b60); HH (b
, c
, d
, a
, x
[10], S34
, 0xbebfbc70);
267 HH (a
, b
, c
, d
, x
[13], S31
, 0x289b7ec6); HH (d
, a
, b
, c
, x
[ 0], S32
, 0xeaa127fa);
268 HH (c
, d
, a
, b
, x
[ 3], S33
, 0xd4ef3085); HH (b
, c
, d
, a
, x
[ 6], S34
, 0x04881d05);
269 HH (a
, b
, c
, d
, x
[ 9], S31
, 0xd9d4d039); HH (d
, a
, b
, c
, x
[12], S32
, 0xe6db99e5);
270 HH (c
, d
, a
, b
, x
[15], S33
, 0x1fa27cf8); HH (b
, c
, d
, a
, x
[ 2], S34
, 0xc4ac5665);
272 II (a
, b
, c
, d
, x
[ 0], S41
, 0xf4292244); II (d
, a
, b
, c
, x
[ 7], S42
, 0x432aff97);
273 II (c
, d
, a
, b
, x
[14], S43
, 0xab9423a7); II (b
, c
, d
, a
, x
[ 5], S44
, 0xfc93a039);
274 II (a
, b
, c
, d
, x
[12], S41
, 0x655b59c3); II (d
, a
, b
, c
, x
[ 3], S42
, 0x8f0ccc92);
275 II (c
, d
, a
, b
, x
[10], S43
, 0xffeff47d); II (b
, c
, d
, a
, x
[ 1], S44
, 0x85845dd1);
276 II (a
, b
, c
, d
, x
[ 8], S41
, 0x6fa87e4f); II (d
, a
, b
, c
, x
[15], S42
, 0xfe2ce6e0);
277 II (c
, d
, a
, b
, x
[ 6], S43
, 0xa3014314); II (b
, c
, d
, a
, x
[13], S44
, 0x4e0811a1);
278 II (a
, b
, c
, d
, x
[ 4], S41
, 0xf7537e82); II (d
, a
, b
, c
, x
[11], S42
, 0xbd3af235);
279 II (c
, d
, a
, b
, x
[ 2], S43
, 0x2ad7d2bb); II (b
, c
, d
, a
, x
[ 9], S44
, 0xeb86d391);
289 //==============================================================================
290 MemoryBlock
MD5::getRawChecksumData() const
292 return MemoryBlock (result
, sizeof (result
));
295 String
MD5::toHexString() const
297 return String::toHexString (result
, sizeof (result
), 0);
300 //==============================================================================
301 bool MD5::operator== (const MD5
& other
) const
303 return memcmp (result
, other
.result
, sizeof (result
)) == 0;
306 bool MD5::operator!= (const MD5
& other
) const
308 return ! operator== (other
);