mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
core/crypto/shake: SHAKE is an XOF, not a hash
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
/*
|
||||
package shake implements the SHAKE XOF algorithm family.
|
||||
|
||||
The SHA3 hash algorithm can be found in the crypto/sha3.
|
||||
|
||||
See:
|
||||
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf
|
||||
*/
|
||||
package shake
|
||||
|
||||
/*
|
||||
@@ -6,30 +14,22 @@ package shake
|
||||
|
||||
List of contributors:
|
||||
zhibog, dotbmp: Initial implementation.
|
||||
|
||||
Interface for the SHAKE XOF. The SHA3 hashing algorithm can be found
|
||||
in package sha3.
|
||||
|
||||
TODO:
|
||||
- This should provide an incremental squeeze interface.
|
||||
- DIGEST_SIZE is inaccurate, SHAKE-128 and SHAKE-256 are security
|
||||
strengths.
|
||||
*/
|
||||
|
||||
import "../_sha3"
|
||||
|
||||
DIGEST_SIZE_128 :: 16
|
||||
DIGEST_SIZE_256 :: 32
|
||||
|
||||
// Context is a SHAKE128 or SHAKE256 instance.
|
||||
Context :: distinct _sha3.Context
|
||||
|
||||
// init_128 initializes a Context for SHAKE128.
|
||||
init_128 :: proc(ctx: ^Context) {
|
||||
ctx.mdlen = DIGEST_SIZE_128
|
||||
ctx.mdlen = 128 / 8
|
||||
_init(ctx)
|
||||
}
|
||||
|
||||
// init_256 initializes a Context for SHAKE256.
|
||||
init_256 :: proc(ctx: ^Context) {
|
||||
ctx.mdlen = DIGEST_SIZE_256
|
||||
ctx.mdlen = 256 / 8
|
||||
_init(ctx)
|
||||
}
|
||||
|
||||
@@ -38,36 +38,31 @@ _init :: proc(ctx: ^Context) {
|
||||
_sha3.init(transmute(^_sha3.Context)(ctx))
|
||||
}
|
||||
|
||||
update :: proc(ctx: ^Context, data: []byte) {
|
||||
// write writes more data into the SHAKE instance. This MUST not be called
|
||||
// after any reads have been done, and attempts to do so will panic.
|
||||
write :: proc(ctx: ^Context, data: []byte) {
|
||||
_sha3.update(transmute(^_sha3.Context)(ctx), data)
|
||||
}
|
||||
|
||||
final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
|
||||
// Rolling digest support is handled here instead of in the generic
|
||||
// _sha3 package as SHAKE is more of an XOF than a hash, so the
|
||||
// standard notion of "final", doesn't really exist when you can
|
||||
// squeeze an unlimited amount of data.
|
||||
//
|
||||
// TODO/yawning: Strongly consider getting rid of this and rigidly
|
||||
// defining SHAKE as an XOF.
|
||||
|
||||
ctx := ctx
|
||||
if finalize_clone {
|
||||
tmp_ctx: Context
|
||||
clone(&tmp_ctx, ctx)
|
||||
ctx = &tmp_ctx
|
||||
}
|
||||
defer(reset(ctx))
|
||||
|
||||
// read reads output from the SHAKE instance. There is no practical upper
|
||||
// limit to the amount of data that can be read from SHAKE. After read has
|
||||
// been called one or more times, further calls to write will panic.
|
||||
read :: proc(ctx: ^Context, dst: []byte) {
|
||||
ctx_ := transmute(^_sha3.Context)(ctx)
|
||||
_sha3.shake_xof(ctx_)
|
||||
_sha3.shake_out(ctx_, hash[:])
|
||||
if !ctx.is_finalized {
|
||||
_sha3.shake_xof(ctx_)
|
||||
}
|
||||
|
||||
_sha3.shake_out(ctx_, dst)
|
||||
}
|
||||
|
||||
// clone clones the Context other into ctx.
|
||||
clone :: proc(ctx, other: ^Context) {
|
||||
_sha3.clone(transmute(^_sha3.Context)(ctx), transmute(^_sha3.Context)(other))
|
||||
}
|
||||
|
||||
// reset sanitizes the Context. The Context must be re-initialized to
|
||||
// be used again.
|
||||
reset :: proc(ctx: ^Context) {
|
||||
_sha3.reset(transmute(^_sha3.Context)(ctx))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user