Go Home Page
The Go Programming Language

Source file src/pkg/crypto/md5/md5block.go

// 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

// 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

        j := 0
        for i := 0; i < 16; i++ {
            X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
            j += 4
        }

        // 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).
        //
        // The index variables are uint so that % by a power
        // of two can be optimized easily by a compiler.

        // Round 1.
        for i := uint(0); i < 16; i++ {
            x := i
            s := shift1[i%4]
            f := ((c ^ d) & b) ^ d
            a += f + X[x] + table[i]
            a = a<<s | a>>(32-s) + b
            a, b, c, d = d, a, b, c
        }

        // Round 2.
        for i := uint(0); i < 16; i++ {
            x := (1 + 5*i) % 16
            s := shift2[i%4]
            g := ((b ^ c) & d) ^ c
            a += g + X[x] + table[i+16]
            a = a<<s | a>>(32-s) + b
            a, b, c, d = d, a, b, c
        }

        // Round 3.
        for i := uint(0); i < 16; i++ {
            x := (5 + 3*i) % 16
            s := shift3[i%4]
            h := b ^ c ^ d
            a += h + X[x] + table[i+32]
            a = a<<s | a>>(32-s) + b
            a, b, c, d = d, a, b, c
        }

        // Round 4.
        for i := uint(0); i < 16; i++ {
            x := (7 * i) % 16
            s := shift4[i%4]
            j := c ^ (b | ^d)
            a += j + X[x] + table[i+48]
            a = a<<s | a>>(32-s) + b
            a, b, c, d = d, a, b, c
        }

        a += aa
        b += bb
        c += cc
        d += dd

        p = p[_Chunk:]
        n += _Chunk
    }

    dig.s[0] = a
    dig.s[1] = b
    dig.s[2] = c
    dig.s[3] = d
    return n
}