Hash computes the MD5 hash of the input message
(message []byte)
| 61 | |
| 62 | // Hash computes the MD5 hash of the input message |
| 63 | func Hash(message []byte) [16]byte { |
| 64 | message = pad(message) |
| 65 | |
| 66 | // Initialize MD5 state variables |
| 67 | a0, b0, c0, d0 := uint32(0x67452301), uint32(0xefcdab89), uint32(0x98badcfe), uint32(0x10325476) |
| 68 | |
| 69 | // Process the message in successive 512-bit chunks |
| 70 | for i := 0; i < len(message); i += 64 { |
| 71 | chunk := message[i : i+64] |
| 72 | var M [16]uint32 |
| 73 | for j := 0; j < 16; j++ { |
| 74 | M[j] = binary.LittleEndian.Uint32(chunk[j*4 : (j+1)*4]) |
| 75 | } |
| 76 | |
| 77 | // Initialize hash value for this chunk |
| 78 | A, B, C, D := a0, b0, c0, d0 |
| 79 | |
| 80 | // Main loop |
| 81 | for i := 0; i < 64; i++ { |
| 82 | var F, g uint32 |
| 83 | if i < 16 { |
| 84 | F = (B & C) | ((^B) & D) |
| 85 | g = uint32(i) |
| 86 | } else if i < 32 { |
| 87 | F = (D & B) | ((^D) & C) |
| 88 | g = uint32((5*i + 1) % 16) |
| 89 | } else if i < 48 { |
| 90 | F = B ^ C ^ D |
| 91 | g = uint32((3*i + 5) % 16) |
| 92 | } else { |
| 93 | F = C ^ (B | (^D)) |
| 94 | g = uint32((7 * i) % 16) |
| 95 | } |
| 96 | F = F + A + K[i] + M[g] |
| 97 | A = D |
| 98 | D = C |
| 99 | C = B |
| 100 | B = B + leftRotate(F, s[i]) |
| 101 | } |
| 102 | |
| 103 | // Add this chunk's hash to result so far |
| 104 | a0 += A |
| 105 | b0 += B |
| 106 | c0 += C |
| 107 | d0 += D |
| 108 | } |
| 109 | |
| 110 | // Produce the final hash value (digest) |
| 111 | var digest [16]byte |
| 112 | binary.LittleEndian.PutUint32(digest[0:4], a0) |
| 113 | binary.LittleEndian.PutUint32(digest[4:8], b0) |
| 114 | binary.LittleEndian.PutUint32(digest[8:12], c0) |
| 115 | binary.LittleEndian.PutUint32(digest[12:16], d0) |
| 116 | |
| 117 | return digest |
| 118 | } |