blob: 2776c8795c1613e687b15d29380676bbea94e618 [file] [log] [blame]
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// MD5 block step.
// In its own file so that a faster assembly or C version
// can be substituted easily.
package md5
import "crypto/md5"
// table[i] = int((1<<32) * abs(sin(i+1 radians))).
var table = []uint32 {
// round 1
0xd76aa478,
0xe8c7b756,
0x242070db,
0xc1bdceee,
0xf57c0faf,
0x4787c62a,
0xa8304613,
0xfd469501,
0x698098d8,
0x8b44f7af,
0xffff5bb1,
0x895cd7be,
0x6b901122,
0xfd987193,
0xa679438e,
0x49b40821,
// round 2
0xf61e2562,
0xc040b340,
0x265e5a51,
0xe9b6c7aa,
0xd62f105d,
0x2441453,
0xd8a1e681,
0xe7d3fbc8,
0x21e1cde6,
0xc33707d6,
0xf4d50d87,
0x455a14ed,
0xa9e3e905,
0xfcefa3f8,
0x676f02d9,
0x8d2a4c8a,
// round3
0xfffa3942,
0x8771f681,
0x6d9d6122,
0xfde5380c,
0xa4beea44,
0x4bdecfa9,
0xf6bb4b60,
0xbebfbc70,
0x289b7ec6,
0xeaa127fa,
0xd4ef3085,
0x4881d05,
0xd9d4d039,
0xe6db99e5,
0x1fa27cf8,
0xc4ac5665,
// round 4
0xf4292244,
0x432aff97,
0xab9423a7,
0xfc93a039,
0x655b59c3,
0x8f0ccc92,
0xffeff47d,
0x85845dd1,
0x6fa87e4f,
0xfe2ce6e0,
0xa3014314,
0x4e0811a1,
0xf7537e82,
0xbd3af235,
0x2ad7d2bb,
0xeb86d391,
}
var shift1 = []uint { 7, 12, 17, 22 };
var shift2 = []uint { 5, 9, 14, 20 };
var shift3 = []uint { 4, 11, 16, 23 };
var shift4 = []uint { 6, 10, 15, 21 };
func _Block(dig *digest, p []byte) int {
a := dig.s[0];
b := dig.s[1];
c := dig.s[2];
d := dig.s[3];
n := 0;
var X [16]uint32;
for len(p) >= _Chunk {
aa, bb, cc, dd := a, b, c, d;
for i := 0; i < 16; i++ {
j := i*4;
X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24;
}
// If this needs to be made faster in the future,
// the usual trick is to unroll each of these
// loops by a factor of 4; that lets you replace
// the shift[] lookups with constants and,
// with suitable variable renaming in each
// unrolled body, delete the a, b, c, d = d, a, b, c
// (or you can let the optimizer do the renaming).
// Round 1.
for i := 0; i < 16; i++ {
x := i;
t := i;
s := shift1[i%4];
f := ((c ^ d) & b) ^ d;
a += f + X[x] + table[t];
a = a<<s | a>>(32-s);
a += b;
a, b, c, d = d, a, b, c;
}
// Round 2.
for i := 0; i < 16; i++ {
x := (1+5*i)%16;
t := 16+i;
s := shift2[i%4];
g := ((b ^ c) & d) ^ c;
a += g + X[x] + table[t];
a = a<<s | a>>(32-s);
a += b;
a, b, c, d = d, a, b, c;
}
// Round 3.
for i := 0; i < 16; i++ {
x := (5+3*i)%16;
t := 32+i;
s := shift3[i%4];
h := b ^ c ^ d;
a += h + X[x] + table[t];
a = a<<s | a>>(32-s);
a += b;
a, b, c, d = d, a, b, c;
}
// Round 4.
for i := 0; i < 16; i++ {
x := (7*i)%16;
s := shift4[i%4];
t := 48+i;
ii := c ^ (b | ^d);
a += ii + X[x] + table[t];
a = a<<s | a>>(32-s);
a += b;
a, b, c, d = d, a, b, c;
}
a += aa;
b += bb;
c += cc;
d += dd;
p = p[_Chunk:len(p)];
n += _Chunk;
}
dig.s[0] = a;
dig.s[1] = b;
dig.s[2] = c;
dig.s[3] = d;
return n;
}