github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/crypto/sha3/sha3.go (about)

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