Source file src/crypto/md5/gen.go

Documentation: crypto/md5

     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 -output md5block.go
    11  
    12  package main
    13  
    14  import (
    15  	"bytes"
    16  	"flag"
    17  	"go/format"
    18  	"io/ioutil"
    19  	"log"
    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 = ioutil.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  `
   260  

View as plain text