gen.mx raw

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