Update C6 (#110)

* rename input mask to plaintext

* update naming and docs for c6

* touch ups
This commit is contained in:
sinu.eth
2022-11-05 13:40:04 -07:00
committed by GitHub
parent 031b22d357
commit 3ca47aec5b

View File

@@ -4,120 +4,106 @@ use mpc_circuits::{
/// TLS stage 6
///
/// Compute AES-CTR
/// Encrypt plaintext or decrypt ciphertext in AES-CTR mode
///
/// T_IN could also just be used as a mask for the encrypted counter-block.
///
/// Inputs:
///
/// 0. N_CWK: 16-byte Notary share of client write-key
/// 1. N_CIV: 4-byte Notary share of client IV
/// 2. U_CWK: 16-byte User share of client write-key
/// 3. U_CIV: 4-byte User share of client IV
/// 4. U_MASK: 16-byte User mask for encrypted counter block
/// 5. NONCE: U16 Nonce
/// 6. CTR: U16 CTR
/// 0. N_K: 16-byte Notary share of write-key
/// 1. N_IV: 4-byte Notary share of IV
/// 2. U_K: 16-byte User share of write-key
/// 3. U_IV: 4-byte User share of IV
/// 4. T_IN: 16-byte text (plaintext or ciphertext)
/// 5. NONCE: 8-byte Explicit Nonce
/// 6. CTR: U32 Counter
///
/// Outputs:
///
/// 0. MASKED_ECTR: 16-byte masked (U_MASK) encrypted counter block
/// 0. T_OUT: 16-byte output (plaintext or ciphertext)
pub fn c6() -> Circuit {
let mut builder = CircuitBuilder::new("c6", "0.1.0");
let n_cwk = builder.add_input(
"N_CWK",
"16-byte Notary client write-key share",
let n_k = builder.add_input(
"N_K",
"16-byte Notary write-key share",
ValueType::Bytes,
128,
);
let n_civ = builder.add_input(
"N_SIV",
"4-byte Notary share of client IV",
ValueType::Bytes,
32,
);
let u_cwk = builder.add_input(
let n_iv = builder.add_input("N_SIV", "4-byte Notary share of IV", ValueType::Bytes, 32);
let c_k = builder.add_input(
"U_SWK",
"16-byte User share of client write-key",
"16-byte User share of write-key",
ValueType::Bytes,
128,
);
let u_civ = builder.add_input(
"U_SIV",
"4-byte User share of client IV",
ValueType::Bytes,
32,
);
let u_mask = builder.add_input(
"U_MASK",
"16-byte User mask for encrypted counter block",
let c_iv = builder.add_input("U_SIV", "4-byte User share of IV", ValueType::Bytes, 32);
let t_in = builder.add_input(
"T_IN",
"16-byte text (plaintext or ciphertext)",
ValueType::Bytes,
128,
);
let nonce = builder.add_input("NONCE", "U64 Nonce", ValueType::U64, 64);
let ctr = builder.add_input("CTR", "U32 CTR", ValueType::U32, 32);
let nonce = builder.add_input("NONCE", "8-byte Explicit Nonce", ValueType::Bytes, 64);
let ctr = builder.add_input("CTR", "U32 Counter", ValueType::U32, 32);
let mut builder = builder.build_inputs();
let aes = Circuit::load_bytes(AES_128_REVERSE).expect("failed to load aes_128_reverse circuit");
let aes_ectr = builder.add_circ(aes);
let cwk = builder.add_circ(nbit_xor(128));
let civ = builder.add_circ(nbit_xor(32));
let masked_ectr = builder.add_circ(nbit_xor(128));
let k = builder.add_circ(nbit_xor(128));
let iv = builder.add_circ(nbit_xor(32));
let t_out = builder.add_circ(nbit_xor(128));
// cwk
builder.connect(
&n_cwk[..],
&cwk.input(0).expect("nbit_xor missing input 0")[..],
);
builder.connect(
&u_cwk[..],
&cwk.input(1).expect("nbit_xor missing input 1")[..],
);
let cwk = cwk.output(0).expect("nbit_xor missing output 0");
// Compute write-key
builder.connect(&n_k[..], &k.input(0).expect("nbit_xor missing input 0")[..]);
builder.connect(&c_k[..], &k.input(1).expect("nbit_xor missing input 1")[..]);
let k = k.output(0).expect("nbit_xor missing output 0");
// civ
// iv
builder.connect(
&n_civ[..],
&civ.input(0).expect("nbit_xor missing input 0")[..],
&n_iv[..],
&iv.input(0).expect("nbit_xor missing input 0")[..],
);
builder.connect(
&u_civ[..],
&civ.input(1).expect("nbit_xor missing input 1")[..],
&c_iv[..],
&iv.input(1).expect("nbit_xor missing input 1")[..],
);
let civ = civ.output(0).expect("nbit_xor missing output 0");
let iv = iv.output(0).expect("nbit_xor missing output 0");
// Compute ECTR
builder.connect(
&cwk[..],
&aes_ectr.input(0).expect("aes missing input 0")[..],
);
// Compute encrypted counter-block
builder.connect(&k[..], &aes_ectr.input(0).expect("aes missing input 0")[..]);
let aes_ectr_m = aes_ectr.input(1).expect("aes missing input 1");
builder.connect(&civ[..], &aes_ectr_m[96..]);
// Implicit nonce
builder.connect(&iv[..], &aes_ectr_m[96..]);
// Explicit nonce
builder.connect(&nonce[..], &aes_ectr_m[32..96]);
// Counter
builder.connect(&ctr[..], &aes_ectr_m[..32]);
let ectr = aes_ectr.output(0).expect("aes missing output 0");
// Apply ECTR mask
// Apply text
builder.connect(
&ectr[..],
&masked_ectr.input(0).expect("nbit_xor missing input 0")[..],
&t_out.input(0).expect("nbit_xor missing input 0")[..],
);
builder.connect(
&u_mask[..],
&masked_ectr.input(1).expect("nbit_xor missing input 1")[..],
&t_in[..],
&t_out.input(1).expect("nbit_xor missing input 1")[..],
);
let mut builder = builder.build_gates();
let out_ectr = builder.add_output(
"MASKED_ECTR",
"16-byte masked (U_MASK) encrypted counter block",
"T_OUT",
"16-byte output (plaintext or ciphertext)",
ValueType::Bytes,
128,
);
builder.connect(
&masked_ectr.output(0).expect("nbit_xor missing output 0")[..],
&t_out.output(0).expect("nbit_xor missing output 0")[..],
&out_ectr[..],
);
@@ -140,58 +126,53 @@ mod tests {
let mut rng = thread_rng();
let n_cwk: [u8; 16] = rng.gen();
let n_civ: [u8; 4] = rng.gen();
let u_cwk: [u8; 16] = rng.gen();
let u_civ: [u8; 4] = rng.gen();
let u_mask: [u8; 16] = rng.gen();
let nonce: u64 = rng.gen();
let n_k: [u8; 16] = rng.gen();
let n_iv: [u8; 4] = rng.gen();
let u_k: [u8; 16] = rng.gen();
let u_iv: [u8; 4] = rng.gen();
let t_in: [u8; 16] = rng.gen();
let explicit_nonce: [u8; 8] = rng.gen();
let ctr: u32 = rng.gen();
// combine key shares
let cwk = n_cwk
let k = n_k.iter().zip(u_k).map(|(n, u)| n ^ u).collect::<Vec<u8>>();
let iv = n_iv
.iter()
.zip(u_cwk)
.map(|(n, u)| n ^ u)
.collect::<Vec<u8>>();
let civ = n_civ
.iter()
.zip(u_civ)
.zip(u_iv)
.map(|(n, u)| n ^ u)
.collect::<Vec<u8>>();
// set AES key
let key = GenericArray::clone_from_slice(&cwk);
let key = GenericArray::clone_from_slice(&k);
let cipher = Aes128::new(&key);
// AES-ECB encrypt a block with counter and nonce
let mut msg = [0u8; 16];
msg[0..4].copy_from_slice(&civ);
msg[4..12].copy_from_slice(&nonce.to_be_bytes());
msg[0..4].copy_from_slice(&iv);
msg[4..12].copy_from_slice(&explicit_nonce);
msg[12..16].copy_from_slice(&ctr.to_be_bytes());
let mut msg = GenericArray::clone_from_slice(&msg);
cipher.encrypt_block(&mut msg);
let ectr = msg;
// XOR the first block and verify_data with User's mask
let ectr_masked = ectr
let t_out = ectr
.iter()
.zip(u_mask)
.zip(t_in)
.map(|(v, u)| v ^ u)
.collect::<Vec<u8>>();
test_circ(
&circ,
&[
Value::Bytes(n_cwk.into_iter().rev().collect()),
Value::Bytes(n_civ.into_iter().rev().collect()),
Value::Bytes(u_cwk.into_iter().rev().collect()),
Value::Bytes(u_civ.into_iter().rev().collect()),
Value::Bytes(u_mask.into_iter().rev().collect()),
Value::U64(nonce),
Value::Bytes(n_k.into_iter().rev().collect()),
Value::Bytes(n_iv.into_iter().rev().collect()),
Value::Bytes(u_k.into_iter().rev().collect()),
Value::Bytes(u_iv.into_iter().rev().collect()),
Value::Bytes(t_in.into_iter().rev().collect()),
Value::Bytes(explicit_nonce.into_iter().rev().collect()),
Value::U32(ctr),
],
&[Value::Bytes(ectr_masked.into_iter().rev().collect())],
&[Value::Bytes(t_out.into_iter().rev().collect())],
);
}
}