github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/crypto/sha3/sha3.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:37</date>
    10  //</624342628225257472>
    11  
    12  //版权所有2014 Go作者。版权所有。
    13  //此源代码的使用受BSD样式的控制
    14  //可以在许可文件中找到的许可证。
    15  
    16  package sha3
    17  
    18  //sponge direction表示字节在海绵中流动的方向。
    19  type spongeDirection int
    20  
    21  const (
    22  //海绵吸收表示海绵吸收输入。
    23  	spongeAbsorbing spongeDirection = iota
    24  //海绵挤压表示海绵被挤压。
    25  	spongeSqueezing
    26  )
    27  
    28  const (
    29  //maxRate is the maximum size of the internal buffer. 沙克-256
    30  //目前需要最大的缓冲区。
    31  	maxRate = 168
    32  )
    33  
    34  type state struct {
    35  //普通海绵组件。
    36  a    [25]uint64 //哈希的主状态
    37  buf  []byte     //指向存储区
    38  rate int        //要使用的状态字节数
    39  
    40  //dsbyte包含“域分隔”位和
    41  //填充物。Sections 6.1 and 6.2 of [1] separate the outputs of the
    42  //sha-3和通过向消息附加位串来震动函数。
    43  //使用一个小的endian位排序约定,这些是sha-3的“01”
    44  //震动为“1111”,或分别为00000010B和000001111B。然后
    45  //第5.1节中的填充规则用于将消息填充到多个
    46  //速率,包括添加“1”位、零位或更多“0”位,以及
    47  //最后一个“1”位。我们将填充的第一个“1”位合并为dsbyte,
    48  //给出00000110B(0x06)和00011111B(0x1F)。
    49  //[1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
    50  //“FIPS 202草案:SHA-3标准:基于排列的哈希和
    51  //可扩展输出功能(2014年5月)
    52  	dsbyte  byte
    53  	storage [maxRate]byte
    54  
    55  //具体到sha-3和震动。
    56  outputLen int             //默认输出大小(字节)
    57  state     spongeDirection //海绵是吸收还是挤压
    58  }
    59  
    60  //blocksize返回此哈希函数的海绵速率。
    61  func (d *state) BlockSize() int { return d.rate }
    62  
    63  //大小返回哈希函数的输出大小为字节。
    64  func (d *state) Size() int { return d.outputLen }
    65  
    66  //重置通过归零海绵状态清除内部状态,并且
    67  //字节缓冲区,并将sponce.state设置为absorption。
    68  func (d *state) Reset() {
    69  //使排列状态归零。
    70  	for i := range d.a {
    71  		d.a[i] = 0
    72  	}
    73  	d.state = spongeAbsorbing
    74  	d.buf = d.storage[:0]
    75  }
    76  
    77  func (d *state) clone() *state {
    78  	ret := *d
    79  	if ret.state == spongeAbsorbing {
    80  		ret.buf = ret.storage[:len(ret.buf)]
    81  	} else {
    82  		ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate]
    83  	}
    84  
    85  	return &ret
    86  }
    87  
    88  //Permute采用KECCAKF-1600排列。它处理
    89  //任何输入输出缓冲。
    90  func (d *state) permute() {
    91  	switch d.state {
    92  	case spongeAbsorbing:
    93  //如果我们正在吸收,我们需要将输入xor转换成状态
    94  //在应用排列之前。
    95  		xorIn(d, d.buf)
    96  		d.buf = d.storage[:0]
    97  		keccakF1600(&d.a)
    98  	case spongeSqueezing:
    99  //如果我们在挤压,我们需要在挤压前涂上置换素。
   100  //复制更多输出。
   101  		keccakF1600(&d.a)
   102  		d.buf = d.storage[:d.rate]
   103  		copyOut(d, d.buf)
   104  	}
   105  }
   106  
   107  //PAD在dsbyte中附加域分隔位,应用
   108  //多比特率10..1填充规则,并排列状态。
   109  func (d *state) padAndPermute(dsbyte byte) {
   110  	if d.buf == nil {
   111  		d.buf = d.storage[:0]
   112  	}
   113  //具有此实例的域分隔位的PAD。我们知道有
   114  //d.buf中至少有一个字节的空间,因为如果空间已满,
   115  //会叫珀穆特清空它。dsbyte还包含
   116  //第一位是填充。请参见state结构中的注释。
   117  	d.buf = append(d.buf, dsbyte)
   118  	zerosStart := len(d.buf)
   119  	d.buf = d.storage[:d.rate]
   120  	for i := zerosStart; i < d.rate; i++ {
   121  		d.buf[i] = 0
   122  	}
   123  //这会为填充添加最后一位。因为这样
   124  //位从LSB向上编号,最后一位是
   125  //最后一个字节。
   126  	d.buf[d.rate-1] ^= 0x80
   127  //应用排列
   128  	d.permute()
   129  	d.state = spongeSqueezing
   130  	d.buf = d.storage[:d.rate]
   131  	copyOut(d, d.buf)
   132  }
   133  
   134  //写将吸收更多的数据进入散列状态。它会产生一个错误
   135  //如果在写入之后有更多的数据写入shakehash
   136  func (d *state) Write(p []byte) (written int, err error) {
   137  	if d.state != spongeAbsorbing {
   138  		panic("sha3: write to sponge after read")
   139  	}
   140  	if d.buf == nil {
   141  		d.buf = d.storage[:0]
   142  	}
   143  	written = len(p)
   144  
   145  	for len(p) > 0 {
   146  		if len(d.buf) == 0 && len(p) >= d.rate {
   147  //快速路径;吸收输入的完整“速率”字节并应用排列。
   148  			xorIn(d, p[:d.rate])
   149  			p = p[d.rate:]
   150  			keccakF1600(&d.a)
   151  		} else {
   152  //慢路径;缓冲输入,直到我们可以填充海绵,然后将其XOR。
   153  			todo := d.rate - len(d.buf)
   154  			if todo > len(p) {
   155  				todo = len(p)
   156  			}
   157  			d.buf = append(d.buf, p[:todo]...)
   158  			p = p[todo:]
   159  
   160  //If the sponge is full, apply the permutation.
   161  			if len(d.buf) == d.rate {
   162  				d.permute()
   163  			}
   164  		}
   165  	}
   166  
   167  	return
   168  }
   169  
   170  //read挤压海绵中任意数量的字节。
   171  func (d *state) Read(out []byte) (n int, err error) {
   172  //If we're still absorbing, pad and apply the permutation.
   173  	if d.state == spongeAbsorbing {
   174  		d.padAndPermute(d.dsbyte)
   175  	}
   176  
   177  	n = len(out)
   178  
   179  //现在,挤压一下。
   180  	for len(out) > 0 {
   181  		n := copy(out, d.buf)
   182  		d.buf = d.buf[n:]
   183  		out = out[n:]
   184  
   185  //如果我们把海绵挤干了,就按顺序排列。
   186  		if len(d.buf) == 0 {
   187  			d.permute()
   188  		}
   189  	}
   190  
   191  	return
   192  }
   193  
   194  //Sum applies padding to the hash state and then squeezes out the desired
   195  //输出字节数。
   196  func (d *state) Sum(in []byte) []byte {
   197  //复制原始哈希,以便调用方可以继续写入
   198  //求和。
   199  	dup := d.clone()
   200  	hash := make([]byte, dup.outputLen)
   201  	dup.Read(hash)
   202  	return append(in, hash...)
   203  }
   204