MD5/Implementation: Difference between revisions
Content added Content deleted
(Go solution) |
|||
Line 941: | Line 941: | ||
digest(MSG) = A36190ECA92203A477EFC4DAB966CE6F |
digest(MSG) = A36190ECA92203A477EFC4DAB966CE6F |
||
zmd5 : 111.50 M/sec ( 4.59secs)</pre> |
zmd5 : 111.50 M/sec ( 4.59secs)</pre> |
||
=={{header|Go}}== |
|||
{{trans|Java}} |
|||
Condensed a bit after translating. It does an extra copy of the message compared to the Java version, but then we're not worrying about efficiency here. A limitation from RFC 1321 is that the function md5 takes a string, which is a number of whole bytes. Messages of arbitrary bit length are not supported. |
|||
<lang go>package main |
|||
import ( |
|||
"fmt" |
|||
"math" |
|||
) |
|||
type testCase struct { |
|||
hashCode string |
|||
string |
|||
} |
|||
var testCases = []testCase{ |
|||
{"d41d8cd98f00b204e9800998ecf8427e", ""}, |
|||
{"0cc175b9c0f1b6a831c399e269772661", "a"}, |
|||
{"900150983cd24fb0d6963f7d28e17f72", "abc"}, |
|||
{"f96b697d7cb7938d525a2f31aaf161d0", "message digest"}, |
|||
{"c3fcd3d76192e4007dfb496cca67e13b", "abcdefghijklmnopqrstuvwxyz"}, |
|||
{"d174ab98d277d9f5a5611c2c9f419d9f", |
|||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}, |
|||
{"57edf4a22be3c955ac49da2e2107b67a", "12345678901234567890" + |
|||
"123456789012345678901234567890123456789012345678901234567890"}, |
|||
} |
|||
func main() { |
|||
for _, tc := range testCases { |
|||
fmt.Printf("%s\n%x\n\n", tc.hashCode, md5(tc.string)) |
|||
} |
|||
} |
|||
var shift = []uint{7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21} |
|||
var table [64]uint32 |
|||
func init() { |
|||
for i := range table { |
|||
n := math.Float64bits(math.Abs(math.Sin(float64(i + 1)))) |
|||
table[i] = uint32((n&0xFFFFFFFFFFFFF | 0x10000000000000) >> |
|||
(1043 - (n >> 52 & 0x7FF))) |
|||
} |
|||
} |
|||
func md5(s string) (r [16]byte) { |
|||
numBlocks := (len(s) + 72) >> 6 |
|||
padded := make([]byte, numBlocks<<6) |
|||
copy(padded, s) |
|||
padded[len(s)] = 0x80 |
|||
for i, messageLenBits := len(padded)-8, len(s)<<3; i < len(padded); i++ { |
|||
padded[i] = byte(messageLenBits) |
|||
messageLenBits >>= 8 |
|||
} |
|||
var a, b, c, d uint32 = 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 |
|||
var buffer [16]uint32 |
|||
for i := 0; i < numBlocks; i++ { |
|||
index := i << 6 |
|||
for j := 0; j < 64; j, index = j+1, index+1 { |
|||
buffer[j>>2] = (uint32(padded[index]) << 24) | (buffer[j>>2] >> 8) |
|||
} |
|||
a1, b1, c1, d1 := a, b, c, d |
|||
for j := 0; j < 64; j++ { |
|||
var f uint32 |
|||
bufferIndex := j |
|||
round := j >> 4 |
|||
switch round { |
|||
case 0: |
|||
f = (b1 & c1) | (^b1 & d1) |
|||
case 1: |
|||
f = (b1 & d1) | (c1 & ^d1) |
|||
bufferIndex = (bufferIndex*5 + 1) & 0x0F |
|||
case 2: |
|||
f = b1 ^ c1 ^ d1 |
|||
bufferIndex = (bufferIndex*3 + 5) & 0x0F |
|||
case 3: |
|||
f = c1 ^ (b1 | ^d1) |
|||
bufferIndex = (bufferIndex * 7) & 0x0F |
|||
} |
|||
sa := shift[(round<<2)|(j&3)] |
|||
a1 += f + buffer[bufferIndex] + table[j] |
|||
a1, d1, c1, b1 = d1, c1, b1, a1<<sa|a1>>(32-sa)+b1 |
|||
} |
|||
a, b, c, d = a+a1, b+b1, c+c1, d+d1 |
|||
} |
|||
for i, n := range []uint32{a, b, c, d} { |
|||
for j := 0; j < 4; j++ { |
|||
r[i*4+j] = byte(n) |
|||
n >>= 8 |
|||
} |
|||
} |
|||
return |
|||
}</lang> |
|||
Output: |
|||
<pre> |
|||
d41d8cd98f00b204e9800998ecf8427e |
|||
d41d8cd98f00b204e9800998ecf8427e |
|||
0cc175b9c0f1b6a831c399e269772661 |
|||
0cc175b9c0f1b6a831c399e269772661 |
|||
900150983cd24fb0d6963f7d28e17f72 |
|||
900150983cd24fb0d6963f7d28e17f72 |
|||
f96b697d7cb7938d525a2f31aaf161d0 |
|||
f96b697d7cb7938d525a2f31aaf161d0 |
|||
c3fcd3d76192e4007dfb496cca67e13b |
|||
c3fcd3d76192e4007dfb496cca67e13b |
|||
d174ab98d277d9f5a5611c2c9f419d9f |
|||
d174ab98d277d9f5a5611c2c9f419d9f |
|||
57edf4a22be3c955ac49da2e2107b67a |
|||
57edf4a22be3c955ac49da2e2107b67a |
|||
</pre> |
|||
=={{header|Icon}} and {{header|Unicon}}== |
=={{header|Icon}} and {{header|Unicon}}== |