github.com/insolar/x-crypto@v0.0.0-20191031140942-75fab8a325f6/md5/gen.go (about) 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 // +build ignore 6 7 // This program generates md5block.go 8 // Invoke as 9 // 10 // go run gen.go [-full] -output md5block.go 11 // 12 // The -full flag causes the generated code to do a full 13 // (16x) unrolling instead of a 4x unrolling. 14 15 package main 16 17 import ( 18 "bytes" 19 "flag" 20 "go/format" 21 "io/ioutil" 22 "log" 23 "strings" 24 "text/template" 25 ) 26 27 var filename = flag.String("output", "md5block.go", "output file name") 28 29 func main() { 30 flag.Parse() 31 32 var buf bytes.Buffer 33 34 t := template.Must(template.New("main").Funcs(funcs).Parse(program)) 35 if err := t.Execute(&buf, data); err != nil { 36 log.Fatal(err) 37 } 38 39 data, err := format.Source(buf.Bytes()) 40 if err != nil { 41 log.Fatal(err) 42 } 43 err = ioutil.WriteFile(*filename, data, 0644) 44 if err != nil { 45 log.Fatal(err) 46 } 47 } 48 49 type Data struct { 50 a, b, c, d string 51 Shift1 []int 52 Shift2 []int 53 Shift3 []int 54 Shift4 []int 55 Table1 []uint32 56 Table2 []uint32 57 Table3 []uint32 58 Table4 []uint32 59 Full bool 60 } 61 62 var funcs = template.FuncMap{ 63 "dup": dup, 64 "relabel": relabel, 65 "rotate": rotate, 66 } 67 68 func dup(count int, x []int) []int { 69 var out []int 70 for i := 0; i < count; i++ { 71 out = append(out, x...) 72 } 73 return out 74 } 75 76 func relabel(s string) string { 77 return strings.NewReplacer("a", data.a, "b", data.b, "c", data.c, "d", data.d).Replace(s) 78 } 79 80 func rotate() string { 81 data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c 82 return "" // no output 83 } 84 85 func init() { 86 flag.BoolVar(&data.Full, "full", false, "complete unrolling") 87 } 88 89 var data = Data{ 90 a: "a", 91 b: "b", 92 c: "c", 93 d: "d", 94 Shift1: []int{7, 12, 17, 22}, 95 Shift2: []int{5, 9, 14, 20}, 96 Shift3: []int{4, 11, 16, 23}, 97 Shift4: []int{6, 10, 15, 21}, 98 99 // table[i] = int((1<<32) * abs(sin(i+1 radians))). 100 Table1: []uint32{ 101 // round 1 102 0xd76aa478, 103 0xe8c7b756, 104 0x242070db, 105 0xc1bdceee, 106 0xf57c0faf, 107 0x4787c62a, 108 0xa8304613, 109 0xfd469501, 110 0x698098d8, 111 0x8b44f7af, 112 0xffff5bb1, 113 0x895cd7be, 114 0x6b901122, 115 0xfd987193, 116 0xa679438e, 117 0x49b40821, 118 }, 119 Table2: []uint32{ 120 // round 2 121 0xf61e2562, 122 0xc040b340, 123 0x265e5a51, 124 0xe9b6c7aa, 125 0xd62f105d, 126 0x2441453, 127 0xd8a1e681, 128 0xe7d3fbc8, 129 0x21e1cde6, 130 0xc33707d6, 131 0xf4d50d87, 132 0x455a14ed, 133 0xa9e3e905, 134 0xfcefa3f8, 135 0x676f02d9, 136 0x8d2a4c8a, 137 }, 138 Table3: []uint32{ 139 // round3 140 0xfffa3942, 141 0x8771f681, 142 0x6d9d6122, 143 0xfde5380c, 144 0xa4beea44, 145 0x4bdecfa9, 146 0xf6bb4b60, 147 0xbebfbc70, 148 0x289b7ec6, 149 0xeaa127fa, 150 0xd4ef3085, 151 0x4881d05, 152 0xd9d4d039, 153 0xe6db99e5, 154 0x1fa27cf8, 155 0xc4ac5665, 156 }, 157 Table4: []uint32{ 158 // round 4 159 0xf4292244, 160 0x432aff97, 161 0xab9423a7, 162 0xfc93a039, 163 0x655b59c3, 164 0x8f0ccc92, 165 0xffeff47d, 166 0x85845dd1, 167 0x6fa87e4f, 168 0xfe2ce6e0, 169 0xa3014314, 170 0x4e0811a1, 171 0xf7537e82, 172 0xbd3af235, 173 0x2ad7d2bb, 174 0xeb86d391, 175 }, 176 } 177 178 var program = `// Copyright 2013 The Go Authors. All rights reserved. 179 // Use of this source code is governed by a BSD-style 180 // license that can be found in the LICENSE file. 181 182 // Code generated by go run gen.go{{if .Full}} -full{{end}} -output md5block.go; DO NOT EDIT. 183 184 package md5 185 186 import ( 187 "unsafe" 188 "runtime" 189 ) 190 191 {{if not .Full}} 192 var t1 = [...]uint32{ 193 {{range .Table1}}{{printf "\t%#x,\n" .}}{{end}} 194 } 195 196 var t2 = [...]uint32{ 197 {{range .Table2}}{{printf "\t%#x,\n" .}}{{end}} 198 } 199 200 var t3 = [...]uint32{ 201 {{range .Table3}}{{printf "\t%#x,\n" .}}{{end}} 202 } 203 204 var t4 = [...]uint32{ 205 {{range .Table4}}{{printf "\t%#x,\n" .}}{{end}} 206 } 207 {{end}} 208 209 const x86 = runtime.GOARCH == "amd64" || runtime.GOARCH == "386" 210 211 var littleEndian bool 212 213 func init() { 214 x := uint32(0x04030201) 215 y := [4]byte{0x1, 0x2, 0x3, 0x4} 216 littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y 217 } 218 219 func blockGeneric(dig *digest, p []byte) { 220 a := dig.s[0] 221 b := dig.s[1] 222 c := dig.s[2] 223 d := dig.s[3] 224 var X *[16]uint32 225 var xbuf [16]uint32 226 for len(p) >= chunk { 227 aa, bb, cc, dd := a, b, c, d 228 229 // This is a constant condition - it is not evaluated on each iteration. 230 if x86 { 231 // MD5 was designed so that x86 processors can just iterate 232 // over the block data directly as uint32s, and we generate 233 // less code and run 1.3x faster if we take advantage of that. 234 // My apologies. 235 X = (*[16]uint32)(unsafe.Pointer(&p[0])) 236 } else if littleEndian && uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { 237 X = (*[16]uint32)(unsafe.Pointer(&p[0])) 238 } else { 239 X = &xbuf 240 j := 0 241 for i := 0; i < 16; i++ { 242 X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 243 j += 4 244 } 245 } 246 247 {{if .Full}} 248 // Round 1. 249 {{range $i, $s := dup 4 .Shift1}} 250 {{index $.Table1 $i | printf "a += (((c^d)&b)^d) + X[%d] + %d" $i | relabel}} 251 {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}} 252 {{rotate}} 253 {{end}} 254 255 // Round 2. 256 {{range $i, $s := dup 4 .Shift2}} 257 {{index $.Table2 $i | printf "a += (((b^c)&d)^c) + X[(1+5*%d)&15] + %d" $i | relabel}} 258 {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}} 259 {{rotate}} 260 {{end}} 261 262 // Round 3. 263 {{range $i, $s := dup 4 .Shift3}} 264 {{index $.Table3 $i | printf "a += (b^c^d) + X[(5+3*%d)&15] + %d" $i | relabel}} 265 {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}} 266 {{rotate}} 267 {{end}} 268 269 // Round 4. 270 {{range $i, $s := dup 4 .Shift4}} 271 {{index $.Table4 $i | printf "a += (c^(b|^d)) + X[(7*%d)&15] + %d" $i | relabel}} 272 {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}} 273 {{rotate}} 274 {{end}} 275 {{else}} 276 // Round 1. 277 for i := uint(0); i < 16; { 278 {{range $s := .Shift1}} 279 {{printf "a += (((c^d)&b)^d) + X[i&15] + t1[i&15]" | relabel}} 280 {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}} 281 i++ 282 {{rotate}} 283 {{end}} 284 } 285 286 // Round 2. 287 for i := uint(0); i < 16; { 288 {{range $s := .Shift2}} 289 {{printf "a += (((b^c)&d)^c) + X[(1+5*i)&15] + t2[i&15]" | relabel}} 290 {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}} 291 i++ 292 {{rotate}} 293 {{end}} 294 } 295 296 // Round 3. 297 for i := uint(0); i < 16; { 298 {{range $s := .Shift3}} 299 {{printf "a += (b^c^d) + X[(5+3*i)&15] + t3[i&15]" | relabel}} 300 {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}} 301 i++ 302 {{rotate}} 303 {{end}} 304 } 305 306 // Round 4. 307 for i := uint(0); i < 16; { 308 {{range $s := .Shift4}} 309 {{printf "a += (c^(b|^d)) + X[(7*i)&15] + t4[i&15]" | relabel}} 310 {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}} 311 i++ 312 {{rotate}} 313 {{end}} 314 } 315 {{end}} 316 317 a += aa 318 b += bb 319 c += cc 320 d += dd 321 322 p = p[chunk:] 323 } 324 325 dig.s[0] = a 326 dig.s[1] = b 327 dig.s[2] = c 328 dig.s[3] = d 329 } 330 `