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