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