use crate::{
core::{
bounds::FieldBounds,
circuits::{
boolean::{boolean_value::BooleanValue, byte::Byte, sha3::SHA3_512},
traits::{arithmetic_circuit::ArithmeticCircuit, boolean_circuit::BooleanCircuit},
},
expressions::{
expr::{EvalFailure, Expr},
other_expr::OtherExpr,
},
global_value::{curve_value::CurveValue, value::FieldValue},
mxe_input::{MxeFieldInput, MxeInput, MxeScalarInput},
},
traits::{FromLeBits, GetBit, Random, Reveal, Select, ToLeBytes},
utils::{
crypto::key::{
ED25519_SECRET_KEY_COUNT,
ED25519_SIGNING_KEY_HASH_PREFIX_COUNT,
MXE_ED25519_SECRET_KEY,
},
elliptic_curve::AffineEdwardsPoint,
field::{BaseField, ScalarField},
},
};
use ed25519_dalek::{
hazmat::{raw_sign, raw_verify, ExpandedSecretKey},
Signature,
VerifyingKey,
};
use ff::{Field, PrimeField};
use sha3::{Digest, Sha3_512};
#[derive(Clone, Copy)]
pub struct Ed25519SecretKey([Byte<BooleanValue>; 32]);
impl Ed25519SecretKey {
pub fn new_from_inner(a: [Byte<BooleanValue>; 32]) -> Self {
Self(a)
}
pub fn inner(&self) -> [Byte<BooleanValue>; 32] {
self.0
}
#[allow(dead_code)]
pub fn mxe_secret_key() -> Self {
Self(
(0..ED25519_SECRET_KEY_COUNT)
.map(BooleanValue::ed25519_secret_key)
.collect::<Vec<BooleanValue>>()
.chunks(8)
.map(|chunk| {
Byte::new(
chunk
.to_vec()
.try_into()
.unwrap_or_else(|v: Vec<BooleanValue>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
})
.collect::<Vec<Byte<BooleanValue>>>()
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!(
"Expected a Vec of length {} (found {})",
ED25519_SECRET_KEY_COUNT / 8,
v.len()
)
}),
)
}
#[allow(dead_code)]
pub fn compress(&self) -> [FieldValue<BaseField>; 2] {
self.0
.chunks(16)
.map(|bytes| {
FieldValue::<BaseField>::from_le_bits(
bytes
.iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>(),
false,
)
})
.collect::<Vec<FieldValue<BaseField>>>()
.try_into()
.unwrap_or_else(|v: Vec<FieldValue<BaseField>>| {
panic!("Expected a Vec of length 2 (found {})", v.len())
})
}
}
impl Random for Ed25519SecretKey {
fn random() -> Self {
Self(
(0..32)
.map(|_| Byte::random())
.collect::<Vec<Byte<BooleanValue>>>()
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
}),
)
}
}
#[allow(non_snake_case, dead_code)]
fn encode(P: AffineEdwardsPoint<FieldValue<BaseField>>) -> [Byte<BooleanValue>; 32] {
let (x, y) = P.inner();
let mut P_encoded = (0..BaseField::NUM_BITS)
.map(|i| y.get_bit(i as usize, false))
.collect::<Vec<BooleanValue>>();
P_encoded.push(x.get_bit(0, false));
P_encoded
.chunks(8)
.map(|chunk| {
Byte::new(
chunk
.to_vec()
.try_into()
.unwrap_or_else(|v: Vec<BooleanValue>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
})
.collect::<Vec<Byte<BooleanValue>>>()
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
})
}
#[allow(non_snake_case, dead_code)]
fn decode(P: [Byte<BooleanValue>; 32]) -> AffineEdwardsPoint<FieldValue<BaseField>> {
let mut y_bits = P
.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>();
let x_lsb_expected = y_bits.pop().unwrap();
let y = FieldValue::<BaseField>::from_le_bits(y_bits, false);
let (_, point) = AffineEdwardsPoint::try_from_y(y);
let x_lsb = point.x.get_bit(0, false);
let x = (x_lsb ^ x_lsb_expected).select(-point.x, point.x);
AffineEdwardsPoint::new((x, y), false, false)
}
#[derive(Clone, Copy, Debug)]
#[allow(non_snake_case, dead_code)]
pub struct Ed25519Signature {
pub R_encoded: [Byte<BooleanValue>; 32],
pub S: [Byte<BooleanValue>; 32],
}
#[allow(non_snake_case, dead_code)]
impl Ed25519Signature {
pub fn new(R_encoded: [Byte<BooleanValue>; 32], S: [Byte<BooleanValue>; 32]) -> Self {
Self { R_encoded, S }
}
pub fn from_bytes(bytes: [Byte<BooleanValue>; 64]) -> Self {
let mut R_encoded = bytes.to_vec();
let S = R_encoded.split_off(32);
Self::new(
R_encoded
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
}),
S.try_into().unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
}),
)
}
pub fn to_bytes(self) -> [Byte<BooleanValue>; 64] {
let mut bytes = self.R_encoded.to_vec();
bytes.append(&mut self.S.to_vec());
bytes
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 64 (found {})", v.len())
})
}
pub fn to_vec(self) -> Vec<Byte<BooleanValue>> {
self.to_bytes().to_vec()
}
}
#[derive(Clone)]
#[allow(dead_code)]
pub struct Ed25519SigningKey {
pub(crate) s: FieldValue<ScalarField>,
pub(crate) hash_prefix: [Byte<BooleanValue>; 32],
pub(crate) verifying_key: Ed25519VerifyingKey,
}
impl Ed25519SigningKey {
pub fn new(
s: FieldValue<ScalarField>,
hash_prefix: [Byte<BooleanValue>; 32],
verifying_key: Ed25519VerifyingKey,
) -> Self {
Self {
s,
hash_prefix,
verifying_key,
}
}
pub fn mxe_signing_key() -> Self {
Self {
s: FieldValue::<ScalarField>::from_expr(Expr::Other(OtherExpr::MxeKey(
MxeInput::ScalarOnly(MxeScalarInput::Ed25519SigningKeyS()),
))),
hash_prefix: (0..ED25519_SIGNING_KEY_HASH_PREFIX_COUNT)
.map(BooleanValue::ed25519_signing_key_hash_prefix)
.collect::<Vec<BooleanValue>>()
.chunks(8)
.map(|chunk| {
Byte::new(
chunk
.to_vec()
.try_into()
.unwrap_or_else(|v: Vec<BooleanValue>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
})
.collect::<Vec<Byte<BooleanValue>>>()
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!(
"Expected a Vec of length {} (found {})",
ED25519_SIGNING_KEY_HASH_PREFIX_COUNT / 8,
v.len()
)
}),
verifying_key: Ed25519VerifyingKey::new_from_public_key_encoded(
(0..32)
.map(|i| {
Byte::from(FieldValue::<BaseField>::from_expr(Expr::Other(
OtherExpr::MxeKey(MxeInput::Base(MxeFieldInput::Ed25519VerifyingKey(
i,
))),
)))
})
.collect::<Vec<Byte<BooleanValue>>>()
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
}),
),
}
}
#[allow(non_snake_case)]
pub fn sign(&self, message: Vec<Byte<BooleanValue>>) -> Ed25519Signature {
let hasher = SHA3_512::new();
let mut prefix_vec = self.hash_prefix.to_vec();
prefix_vec.extend(message.iter());
let r = FieldValue::<ScalarField>::from_le_bits(
hasher
.digest(prefix_vec.to_vec())
.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>(),
false,
);
let R = (r * CurveValue::generator()).to_affine();
let R_encoded = encode(R);
let mut R_encoded_vec = R_encoded.to_vec();
R_encoded_vec.extend(self.verifying_key.public_key_encoded.iter());
R_encoded_vec.extend(message.iter());
let k = FieldValue::<ScalarField>::from_le_bits(
hasher
.digest(R_encoded_vec)
.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>(),
false,
);
let S = r + k * self.s;
Ed25519Signature::new(R_encoded, S.to_le_bytes())
}
}
impl From<Ed25519SecretKey> for Ed25519SigningKey {
#[allow(non_snake_case)]
fn from(value: Ed25519SecretKey) -> Self {
let hasher = SHA3_512::new();
let mut h_lo = hasher.digest(value.inner().to_vec()).to_vec();
let h_hi: [Byte<BooleanValue>; 32] =
h_lo.split_off(32)
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
});
let mut s_bits = vec![BooleanValue::from(false); 3];
s_bits.extend(
h_lo.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>()[3..254]
.to_vec(),
);
s_bits.push(BooleanValue::from(true));
let s = FieldValue::<ScalarField>::from_le_bits(s_bits, false);
let public_key = (s * CurveValue::generator()).to_affine();
Ed25519SigningKey::new(
s,
h_hi,
Ed25519VerifyingKey::new_from_public_key(public_key),
)
}
}
#[derive(Clone, Debug)]
pub struct Ed25519VerifyingKeyFromSecretKey;
impl ArithmeticCircuit<BaseField> for Ed25519VerifyingKeyFromSecretKey {
fn eval(&self, x: Vec<BaseField>) -> Result<Vec<BaseField>, EvalFailure> {
assert!(x.len() == 32);
x.iter()
.for_each(|byte| assert!(*byte <= BaseField::from(255)));
let secret_key = x
.into_iter()
.map(|val| val.to_le_bytes()[0])
.collect::<Vec<u8>>();
let h = Sha3_512::default().chain_update(secret_key).finalize();
let esk = ExpandedSecretKey::from_bytes(&h.into());
let verifying_key = VerifyingKey::from(&esk);
Ok(verifying_key
.to_bytes()
.into_iter()
.map(|byte| BaseField::from(byte as u64))
.collect::<Vec<BaseField>>())
}
fn bounds(&self, _bounds: Vec<FieldBounds<BaseField>>) -> Vec<FieldBounds<BaseField>> {
vec![FieldBounds::new(BaseField::ZERO, BaseField::from(255)); 32]
}
fn run(&self, vals: Vec<FieldValue<BaseField>>) -> Vec<FieldValue<BaseField>> {
let secret_key = Ed25519SecretKey::new_from_inner(
vals.into_iter()
.map(Byte::from)
.collect::<Vec<Byte<BooleanValue>>>()
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
}),
);
let signing_key = Ed25519SigningKey::from(secret_key);
signing_key
.verifying_key
.public_key_encoded
.into_iter()
.map(FieldValue::<BaseField>::from)
.collect::<Vec<FieldValue<BaseField>>>()
}
}
#[derive(Clone, Debug)]
pub struct Ed25519Sign;
impl ArithmeticCircuit<BaseField> for Ed25519Sign {
fn eval(&self, x: Vec<BaseField>) -> Result<Vec<BaseField>, EvalFailure> {
x.iter()
.for_each(|byte| assert!(*byte <= BaseField::from(255)));
assert!(x.len() >= 32);
let mut secret_key = x
.into_iter()
.map(|val| val.to_le_bytes()[0])
.collect::<Vec<u8>>();
let message = secret_key.split_off(32);
let h = Sha3_512::default().chain_update(secret_key).finalize();
let esk = ExpandedSecretKey::from_bytes(&h.into());
let verifying_key = VerifyingKey::from(&esk);
let signature = raw_sign::<Sha3_512>(&esk, &message, &verifying_key);
Ok(signature
.to_vec()
.into_iter()
.map(|byte| BaseField::from(byte as u64))
.collect::<Vec<BaseField>>())
}
fn bounds(&self, _bounds: Vec<FieldBounds<BaseField>>) -> Vec<FieldBounds<BaseField>> {
vec![FieldBounds::new(BaseField::ZERO, BaseField::from(255)); 64]
}
fn run(&self, vals: Vec<FieldValue<BaseField>>) -> Vec<FieldValue<BaseField>> {
let mut secret_key = vals
.into_iter()
.map(Byte::from)
.collect::<Vec<Byte<BooleanValue>>>();
let message = secret_key.split_off(32);
let secret_key = Ed25519SecretKey::new_from_inner(secret_key.try_into().unwrap_or_else(
|v: Vec<Byte<BooleanValue>>| panic!("Expected a Vec of length 32 (found {})", v.len()),
));
let signing_key = Ed25519SigningKey::from(secret_key);
let signature = signing_key.sign(message);
signature
.to_vec()
.into_iter()
.map(FieldValue::<BaseField>::from)
.collect::<Vec<FieldValue<BaseField>>>()
}
}
impl BooleanCircuit for Ed25519Sign {
fn eval(&self, x: Vec<bool>) -> Result<Vec<bool>, EvalFailure> {
let x_byte = x
.chunks(8)
.map(|bits| {
BaseField::from(u8::from(Byte::new(bits.to_vec().try_into().unwrap_or_else(
|v: Vec<bool>| panic!("Expected a Vec of length 8 (found {})", v.len()),
))) as u64)
})
.collect::<Vec<BaseField>>();
let res = ArithmeticCircuit::eval(self, x_byte)?;
Ok(res
.into_iter()
.flat_map(|byte| Byte::from(byte.to_le_bytes()[0]).to_vec())
.collect::<Vec<bool>>())
}
fn run(&self, vals: Vec<BooleanValue>) -> Vec<BooleanValue> {
let vals_byte = vals
.chunks(8)
.map(|bits| {
FieldValue::from(Byte::new(bits.to_vec().try_into().unwrap_or_else(
|v: Vec<BooleanValue>| panic!("Expected a Vec of length 8 (found {})", v.len()),
)))
})
.collect::<Vec<FieldValue<BaseField>>>();
let res = ArithmeticCircuit::run(self, vals_byte);
res.into_iter()
.flat_map(|byte| byte.to_le_bytes()[0].to_vec())
.collect::<Vec<BooleanValue>>()
}
}
#[derive(Clone, Debug)]
pub struct Ed25519MXESign;
impl ArithmeticCircuit<BaseField> for Ed25519MXESign {
fn eval(&self, x: Vec<BaseField>) -> Result<Vec<BaseField>, EvalFailure> {
x.iter()
.for_each(|byte| assert!(*byte <= BaseField::from(255)));
let message = x
.into_iter()
.map(|val| val.to_le_bytes()[0])
.collect::<Vec<u8>>();
let h = Sha3_512::default()
.chain_update(MXE_ED25519_SECRET_KEY)
.finalize();
let esk = ExpandedSecretKey::from_bytes(&h.into());
let verifying_key = VerifyingKey::from(&esk);
let signature = raw_sign::<Sha3_512>(&esk, &message, &verifying_key);
Ok(signature
.to_vec()
.into_iter()
.map(|byte| BaseField::from(byte as u64))
.collect::<Vec<BaseField>>())
}
fn bounds(&self, _bounds: Vec<FieldBounds<BaseField>>) -> Vec<FieldBounds<BaseField>> {
vec![FieldBounds::new(BaseField::ZERO, BaseField::from(255)); 64]
}
fn run(&self, vals: Vec<FieldValue<BaseField>>) -> Vec<FieldValue<BaseField>> {
let message = vals
.into_iter()
.map(Byte::from)
.collect::<Vec<Byte<BooleanValue>>>();
let mxe_signing_key = Ed25519SigningKey::mxe_signing_key();
let signature = mxe_signing_key.sign(message);
signature
.to_vec()
.into_iter()
.map(FieldValue::<BaseField>::from)
.collect::<Vec<FieldValue<BaseField>>>()
}
}
#[derive(Clone, Copy, Debug)]
pub struct Ed25519VerifyingKey {
pub(crate) public_key: AffineEdwardsPoint<FieldValue<BaseField>>,
pub(crate) public_key_encoded: [Byte<BooleanValue>; 32],
}
#[allow(dead_code)]
impl Ed25519VerifyingKey {
pub fn new_from_public_key(public_key: AffineEdwardsPoint<FieldValue<BaseField>>) -> Self {
Self {
public_key,
public_key_encoded: encode(public_key),
}
}
pub fn new_from_public_key_encoded(public_key_encoded: [Byte<BooleanValue>; 32]) -> Self {
Self {
public_key: decode(public_key_encoded),
public_key_encoded,
}
}
#[allow(non_snake_case)]
pub fn verify(
&self,
message: Vec<Byte<BooleanValue>>,
signature: Ed25519Signature,
) -> BooleanValue {
let hasher = SHA3_512::new();
let R_encoded = signature.R_encoded;
let R = decode(R_encoded);
let mut R_encoded_vec = R_encoded.to_vec();
R_encoded_vec.extend(self.public_key_encoded.iter());
R_encoded_vec.extend(message.iter());
let k = FieldValue::<ScalarField>::from_le_bits(
hasher
.digest(R_encoded_vec)
.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>(),
false,
);
let S = FieldValue::<ScalarField>::from_le_bits(
signature
.S
.into_iter()
.flat_map(|byte| byte.to_vec())
.take(253)
.collect::<Vec<BooleanValue>>(),
false,
);
let lhs = S * CurveValue::generator() - CurveValue::from_affine(R);
let rhs = k * CurveValue::from_affine(self.public_key);
(lhs - rhs).is_identity()
}
}
impl Reveal for Ed25519VerifyingKey {
fn reveal(self) -> Self {
Self {
public_key: self.public_key.reveal(),
public_key_encoded: self.public_key_encoded.map(|byte| byte.reveal()),
}
}
}
#[derive(Clone, Debug)]
pub struct Ed25519Verify;
impl ArithmeticCircuit<BaseField> for Ed25519Verify {
fn eval(&self, x: Vec<BaseField>) -> Result<Vec<BaseField>, EvalFailure> {
x.iter()
.for_each(|byte| assert!(*byte <= BaseField::from(255)));
assert!(x.len() >= 96);
let mut public_key_encoded_bytes = x
.into_iter()
.map(|val| val.to_le_bytes()[0])
.collect::<Vec<u8>>();
let mut message = public_key_encoded_bytes.split_off(32);
let len = message.len();
let signature_bytes = message.split_off(len - 64);
let verifying_key =
VerifyingKey::from_bytes(&public_key_encoded_bytes.try_into().unwrap_or_else(
|v: Vec<u8>| panic!("Expected a Vec of length 32 (found {})", v.len()),
))
.unwrap();
let signature =
Signature::from_bytes(&signature_bytes.try_into().unwrap_or_else(|v: Vec<u8>| {
panic!("Expected a Vec of length 64 (found {})", v.len())
}));
let is_valid = raw_verify::<Sha3_512>(&verifying_key, &message, &signature);
Ok(vec![BaseField::from(is_valid.is_ok())])
}
fn bounds(&self, _bounds: Vec<FieldBounds<BaseField>>) -> Vec<FieldBounds<BaseField>> {
vec![FieldBounds::new(BaseField::ZERO, BaseField::ONE)]
}
fn run(&self, vals: Vec<FieldValue<BaseField>>) -> Vec<FieldValue<BaseField>> {
let mut public_key_encoded_bytes = vals
.into_iter()
.map(Byte::from)
.collect::<Vec<Byte<BooleanValue>>>();
let mut message = public_key_encoded_bytes.split_off(32);
let len = message.len();
let signature_bytes = message.split_off(len - 64);
let verifying_key = Ed25519VerifyingKey::new_from_public_key_encoded(
public_key_encoded_bytes
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
}),
);
let signature = Ed25519Signature::from_bytes(signature_bytes.try_into().unwrap_or_else(
|v: Vec<Byte<BooleanValue>>| panic!("Expected a Vec of length 64 (found {})", v.len()),
));
let is_valid = verifying_key.verify(message, signature);
vec![FieldValue::<BaseField>::from(is_valid)]
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::{
circuits::traits::{
arithmetic_circuit::tests::TestedArithmeticCircuit,
boolean_circuit::tests::TestedBooleanCircuit,
},
expressions::{
bit_expr::{BitExpr, BitInputInfo},
domain::Domain,
expr::EvalValue,
InputKind,
},
global_value::global_expr_store::with_local_expr_store_as_global,
ir_builder::{ExprStore, IRBuilder},
};
use ed25519_dalek::VerifyingKey;
use rand::Rng;
use sha3::Sha3_512;
use std::rc::Rc;
impl TestedArithmeticCircuit<BaseField> for Ed25519MXESign {
fn gen_desc<R: Rng + ?Sized>(_rng: &mut R) -> Self {
Self
}
fn gen_n_inputs<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
let mut message_len = 4;
while rng.gen_bool(0.75) {
message_len += 3 * 8;
}
message_len
}
fn gen_input_bounds<R: Rng + ?Sized>(_rng: &mut R) -> FieldBounds<BaseField> {
FieldBounds::new(BaseField::ZERO, BaseField::from(255))
}
}
#[test]
fn test_mxe_sign() {
Ed25519MXESign::test(1, 1)
}
impl TestedBooleanCircuit for Ed25519Sign {
fn gen_desc<R: Rng + ?Sized>(_rng: &mut R) -> Self {
Self
}
fn gen_n_inputs<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
let mut bits_len = 256 + 12 * 8;
while rng.gen_bool(0.75) {
bits_len += 3 * 8;
}
bits_len
}
}
#[test]
fn test_sign() {
Ed25519Sign::test(1, 1)
}
#[test]
#[allow(non_snake_case)]
fn test_verify() {
let rng = &mut crate::utils::test_rng::get();
let mut byte_len = 32 + 12;
while rng.gen_bool(0.75) {
byte_len += 3;
}
let mut secret_key_bits = (0..8 * byte_len)
.map(|_| rng.gen_bool(0.5))
.collect::<Vec<bool>>();
let mut message_bits = secret_key_bits.split_off(256);
let secret_key = secret_key_bits
.chunks(8)
.map(|chunk| {
u8::from(Byte::new(chunk.to_vec().try_into().unwrap_or_else(
|v: Vec<bool>| panic!("Expected a Vec of length 8 (found {})", v.len()),
)))
})
.collect::<Vec<u8>>();
let message = message_bits
.chunks(8)
.map(|chunk| {
u8::from(Byte::new(chunk.to_vec().try_into().unwrap_or_else(
|v: Vec<bool>| panic!("Expected a Vec of length 8 (found {})", v.len()),
)))
})
.collect::<Vec<u8>>();
let h = Sha3_512::default().chain_update(secret_key).finalize();
let esk = ExpandedSecretKey::from_bytes(&h.into());
let verifying_key = VerifyingKey::from(&esk);
let signature = raw_sign::<Sha3_512>(&esk, &message, &verifying_key);
fn run(input_ids: Vec<usize>) -> Vec<usize> {
let mut secret_key = input_ids
.chunks(8)
.map(|chunk| {
Byte::new(
chunk
.iter()
.copied()
.map(BooleanValue::new)
.collect::<Vec<BooleanValue>>()
.try_into()
.unwrap_or_else(|v: Vec<BooleanValue>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
})
.collect::<Vec<Byte<BooleanValue>>>();
let mut message = secret_key.split_off(32);
let len = message.len();
let mut R_encoded = message.split_off(len - 64);
let S = R_encoded.split_off(32);
let verifying_key = Ed25519SigningKey::from(Ed25519SecretKey::new_from_inner(
secret_key
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
}),
))
.verifying_key;
let signature = Ed25519Signature::new(
R_encoded
.try_into()
.unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
}),
S.try_into().unwrap_or_else(|v: Vec<Byte<BooleanValue>>| {
panic!("Expected a Vec of length 32 (found {})", v.len())
}),
);
let verification = verifying_key.verify(message, signature);
vec![verification.get_id()]
}
let mut inputs = secret_key_bits;
let is_valid_signature = rng.gen_bool(0.5);
if !is_valid_signature {
message_bits[0] = !message_bits[0];
}
inputs.append(&mut message_bits);
inputs.append(
&mut signature
.r_bytes()
.iter()
.flat_map(|byte| Byte::from(*byte).to_vec())
.collect::<Vec<bool>>(),
);
inputs.append(
&mut signature
.s_bytes()
.iter()
.flat_map(|byte| Byte::from(*byte).to_vec())
.collect::<Vec<bool>>(),
);
let inputs_len = inputs.len();
let mut inputs_map = inputs.into_iter().map(EvalValue::Bit).enumerate().collect();
let mut expr_store = IRBuilder::new(true);
let input_ids = (0..inputs_len)
.map(|i| {
<IRBuilder as ExprStore<BaseField>>::push_bit(
&mut expr_store,
BitExpr::Input(
i,
Rc::new(BitInputInfo {
kind: InputKind::Secret,
..BitInputInfo::default()
}),
),
)
})
.collect::<Vec<usize>>();
let outputs = with_local_expr_store_as_global(|| run(input_ids.clone()), &mut expr_store);
let ir = expr_store.into_ir(outputs);
let result = ir
.eval(rng, &mut inputs_map)
.map(|x| x.into_iter().map(bool::unwrap).collect::<Vec<bool>>())
.unwrap();
assert_eq!(result[0], is_valid_signature);
}
}