1// Copyright 2012 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5//go:build ignore 6// +build ignore 7 8// This program generates md5block.go 9// Invoke as 10// 11// go run gen.go -output md5block.go 12 13package main 14 15import ( 16 "bytes" 17 "flag" 18 "go/format" 19 "log" 20 "os" 21 "strings" 22 "text/template" 23) 24 25var filename = flag.String("output", "md5block.go", "output file name") 26 27func main() { 28 flag.Parse() 29 30 var buf bytes.Buffer 31 32 t := template.Must(template.New("main").Funcs(funcs).Parse(program)) 33 if err := t.Execute(&buf, data); err != nil { 34 log.Fatal(err) 35 } 36 37 data, err := format.Source(buf.Bytes()) 38 if err != nil { 39 log.Fatal(err) 40 } 41 err = os.WriteFile(*filename, data, 0644) 42 if err != nil { 43 log.Fatal(err) 44 } 45} 46 47type Data struct { 48 a, b, c, d string 49 Shift1 []int 50 Shift2 []int 51 Shift3 []int 52 Shift4 []int 53 Table1 []uint32 54 Table2 []uint32 55 Table3 []uint32 56 Table4 []uint32 57} 58 59var funcs = template.FuncMap{ 60 "dup": dup, 61 "relabel": relabel, 62 "rotate": rotate, 63 "idx": idx, 64 "seq": seq, 65} 66 67func dup(count int, x []int) []int { 68 var out []int 69 for i := 0; i < count; i++ { 70 out = append(out, x...) 71 } 72 return out 73} 74 75func relabel(s string) string { 76 return strings.NewReplacer("arg0", data.a, "arg1", data.b, "arg2", data.c, "arg3", data.d).Replace(s) 77} 78 79func rotate() string { 80 data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c 81 return "" // no output 82} 83 84func idx(round, index int) int { 85 v := 0 86 switch round { 87 case 1: 88 v = index 89 case 2: 90 v = (1 + 5*index) & 15 91 case 3: 92 v = (5 + 3*index) & 15 93 case 4: 94 v = (7 * index) & 15 95 } 96 return v 97} 98 99func seq(i int) []int { 100 s := make([]int, i) 101 for i := range s { 102 s[i] = i 103 } 104 return s 105} 106 107var data = Data{ 108 a: "a", 109 b: "b", 110 c: "c", 111 d: "d", 112 Shift1: []int{7, 12, 17, 22}, 113 Shift2: []int{5, 9, 14, 20}, 114 Shift3: []int{4, 11, 16, 23}, 115 Shift4: []int{6, 10, 15, 21}, 116 117 // table[i] = int((1<<32) * abs(sin(i+1 radians))). 118 Table1: []uint32{ 119 // round 1 120 0xd76aa478, 121 0xe8c7b756, 122 0x242070db, 123 0xc1bdceee, 124 0xf57c0faf, 125 0x4787c62a, 126 0xa8304613, 127 0xfd469501, 128 0x698098d8, 129 0x8b44f7af, 130 0xffff5bb1, 131 0x895cd7be, 132 0x6b901122, 133 0xfd987193, 134 0xa679438e, 135 0x49b40821, 136 }, 137 Table2: []uint32{ 138 // round 2 139 0xf61e2562, 140 0xc040b340, 141 0x265e5a51, 142 0xe9b6c7aa, 143 0xd62f105d, 144 0x2441453, 145 0xd8a1e681, 146 0xe7d3fbc8, 147 0x21e1cde6, 148 0xc33707d6, 149 0xf4d50d87, 150 0x455a14ed, 151 0xa9e3e905, 152 0xfcefa3f8, 153 0x676f02d9, 154 0x8d2a4c8a, 155 }, 156 Table3: []uint32{ 157 // round3 158 0xfffa3942, 159 0x8771f681, 160 0x6d9d6122, 161 0xfde5380c, 162 0xa4beea44, 163 0x4bdecfa9, 164 0xf6bb4b60, 165 0xbebfbc70, 166 0x289b7ec6, 167 0xeaa127fa, 168 0xd4ef3085, 169 0x4881d05, 170 0xd9d4d039, 171 0xe6db99e5, 172 0x1fa27cf8, 173 0xc4ac5665, 174 }, 175 Table4: []uint32{ 176 // round 4 177 0xf4292244, 178 0x432aff97, 179 0xab9423a7, 180 0xfc93a039, 181 0x655b59c3, 182 0x8f0ccc92, 183 0xffeff47d, 184 0x85845dd1, 185 0x6fa87e4f, 186 0xfe2ce6e0, 187 0xa3014314, 188 0x4e0811a1, 189 0xf7537e82, 190 0xbd3af235, 191 0x2ad7d2bb, 192 0xeb86d391, 193 }, 194} 195 196var program = `// Copyright 2013 The Go Authors. All rights reserved. 197// Use of this source code is governed by a BSD-style 198// license that can be found in the LICENSE file. 199 200// Code generated by go run gen.go -output md5block.go; DO NOT EDIT. 201 202package md5 203 204import ( 205 "encoding/binary" 206 "math/bits" 207) 208 209func blockGeneric(dig *digest, p []byte) { 210 // load state 211 a, b, c, d := dig.s[0], dig.s[1], dig.s[2], dig.s[3] 212 213 for i := 0; i <= len(p)-BlockSize; i += BlockSize { 214 // eliminate bounds checks on p 215 q := p[i:] 216 q = q[:BlockSize:BlockSize] 217 218 // save current state 219 aa, bb, cc, dd := a, b, c, d 220 221 // load input block 222 {{range $i := seq 16 -}} 223 {{printf "x%x := binary.LittleEndian.Uint32(q[4*%#x:])" $i $i}} 224 {{end}} 225 226 // round 1 227 {{range $i, $s := dup 4 .Shift1 -}} 228 {{printf "arg0 = arg1 + bits.RotateLeft32((((arg2^arg3)&arg1)^arg3)+arg0+x%x+%#08x, %d)" (idx 1 $i) (index $.Table1 $i) $s | relabel}} 229 {{rotate -}} 230 {{end}} 231 232 // round 2 233 {{range $i, $s := dup 4 .Shift2 -}} 234 {{printf "arg0 = arg1 + bits.RotateLeft32((((arg1^arg2)&arg3)^arg2)+arg0+x%x+%#08x, %d)" (idx 2 $i) (index $.Table2 $i) $s | relabel}} 235 {{rotate -}} 236 {{end}} 237 238 // round 3 239 {{range $i, $s := dup 4 .Shift3 -}} 240 {{printf "arg0 = arg1 + bits.RotateLeft32((arg1^arg2^arg3)+arg0+x%x+%#08x, %d)" (idx 3 $i) (index $.Table3 $i) $s | relabel}} 241 {{rotate -}} 242 {{end}} 243 244 // round 4 245 {{range $i, $s := dup 4 .Shift4 -}} 246 {{printf "arg0 = arg1 + bits.RotateLeft32((arg2^(arg1|^arg3))+arg0+x%x+%#08x, %d)" (idx 4 $i) (index $.Table4 $i) $s | relabel}} 247 {{rotate -}} 248 {{end}} 249 250 // add saved state 251 a += aa 252 b += bb 253 c += cc 254 d += dd 255 } 256 257 // save state 258 dig.s[0], dig.s[1], dig.s[2], dig.s[3] = a, b, c, d 259} 260` 261