Blake PRF & R1CS Boolean Refactor (#132)

* refactor(r1cs-std/boolean): expose enforcing value less than functionality

* fix(r1cs-std/boolean): ensure num_bits is calculated correctly from the arg

* feat(primitives/blake2s): allow creating Blake2s with custom params
This commit is contained in:
Pratyush Mishra
2020-03-05 10:51:59 -08:00
committed by GitHub
parent 0b57cdd736
commit 0df0a15e1b
3 changed files with 142 additions and 19 deletions

View File

@@ -313,20 +313,50 @@ fn blake2s_compression<ConstraintF: PrimeField, CS: ConstraintSystem<ConstraintF
//
pub fn blake2s_gadget<ConstraintF: PrimeField, CS: ConstraintSystem<ConstraintF>>(
cs: CS,
input: &[Boolean],
) -> Result<Vec<UInt32>, SynthesisError> {
assert!(input.len() % 8 == 0);
let mut parameters = [0; 8];
parameters[0] = 0x01010000 ^ 32;
blake2s_gadget_with_parameters(cs, input, &parameters)
}
pub fn blake2s_gadget_with_parameters<
ConstraintF: PrimeField,
CS: ConstraintSystem<ConstraintF>,
>(
mut cs: CS,
input: &[Boolean],
parameters: &[u32; 8],
) -> Result<Vec<UInt32>, SynthesisError> {
assert!(input.len() % 8 == 0);
let mut h = Vec::with_capacity(8);
h.push(UInt32::constant(0x6A09E667 ^ 0x01010000 ^ 32));
h.push(UInt32::constant(0xBB67AE85));
h.push(UInt32::constant(0x3C6EF372));
h.push(UInt32::constant(0xA54FF53A));
h.push(UInt32::constant(0x510E527F));
h.push(UInt32::constant(0x9B05688C));
h.push(UInt32::constant(0x1F83D9AB));
h.push(UInt32::constant(0x5BE0CD19));
h.push(
UInt32::constant(0x6A09E667).xor(cs.ns(|| "xor h[0]"), &UInt32::constant(parameters[0]))?,
);
h.push(
UInt32::constant(0xBB67AE85).xor(cs.ns(|| "xor h[1]"), &UInt32::constant(parameters[1]))?,
);
h.push(
UInt32::constant(0x3C6EF372).xor(cs.ns(|| "xor h[2]"), &UInt32::constant(parameters[2]))?,
);
h.push(
UInt32::constant(0xA54FF53A).xor(cs.ns(|| "xor h[3]"), &UInt32::constant(parameters[3]))?,
);
h.push(
UInt32::constant(0x510E527F).xor(cs.ns(|| "xor h[4]"), &UInt32::constant(parameters[4]))?,
);
h.push(
UInt32::constant(0x9B05688C).xor(cs.ns(|| "xor h[5]"), &UInt32::constant(parameters[5]))?,
);
h.push(
UInt32::constant(0x1F83D9AB).xor(cs.ns(|| "xor h[6]"), &UInt32::constant(parameters[6]))?,
);
h.push(
UInt32::constant(0x5BE0CD19).xor(cs.ns(|| "xor h[7]"), &UInt32::constant(parameters[7]))?,
);
let mut blocks: Vec<Vec<UInt32>> = vec![];

View File

@@ -1,3 +1,4 @@
use alloc::vec::Vec;
use blake2::Blake2s as b2s;
use digest::Digest;
@@ -26,3 +27,63 @@ impl PRF for Blake2s {
Ok(result)
}
}
#[derive(Clone)]
pub struct Blake2sWithParameterBlock {
pub digest_length: u8,
pub key_length: u8,
pub fan_out: u8,
pub depth: u8,
pub leaf_length: u32,
pub node_offset: u32,
pub xof_digest_length: u16,
pub node_depth: u8,
pub inner_length: u8,
pub salt: [u8; 8],
pub personalization: [u8; 8],
}
impl Blake2sWithParameterBlock {
pub fn parameters(&self) -> [u32; 8] {
let mut parameters = [0; 8];
parameters[0] = u32::from_le_bytes([
self.digest_length,
self.key_length,
self.fan_out,
self.depth,
]);
parameters[1] = self.leaf_length;
parameters[2] = self.node_offset;
parameters[3] = u32::from_le_bytes([
self.xof_digest_length as u8,
(self.xof_digest_length >> 8) as u8,
self.node_depth,
self.inner_length,
]);
let mut salt_bytes_1 = [0; 4];
let mut salt_bytes_2 = [0; 4];
let mut personalization_bytes_1 = [0; 4];
let mut personalization_bytes_2 = [0; 4];
for i in 0..4 {
salt_bytes_1[i] = self.salt[i];
salt_bytes_2[i] = self.salt[4 + i];
personalization_bytes_1[i] = self.personalization[i];
personalization_bytes_2[i] = self.personalization[4 + i];
}
parameters[4] = u32::from_le_bytes(salt_bytes_1);
parameters[5] = u32::from_le_bytes(salt_bytes_2);
parameters[6] = u32::from_le_bytes(personalization_bytes_1);
parameters[7] = u32::from_le_bytes(personalization_bytes_2);
parameters
}
pub fn evaluate(&self, input: &[u8]) -> Vec<u8> {
let eval_time = start_timer!(|| "Blake2sWithParameterBlock::Eval");
let mut h = b2s::with_parameter_block(&self.parameters());
h.input(input.as_ref());
end_timer!(eval_time);
h.result().to_vec()
}
}