core/crypto/shake: SHAKE is an XOF, not a hash

This commit is contained in:
Yawning Angel
2024-02-07 00:37:18 +09:00
parent 1d151c4c92
commit b02b85d242
4 changed files with 107 additions and 91 deletions
-27
View File
@@ -4,7 +4,6 @@ import "core:crypto/blake2b"
import "core:crypto/blake2s"
import "core:crypto/sha2"
import "core:crypto/sha3"
import "core:crypto/shake"
import "core:crypto/sm3"
import "core:crypto/legacy/keccak"
import "core:crypto/legacy/md5"
@@ -26,8 +25,6 @@ Algorithm :: enum {
SHA3_256,
SHA3_384,
SHA3_512,
SHAKE_128,
SHAKE_256,
SM3,
Legacy_KECCAK_224,
Legacy_KECCAK_256,
@@ -51,8 +48,6 @@ ALGORITHM_NAMES := [Algorithm]string {
.SHA3_256 = "SHA3-256",
.SHA3_384 = "SHA3-384",
.SHA3_512 = "SHA3-512",
.SHAKE_128 = "SHAKE-128",
.SHAKE_256 = "SHAKE-256",
.SM3 = "SM3",
.Legacy_KECCAK_224 = "Keccak-224",
.Legacy_KECCAK_256 = "Keccak-256",
@@ -76,8 +71,6 @@ DIGEST_SIZES := [Algorithm]int {
.SHA3_256 = sha3.DIGEST_SIZE_256,
.SHA3_384 = sha3.DIGEST_SIZE_384,
.SHA3_512 = sha3.DIGEST_SIZE_512,
.SHAKE_128 = shake.DIGEST_SIZE_128,
.SHAKE_256 = shake.DIGEST_SIZE_256,
.SM3 = sm3.DIGEST_SIZE,
.Legacy_KECCAK_224 = keccak.DIGEST_SIZE_224,
.Legacy_KECCAK_256 = keccak.DIGEST_SIZE_256,
@@ -96,7 +89,6 @@ Context :: struct {
^sha2.Context_256,
^sha2.Context_512,
^sha3.Context,
^shake.Context,
^sm3.Context,
^keccak.Context,
^md5.Context,
@@ -159,14 +151,6 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, allocator := context.allocator
impl := new(sha3.Context, allocator)
sha3.init_512(impl)
ctx._impl = impl
case .SHAKE_128:
impl := new(shake.Context, allocator)
shake.init_128(impl)
ctx._impl = impl
case .SHAKE_256:
impl := new(shake.Context, allocator)
shake.init_256(impl)
ctx._impl = impl
case .SM3:
impl := new(sm3.Context, allocator)
sm3.init(impl)
@@ -218,8 +202,6 @@ update :: proc(ctx: ^Context, data: []byte) {
sha2.update(impl, data)
case ^sha3.Context:
sha3.update(impl, data)
case ^shake.Context:
shake.update(impl, data)
case ^sm3.Context:
sm3.update(impl, data)
case ^keccak.Context:
@@ -250,8 +232,6 @@ final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
sha2.final(impl, hash, finalize_clone)
case ^sha3.Context:
sha3.final(impl, hash, finalize_clone)
case ^shake.Context:
shake.final(impl, hash, finalize_clone)
case ^sm3.Context:
sm3.final(impl, hash, finalize_clone)
case ^keccak.Context:
@@ -304,10 +284,6 @@ clone :: proc(ctx, other: ^Context, allocator := context.allocator) {
impl := new(sha3.Context, allocator)
sha3.clone(impl, src_impl)
ctx._impl = impl
case ^shake.Context:
impl := new(shake.Context, allocator)
shake.clone(impl, src_impl)
ctx._impl = impl
case ^sm3.Context:
impl := new(sm3.Context, allocator)
sm3.clone(impl, src_impl)
@@ -348,9 +324,6 @@ reset :: proc(ctx: ^Context) {
case ^sha3.Context:
sha3.reset(impl)
free(impl, ctx._allocator)
case ^shake.Context:
shake.reset(impl)
free(impl, ctx._allocator)
case ^sm3.Context:
sm3.reset(impl)
free(impl, ctx._allocator)
+28 -33
View File
@@ -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))
}