v

Зеркало из https://github.com/vlang/v
Форк
0
/
sha3.v 
360 строк · 9.3 Кб
1
// Copyright (c) 2023 Kim Shrier. All rights reserved.
2
// Use of this source code is governed by an MIT license
3
// that can be found in the LICENSE file.
4
// Package sha3 implements the 512, 384, 256, and 224
5
// bit hash algorithms and the 128 and 256 bit
6
// extended output functions as defined in
7
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf.
8
// Last updated: August 2015
9
module sha3
10

11
import math
12

13
// size_224 is the size, in bytes, of a sha3 sum224 checksum.
14
pub const size_224 = 28
15
// size_256 is the size, in bytes, of a sha3 sum256 checksum.
16
pub const size_256 = 32
17
// size_384 is the size, in bytes, of a sha3 sum384 checksum.
18
pub const size_384 = 48
19
// size_512 is the size, in bytes, of a sha3 sum512 checksum.
20
pub const size_512 = 64
21

22
// rate_224 is the rate, in bytes, absorbed into the sponge on every permutation
23
pub const rate_224 = 144
24
// rate_256 is the rate, in bytes, absorbed into the sponge on every permutation
25
pub const rate_256 = 136
26
// rate_384 is the rate, in bytes, absorbed into the sponge on every permutation
27
pub const rate_384 = 104
28
// rate_512 is the rate, in bytes, absorbed into the sponge on every permutation
29
pub const rate_512 = 72
30

31
// xof_rate_128 is the capacity, in bytes, of a 128 bit extended output function sponge
32
pub const xof_rate_128 = 168
33
// xof_rate_256 is the capacity, in bytes, of a 256 bit extended output function sponge
34
pub const xof_rate_256 = 136
35

36
// the low order pad bits for a hash function
37
const hash_pad = u8(0x06)
38

39
// the low order pad bits for an extended output function
40
const xof_pad = u8(0x1f)
41

42
// new512 initializes the digest structure for a sha3 512 bit hash
43
pub fn new512() !&Digest {
44
	return new_digest(rate_512, size_512)!
45
}
46

47
// new384 initializes the digest structure for a sha3 384 bit hash
48
pub fn new384() !&Digest {
49
	return new_digest(rate_384, size_384)!
50
}
51

52
// new256 initializes the digest structure for a sha3 256 bit hash
53
pub fn new256() !&Digest {
54
	return new_digest(rate_256, size_256)!
55
}
56

57
// new224 initializes the digest structure for a sha3 224 bit hash
58
pub fn new224() !&Digest {
59
	return new_digest(rate_224, size_224)!
60
}
61

62
// new256_xof initializes the digest structure for a sha3 256 bit extended output function
63
pub fn new256xof(output_len int) !&Digest {
64
	return new_xof_digest(xof_rate_256, output_len)!
65
}
66

67
// new128_xof initializes the digest structure for a sha3 128 bit extended output function
68
pub fn new128xof(output_len int) !&Digest {
69
	return new_xof_digest(xof_rate_128, output_len)!
70
}
71

72
struct HashSizeError {
73
	Error
74
	size int
75
}
76

77
fn (err HashSizeError) msg() string {
78
	return 'Hash size ${err.size} must be ${size_224}, ${size_256}, ${size_384}, or ${size_512}'
79
}
80

81
struct AbsorptionRateError {
82
	Error
83
	size int
84
	rate int
85
}
86

87
fn (err AbsorptionRateError) msg() string {
88
	return 'Absorption rate ${err.rate} is not compatible with a hash size of ${err.size}'
89
}
90

91
struct XOFRateError {
92
	Error
93
	rate int
94
}
95

96
fn (err XOFRateError) msg() string {
97
	return 'Extended output rate ${err.rate} must be ${xof_rate_128} or ${xof_rate_256}'
98
}
99

100
struct XOFSizeError {
101
	Error
102
	size int
103
}
104

105
fn (err XOFSizeError) msg() string {
106
	return 'Extended output size ${err.size} must be > 0'
107
}
108

109
struct Digest {
110
	rate       int // the number of bytes absorbed per permutation
111
	suffix     u8  // the domain suffix, 0x06 for hash, 0x1f for extended output
112
	output_len int // the number of bytes to output
113
mut:
114
	input_buffer []u8  // temporary holding buffer for input bytes
115
	s            State // the state of a kaccak-p[1600, 24] sponge
116
}
117

118
// new_digest creates an initialized digest structure based on
119
// the hash size and whether or not you specify a MAC key.
120
//
121
// absorption_rate is the number of bytes to be absorbed into the
122
//     sponge per permutation.
123
//
124
// hash_size - the number if bytes in the generated hash.
125
//     Legal values are 224, 256, 384, and 512.
126
pub fn new_digest(absorption_rate int, hash_size int) !&Digest {
127
	match hash_size {
128
		size_224 {
129
			if absorption_rate != rate_224 {
130
				return AbsorptionRateError{
131
					rate: absorption_rate
132
					size: hash_size
133
				}
134
			}
135
		}
136
		size_256 {
137
			if absorption_rate != rate_256 {
138
				return AbsorptionRateError{
139
					rate: absorption_rate
140
					size: hash_size
141
				}
142
			}
143
		}
144
		size_384 {
145
			if absorption_rate != rate_384 {
146
				return AbsorptionRateError{
147
					rate: absorption_rate
148
					size: hash_size
149
				}
150
			}
151
		}
152
		size_512 {
153
			if absorption_rate != rate_512 {
154
				return AbsorptionRateError{
155
					rate: absorption_rate
156
					size: hash_size
157
				}
158
			}
159
		}
160
		else {
161
			return HashSizeError{
162
				size: hash_size
163
			}
164
		}
165
	}
166

167
	d := Digest{
168
		rate:       absorption_rate
169
		suffix:     hash_pad
170
		output_len: hash_size
171
		s:          State{}
172
	}
173

174
	return &d
175
}
176

177
// new_xof_digest creates an initialized digest structure based on
178
// the absorption rate and how many bytes of output you need
179
//
180
// absorption_rate is the number of bytes to be absorbed into the
181
//     sponge per permutation.  Legal values are xof_rate_128 and
182
//     xof_rate_256.
183
//
184
// hash_size - the number if bytes in the generated hash.
185
//     Legal values are positive integers.
186
pub fn new_xof_digest(absorption_rate int, hash_size int) !&Digest {
187
	match absorption_rate {
188
		xof_rate_128, xof_rate_256 {
189
			if hash_size < 1 {
190
				return XOFSizeError{
191
					size: hash_size
192
				}
193
			}
194
		}
195
		else {
196
			return XOFRateError{
197
				rate: absorption_rate
198
			}
199
		}
200
	}
201

202
	d := Digest{
203
		rate:       absorption_rate
204
		suffix:     xof_pad
205
		output_len: hash_size
206
		s:          State{}
207
	}
208

209
	return &d
210
}
211

212
// write adds bytes to the sponge.
213
//
214
// This is the absorption phase of the computation.
215
pub fn (mut d Digest) write(data []u8) ! {
216
	// if no data is being added to the hash,
217
	// just return
218
	if data.len == 0 {
219
		return
220
	}
221

222
	// absorb the input into the sponge
223
	mut bytes_remaining := unsafe { data[..] }
224

225
	if d.input_buffer.len != 0 {
226
		// see if we can accumulate rate bytes to be absorbed
227
		empty_space := d.rate - d.input_buffer.len
228

229
		if bytes_remaining.len < empty_space {
230
			d.input_buffer << bytes_remaining
231

232
			// we have not accumulated rate bytes yet.
233
			// just return.
234
			return
235
		} else {
236
			// we have enough bytes to add rate bytes to the
237
			// sponge.
238
			d.input_buffer << bytes_remaining[..empty_space]
239
			bytes_remaining = unsafe { bytes_remaining[empty_space..] }
240

241
			// absorb them
242
			d.s.xor_bytes(d.input_buffer[..d.rate], d.rate)
243
			d.s.kaccak_p_1600_24()
244

245
			d.input_buffer = ''.bytes()
246
		}
247
	}
248

249
	// absorb the remaining bytes
250
	for bytes_remaining.len >= d.rate {
251
		d.s.xor_bytes(bytes_remaining[..d.rate], d.rate)
252
		d.s.kaccak_p_1600_24()
253
		bytes_remaining = unsafe { bytes_remaining[d.rate..] }
254
	}
255

256
	if bytes_remaining.len > 0 {
257
		d.input_buffer = bytes_remaining
258
	}
259
}
260

261
// checksum finalizes the hash and returns the generated bytes.
262
pub fn (mut d Digest) checksum() []u8 {
263
	return d.checksum_internal() or { panic(err) }
264
}
265

266
fn (mut d Digest) checksum_internal() ![]u8 {
267
	// pad the last input bytes to have rate bytes
268
	if d.input_buffer.len == d.rate - 1 {
269
		// a single byte pad needs to be handled specially
270
		d.input_buffer << u8(0x80 | d.suffix)
271
	} else {
272
		zero_pads := (d.rate - d.input_buffer.len) - 2
273

274
		// add the first byte of padding
275
		d.input_buffer << d.suffix
276

277
		// add intermediate zero pad bytes
278
		for _ in 0 .. zero_pads {
279
			d.input_buffer << u8(0x00)
280
		}
281

282
		// add the last pad byte
283
		d.input_buffer << u8(0x80)
284
	}
285

286
	d.s.xor_bytes(d.input_buffer[..d.rate], d.rate)
287
	d.s.kaccak_p_1600_24()
288

289
	// absorption is done.  on to squeezing.
290

291
	// We know that we can extract rate bytes from the current
292
	// state.  If the output_len is <= rate, we don't need to
293
	// iterate and can just return the bytes from the current
294
	// state.
295

296
	if d.output_len <= d.rate {
297
		return d.s.to_bytes()[..d.output_len]
298
	}
299

300
	// we need to squeeze the sponge a little harder to get
301
	// longer strings of bytes.
302

303
	mut output_bytes := []u8{cap: d.output_len}
304
	mut remaining_ouput_len := d.output_len
305

306
	for remaining_ouput_len > 0 {
307
		mut byte_len_this_round := math.min[int](remaining_ouput_len, d.rate)
308
		output_bytes << d.s.to_bytes()[..byte_len_this_round]
309

310
		remaining_ouput_len -= byte_len_this_round
311

312
		if remaining_ouput_len > 0 {
313
			d.s.kaccak_p_1600_24()
314
		}
315
	}
316

317
	return output_bytes
318
}
319

320
// sum512 returns the sha3 512 bit checksum of the data.
321
pub fn sum512(data []u8) []u8 {
322
	mut d := new512() or { panic(err) }
323
	d.write(data) or { panic(err) }
324
	return d.checksum_internal() or { panic(err) }
325
}
326

327
// sum384 returns the sha3 384 bit checksum of the data.
328
pub fn sum384(data []u8) []u8 {
329
	mut d := new384() or { panic(err) }
330
	d.write(data) or { panic(err) }
331
	return d.checksum_internal() or { panic(err) }
332
}
333

334
// sum256 returns the sha3 256 bit checksum of the data.
335
pub fn sum256(data []u8) []u8 {
336
	mut d := new256() or { panic(err) }
337
	d.write(data) or { panic(err) }
338
	return d.checksum_internal() or { panic(err) }
339
}
340

341
// sum224 returns the sha3 224 bit checksum of the data.
342
pub fn sum224(data []u8) []u8 {
343
	mut d := new224() or { panic(err) }
344
	d.write(data) or { panic(err) }
345
	return d.checksum_internal() or { panic(err) }
346
}
347

348
// shake256 returns the sha3 shake256 bit extended output
349
pub fn shake256(data []u8, output_len int) []u8 {
350
	mut d := new256xof(output_len) or { panic(err) }
351
	d.write(data) or { panic(err) }
352
	return d.checksum_internal() or { panic(err) }
353
}
354

355
// shake128 returns the sha3 shake128 bit extended output
356
pub fn shake128(data []u8, output_len int) []u8 {
357
	mut d := new128xof(output_len) or { panic(err) }
358
	d.write(data) or { panic(err) }
359
	return d.checksum_internal() or { panic(err) }
360
}
361

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.