tuplehash.odin 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. /*
  2. package tuplehash implements the TupleHash and TupleHashXOF algorithms.
  3. See:
  4. - https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf
  5. */
  6. package tuplehash
  7. import "../_sha3"
  8. // Context is a TupleHash or TupleHashXOF instance.
  9. Context :: distinct _sha3.Context
  10. // init_128 initializes a Context for TupleHash128 or TupleHashXOF128.
  11. init_128 :: proc(ctx: ^Context, domain_sep: []byte) {
  12. _sha3.init_cshake(transmute(^_sha3.Context)(ctx), N_TUPLEHASH, domain_sep, 128)
  13. }
  14. // init_256 initializes a Context for TupleHash256 or TupleHashXOF256.
  15. init_256 :: proc(ctx: ^Context, domain_sep: []byte) {
  16. _sha3.init_cshake(transmute(^_sha3.Context)(ctx), N_TUPLEHASH, domain_sep, 256)
  17. }
  18. // write_element writes a tuple element into the TupleHash or TupleHashXOF
  19. // instance. This MUST not be called after any reads have been done, and
  20. // any attempts to do so will panic.
  21. write_element :: proc(ctx: ^Context, data: []byte) {
  22. _, _ = _sha3.encode_string(transmute(^_sha3.Context)(ctx), data)
  23. }
  24. // final finalizes the Context, writes the digest to hash, and calls
  25. // reset on the Context.
  26. //
  27. // Iff finalize_clone is set, final will work on a copy of the Context,
  28. // which is useful for for calculating rolling digests.
  29. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
  30. _sha3.final_cshake(transmute(^_sha3.Context)(ctx), hash, finalize_clone)
  31. }
  32. // read reads output from the TupleHashXOF instance. There is no practical
  33. // upper limit to the amount of data that can be read from TupleHashXOF.
  34. // After read has been called one or more times, further calls to
  35. // write_element will panic.
  36. read :: proc(ctx: ^Context, dst: []byte) {
  37. ctx_ := transmute(^_sha3.Context)(ctx)
  38. if !ctx.is_finalized {
  39. _sha3.encode_byte_len(ctx_, 0, false) // right_encode
  40. _sha3.shake_xof(ctx_)
  41. }
  42. _sha3.shake_out(ctx_, dst)
  43. }
  44. // clone clones the Context other into ctx.
  45. clone :: proc(ctx, other: ^Context) {
  46. _sha3.clone(transmute(^_sha3.Context)(ctx), transmute(^_sha3.Context)(other))
  47. }
  48. // reset sanitizes the Context. The Context must be re-initialized to
  49. // be used again.
  50. reset :: proc(ctx: ^Context) {
  51. _sha3.reset(transmute(^_sha3.Context)(ctx))
  52. }
  53. @(private)
  54. N_TUPLEHASH := []byte{'T', 'u', 'p', 'l', 'e', 'H', 'a', 's', 'h'}