diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index e746c2bd..007317f8 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -37,10 +37,10 @@ impl FlatEmbed { #[cfg(feature = "bellman")] FlatEmbed::Sha256Round => Signature::new() .inputs(vec![ - Type::array(Type::FieldElement, 512), - Type::array(Type::FieldElement, 256), + Type::array(Type::Boolean, 512), + Type::array(Type::Boolean, 256), ]) - .outputs(vec![Type::array(Type::FieldElement, 256)]), + .outputs(vec![Type::array(Type::Boolean, 256)]), FlatEmbed::Unpack(bitwidth) => Signature::new() .inputs(vec![Type::FieldElement]) .outputs(vec![Type::array(Type::Boolean, *bitwidth)]), @@ -374,7 +374,7 @@ mod tests { let compiled = sha256_round::(); // function should have 768 inputs - assert_eq!(compiled.arguments.len(), 768,); + assert_eq!(compiled.arguments.len(), 768); // function should return 256 values assert_eq!( @@ -435,8 +435,9 @@ mod tests { }; let input = (0..512) - .map(|_| Bn128Field::from(0)) - .chain((0..256).map(|_| Bn128Field::from(1))) + .map(|_| 0) + .chain((0..256).map(|_| 1)) + .map(|i| Bn128Field::from(i)) .collect(); let interpreter = Interpreter::default(); diff --git a/zokrates_core/src/static_analysis/inline.rs b/zokrates_core/src/static_analysis/inline.rs index 889f4646..8d91290c 100644 --- a/zokrates_core/src/static_analysis/inline.rs +++ b/zokrates_core/src/static_analysis/inline.rs @@ -100,6 +100,14 @@ impl<'ast, T: Field> Inliner<'ast, T> { // inline all calls in the main function, recursively let main = inliner.fold_function_symbol(main); + cfg_if::cfg_if! { + if #[cfg(feature = "bellman")] { + // define a function in the main module for the `sha256` embed + let sha256_round = crate::embed::FlatEmbed::Sha256Round; + let sha256_round_key = sha256_round.key::(); + } + } + // define a function in the main module for the `unpack` embed let unpack = crate::embed::FlatEmbed::Unpack(T::get_required_bits()); let unpack_key = unpack.key::(); @@ -135,6 +143,8 @@ impl<'ast, T: Field> Inliner<'ast, T> { "main".into(), TypedModule { functions: vec![ + #[cfg(feature = "bellman")] + (sha256_round_key, TypedFunctionSymbol::Flat(sha256_round)), (unpack_key, TypedFunctionSymbol::Flat(unpack)), (u32_from_bits_key, TypedFunctionSymbol::Flat(u32_from_bits)), (u16_from_bits_key, TypedFunctionSymbol::Flat(u16_from_bits)), diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok new file mode 100644 index 00000000..b332c9c2 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok @@ -0,0 +1,13 @@ +import "./IVconstants" as IVconstants +import "./shaRoundNoBoolCheck" as sha256 + +// A function that takes 4 bool[256] arrays as inputs +// and applies 2 rounds of sha256 compression. +// It returns an array of 256 bool. +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> (bool[256]): + + bool[256] IV = IVconstants() + bool[256] digest1 = sha256(a, b, IV) + bool[256] digest2 = sha256(c, d, digest1) + + return digest2 \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok new file mode 100644 index 00000000..65592589 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok @@ -0,0 +1,16 @@ +import "./1536bit" as sha256 + +// Take two bool[256] arrays as input +// and returns their sha256 full round output as an array of 256 bool. +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> (bool[256]): + + // Hash is computed on the full 1024bit block size + // padding does not fit in the first two blocks + // add dummy block (single "1" followed by "0" + total length) + bool[256] dummyblock1 = [true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + // total length of message is 1024 bits: 0b10000000000 + bool[256] dummyblock2 = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false] + + bool[256] digest = sha256(a, b, c, d, dummyblock1, dummyblock2) + + return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok new file mode 100644 index 00000000..c7ce4a9c --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok @@ -0,0 +1,14 @@ +import "./IVconstants" as IVconstants +import "./shaRoundNoBoolCheck" as sha256 + +// A function that takes 6 bool[256] arrays as inputs +// and applies 3 rounds of sha256 compression. +// It returns an array of 256 bool. +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d, bool[256] e, bool[256] f) -> (bool[256]): + + bool[256] IV = IVconstants() + bool[256] digest1 = sha256(a, b, IV) + bool[256] digest2 = sha256(c, d, digest1) + bool[256] digest3 = sha256(e, f, digest2) + + return digest3 \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok new file mode 100644 index 00000000..c12adb42 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok @@ -0,0 +1,30 @@ +import "./512bit" as sha256 + +// A function that takes 1 bool[256] array as input +// and returns the sha256 full round output as an array of 256 bool. +def main(bool[256] a) -> (bool[256]): + + // Hash is computed on 256 bits of input + // padding fits in the remaining 256 bits of the first block + // add dummy block (single "1" followed by "0" + total length) + bool[256] dummyblock1 = [ \ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0] + + bool[256] digest = sha256(a, dummyblock1) + + return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok new file mode 100644 index 00000000..a05d4a70 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok @@ -0,0 +1,15 @@ +import "./IVconstants" as IVconstants +import "./shaRoundNoBoolCheck" as sha256 + +// A function that takes 2 bool[256] arrays as inputs +// and returns their sha256 compression function as an array of 256 bool. +// In contrast to full_round.zok no padding is being applied +def main(bool[256] a, bool[256] b) -> (bool[256]): + + // a and b is NOT checked to be of type bool + + bool[256] IV = IVconstants() + bool[256] digest = sha256(a, b, IV) + //digest is constraint to be of type bool + + return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok new file mode 100644 index 00000000..d518d3d5 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok @@ -0,0 +1,23 @@ +import "../../../utils/pack/bool/pack128" as pack128 +import "../../../utils/pack/bool/unpack128" as unpack128 +import "./512bitPadded" as sha256 + +// A function that takes an array of 4 field elements as inputs, unpacks each of them to 128 +// bits (big endian), concatenates them and applies sha256. +// It then returns an array of two field elements, each representing 128 bits of the result. +def main(field[4] preimage) -> (field[2]): + + bool[128] a = unpack128(preimage[0]) + bool[128] b = unpack128(preimage[1]) + bool[128] c = unpack128(preimage[2]) + bool[128] d = unpack128(preimage[3]) + + bool[256] lhs = [...a, ...b] + bool[256] rhs = [...c, ...d] + + bool[256] r = sha256(lhs, rhs) + + field res0 = pack128(r[..128]) + field res1 = pack128(r[128..]) + + return [res0, res1] \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok new file mode 100644 index 00000000..7c195915 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok @@ -0,0 +1,17 @@ +import "./1024bit" as sha256 + +// A function that takes 2 bool[256] arrays as inputs +// and returns their sha256 full round output as an array of 256 bool. +def main(bool[256] a, bool[256] b) -> (bool[256]): + + // Hash is computed on the full 512bit block size + // padding does not fit in the primary block + // add dummy block (single "1" followed by "0" + total length) + bool[256] dummyblock1 = [true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + + // total length of message is 512 bits: 0b1000000000 + bool[256] dummyblock2 = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false] + + bool[256] digest = sha256(a, b, dummyblock1, dummyblock2) + + return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok new file mode 100644 index 00000000..56554cff --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok @@ -0,0 +1,15 @@ +// SHA-256 is specified in FIPS 180-3 and initial values are listed in section 5.3.3 +// https://csrc.nist.gov/csrc/media/publications/fips/180/3/archive/2008-10-31/documents/fips180-3_final.pdf +def main() -> (bool[256]): + bool[32] h0 = [false, true, true, false, true, false, true, false, false, false, false, false, true, false, false, true, true, true, true, false, false, true, true, false, false, true, true, false, false, true, true, true] + bool[32] h1 = [true, false, true, true, true, false, true, true, false, true, true, false, false, true, true, true, true, false, true, false, true, true, true, false, true, false, false, false, false, true, false, true] + bool[32] h2 = [false, false, true, true, true, true, false, false, false, true, true, false, true, true, true, false, true, true, true, true, false, false, true, true, false, true, true, true, false, false, true, false] + bool[32] h3 = [true, false, true, false, false, true, false, true, false, true, false, false, true, true, true, true, true, true, true, true, false, true, false, true, false, false, true, true, true, false, true, false] + bool[32] h4 = [false, true, false, true, false, false, false, true, false, false, false, false, true, true, true, false, false, true, false, true, false, false, true, false, false, true, true, true, true, true, true, true] + bool[32] h5 = [true, false, false, true, true, false, true, true, false, false, false, false, false, true, false, true, false, true, true, false, true, false, false, false, true, false, false, false, true, true, false, false] + bool[32] h6 = [false, false, false, true, true, true, true, true, true, false, false, false, false, false, true, true, true, true, false, true, true, false, false, true, true, false, true, false, true, false, true, true] + bool[32] h7 = [false, true, false, true, true, false, true, true, true, true, true, false, false, false, false, false, true, true, false, false, true, true, false, true, false, false, false, true, true, false, false, true] + + bool[256] IV = [...h0, ...h1, ...h2, ...h3, ...h4, ...h5, ...h6, ...h7] + + return IV \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok new file mode 100644 index 00000000..1f971ae0 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok @@ -0,0 +1,8 @@ +#pragma curve bn128 +import "EMBED/sha256round" as sha256round + +// a and b is NOT checked to be 0 or 1 +// the return value is checked to be 0 or 1 +// IV vector is checked to be of type bool +def main(bool[256] a, bool[256] b, bool[256] IV) -> (bool[256]): + return sha256round([...a, ...b], IV) \ No newline at end of file