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 }