use bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr};
use rand::{Rng};
use std::io::{self, Read, Write};
use jubjub::{
FixedGenerators,
JubjubEngine,
JubjubParams,
Unknown,
edwards::Point,
ToUniform};
use util::{hash_to_scalar, hash_to_scalar_s, sha256_hash_to_scalar};
use ::constants::{MATTER_EDDSA_BLAKE2S_PERSONALIZATION};
fn read_scalar<E: JubjubEngine, R: Read>(reader: R) -> io::Result<E::Fs> {
let mut s_repr = <E::Fs as PrimeField>::Repr::default();
s_repr.read_le(reader)?;
match E::Fs::from_repr(s_repr) {
Ok(s) => Ok(s),
Err(_) => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"scalar is not in field",
)),
}
}
fn write_scalar<E: JubjubEngine, W: Write>(s: &E::Fs, writer: W) -> io::Result<()> {
s.into_repr().write_le(writer)
}
fn h_star<E: JubjubEngine>(a: &[u8], b: &[u8]) -> E::Fs {
hash_to_scalar::<E>(b"Zcash_RedJubjubH", a, b)
}
fn h_star_s<E: JubjubEngine>(a: &[u8], b: &[u8]) -> E::Fs {
hash_to_scalar_s::<E>(MATTER_EDDSA_BLAKE2S_PERSONALIZATION, a, b)
}
fn sha256_h_star<E: JubjubEngine>(a: &[u8], b: &[u8]) -> E::Fs {
sha256_hash_to_scalar::<E>(&[], a, b)
}
#[derive(Copy, Clone)]
pub struct SerializedSignature {
rbar: [u8; 32],
sbar: [u8; 32],
}
#[derive(Clone)]
pub struct Signature<E: JubjubEngine> {
pub r: Point<E, Unknown>,
pub s: E::Fs,
}
pub struct PrivateKey<E: JubjubEngine>(pub E::Fs);
#[derive(Clone)]
pub struct PublicKey<E: JubjubEngine>(pub Point<E, Unknown>);
impl SerializedSignature {
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
let mut rbar = [0u8; 32];
let mut sbar = [0u8; 32];
reader.read_exact(&mut rbar)?;
reader.read_exact(&mut sbar)?;
Ok(SerializedSignature { rbar, sbar })
}
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
writer.write_all(&self.rbar)?;
writer.write_all(&self.sbar)
}
}
impl<E: JubjubEngine> PrivateKey<E> {
pub fn randomize(&self, alpha: E::Fs) -> Self {
let mut tmp = self.0;
tmp.add_assign(&alpha);
PrivateKey(tmp)
}
pub fn read<R: Read>(reader: R) -> io::Result<Self> {
let pk = read_scalar::<E, R>(reader)?;
Ok(PrivateKey(pk))
}
pub fn write<W: Write>(&self, writer: W) -> io::Result<()> {
write_scalar::<E, W>(&self.0, writer)
}
pub fn sign_raw_message<R: Rng>(
&self,
msg: &[u8],
rng: &mut R,
p_g: FixedGenerators,
params: &E::Params,
max_message_size: usize,
) -> Signature<E> {
let mut t = [0u8; 80];
rng.fill_bytes(&mut t[..]);
let r = h_star::<E>(&t[..], msg);
let pk = PublicKey::from_private(&self, p_g, params);
let order_check = pk.0.mul(E::Fs::char(), params);
assert!(order_check.eq(&Point::zero()));
let r_g = params.generator(p_g).mul(r, params);
assert!(msg.len() <= max_message_size);
assert!(max_message_size * 8 <= E::Fs::CAPACITY as usize);
let mut msg_padded : Vec<u8> = msg.iter().cloned().collect();
for _ in 0..(32 - msg.len()) {
msg_padded.extend(&[0u8;1]);
}
let mut s = E::Fs::to_uniform_32(msg_padded.as_ref());
s.mul_assign(&self.0);
s.add_assign(&r);
let as_unknown = Point::from(r_g);
Signature { r: as_unknown, s: s }
}
pub fn sign_schnorr_blake2s<R: Rng>(
&self,
msg: &[u8],
rng: &mut R,
p_g: FixedGenerators,
params: &E::Params,
) -> Signature<E> {
let mut t = [0u8; 80];
rng.fill_bytes(&mut t[..]);
let r = h_star::<E>(&t[..], msg);
let pk = PublicKey::from_private(&self, p_g, params);
let order_check = pk.0.mul(E::Fs::char(), params);
assert!(order_check.eq(&Point::zero()));
let r_g = params.generator(p_g).mul(r, params);
let (r_g_x, _) = r_g.into_xy();
let mut r_g_x_bytes = [0u8; 32];
r_g_x.into_repr().write_le(& mut r_g_x_bytes[..]).expect("has serialized r_g_x");
let concatenated: Vec<u8> = r_g_x_bytes.iter().cloned().collect();
let mut msg_padded : Vec<u8> = msg.iter().cloned().collect();
msg_padded.resize(32, 0u8);
let mut s = h_star_s::<E>(&concatenated[..], &msg_padded[..]);
s.mul_assign(&self.0);
s.add_assign(&r);
let as_unknown = Point::from(r_g);
Signature { r: as_unknown, s: s }
}
pub fn musig_sha256_sign<R: Rng>(
&self,
msg: &[u8],
rng: &mut R,
p_g: FixedGenerators,
params: &E::Params,
) -> Signature<E> {
let mut t = [0u8; 80];
rng.fill_bytes(&mut t[..]);
let r = h_star::<E>(&t[..], msg);
let pk = PublicKey::from_private(&self, p_g, params);
let order_check = pk.0.mul(E::Fs::char(), params);
assert!(order_check.eq(&Point::zero()));
let (pk_x, _) = pk.0.into_xy();
let mut pk_x_bytes = [0u8; 32];
pk_x.into_repr().write_le(& mut pk_x_bytes[..]).expect("has serialized pk_x");
let r_g = params.generator(p_g).mul(r, params);
let (r_g_x, _) = r_g.into_xy();
let mut r_g_x_bytes = [0u8; 32];
r_g_x.into_repr().write_le(& mut r_g_x_bytes[..]).expect("has serialized r_g_x");
let mut concatenated: Vec<u8> = pk_x_bytes.as_ref().to_vec();
concatenated.extend(r_g_x_bytes.as_ref().to_vec().into_iter());
let mut msg_padded : Vec<u8> = msg.iter().cloned().collect();
msg_padded.resize(32, 0u8);
let mut s = sha256_h_star::<E>(&concatenated[..], &msg_padded[..]);
s.mul_assign(&self.0);
s.add_assign(&r);
let as_unknown = Point::from(r_g);
Signature { r: as_unknown, s: s }
}
pub fn sign<R: Rng>(
&self,
msg: &[u8],
rng: &mut R,
p_g: FixedGenerators,
params: &E::Params,
) -> Signature<E> {
let mut t = [0u8; 80];
rng.fill_bytes(&mut t[..]);
let r = h_star::<E>(&t[..], msg);
let pk = PublicKey::from_private(&self, p_g, params);
let order_check = pk.0.mul(E::Fs::char(), params);
assert!(order_check.eq(&Point::zero()));
let r_g = params.generator(p_g).mul(r, params);
let (r_g_x, r_g_y) = r_g.into_xy();
let mut r_g_x_bytes = [0u8; 32];
r_g_x.into_repr().write_le(& mut r_g_x_bytes[..]).expect("has serialized r_g_x");
let mut r_g_y_bytes = [0u8; 32];
r_g_y.into_repr().write_le(& mut r_g_y_bytes[..]).expect("has serialized r_g_y");
let (pk_x, pk_y) = pk.0.into_xy();
let mut pk_x_bytes = [0u8; 32];
pk_x.into_repr().write_le(& mut pk_x_bytes[..]).expect("has serialized pk_x");
let mut pk_y_bytes = [0u8; 32];
pk_y.into_repr().write_le(& mut pk_y_bytes[..]).expect("has serialized pk_y");
let concatenated: Vec<u8> = r_g_x_bytes.iter().chain(r_g_y_bytes.iter()).chain(pk_x_bytes.iter()).chain(pk_y_bytes.iter()).cloned().collect();
let mut s = h_star::<E>(&concatenated[..], msg);
s.mul_assign(&self.0);
s.add_assign(&r);
let as_unknown = Point::from(r_g);
Signature { r: as_unknown, s: s }
}
}
impl<E: JubjubEngine> PublicKey<E> {
pub fn from_private(privkey: &PrivateKey<E>, p_g: FixedGenerators, params: &E::Params) -> Self {
let res = params.generator(p_g).mul(privkey.0, params).into();
PublicKey(res)
}
pub fn randomize(&self, alpha: E::Fs, p_g: FixedGenerators, params: &E::Params) -> Self {
let res: Point<E, Unknown> = params.generator(p_g).mul(alpha, params).into();
let res = res.add(&self.0, params);
PublicKey(res)
}
pub fn read<R: Read>(reader: R, params: &E::Params) -> io::Result<Self> {
let p = Point::read(reader, params)?;
Ok(PublicKey(p))
}
pub fn write<W: Write>(&self, writer: W) -> io::Result<()> {
self.0.write(writer)
}
pub fn verify(
&self,
msg: &[u8],
sig: &Signature<E>,
p_g: FixedGenerators,
params: &E::Params,
) -> bool {
let (r_g_x, r_g_y) = sig.r.into_xy();
let mut r_g_x_bytes = [0u8; 32];
r_g_x.into_repr().write_le(& mut r_g_x_bytes[..]).expect("has serialized r_g_x");
let mut r_g_y_bytes = [0u8; 32];
r_g_y.into_repr().write_le(& mut r_g_y_bytes[..]).expect("has serialized r_g_y");
let (pk_x, pk_y) = self.0.into_xy();
let mut pk_x_bytes = [0u8; 32];
pk_x.into_repr().write_le(& mut pk_x_bytes[..]).expect("has serialized pk_x");
let mut pk_y_bytes = [0u8; 32];
pk_y.into_repr().write_le(& mut pk_y_bytes[..]).expect("has serialized pk_y");
let concatenated: Vec<u8> = r_g_x_bytes.iter().chain(r_g_y_bytes.iter()).chain(pk_x_bytes.iter()).chain(pk_y_bytes.iter()).cloned().collect();
let c = h_star::<E>(&concatenated[..], msg);
let order_check_pk = self.0.mul(E::Fs::char(), params);
if !order_check_pk.eq(&Point::zero()) {
return false;
}
let order_check_r = sig.r.mul(E::Fs::char(), params);
if !order_check_r.eq(&Point::zero()) {
return false;
}
self.0.mul(c, params).add(&sig.r, params).add(
¶ms.generator(p_g).mul(sig.s, params).negate().into(),
params
).eq(&Point::zero())
}
pub fn verify_for_raw_message(
&self,
msg: &[u8],
sig: &Signature<E>,
p_g: FixedGenerators,
params: &E::Params,
max_message_size: usize,
) -> bool {
assert!(msg.len() <= max_message_size);
assert!(max_message_size * 8 <= E::Fs::CAPACITY as usize);
let mut msg_padded : Vec<u8> = msg.iter().cloned().collect();
msg_padded.resize(32, 0u8);
let c = E::Fs::to_uniform_32(msg_padded.as_ref());
let order_check_pk = self.0.mul(E::Fs::char(), params);
if !order_check_pk.eq(&Point::zero()) {
return false;
}
let order_check_r = sig.r.mul(E::Fs::char(), params);
if !order_check_r.eq(&Point::zero()) {
return false;
}
self.0.mul(c, params).add(&sig.r, params).add(
¶ms.generator(p_g).mul(sig.s, params).negate().into(),
params
).eq(&Point::zero())
}
pub fn verify_schnorr_blake2s(
&self,
msg: &[u8],
sig: &Signature<E>,
p_g: FixedGenerators,
params: &E::Params,
) -> bool {
let (r_g_x, _) = sig.r.into_xy();
let mut r_g_x_bytes = [0u8; 32];
r_g_x.into_repr().write_le(& mut r_g_x_bytes[..]).expect("has serialized r_g_x");
let concatenated: Vec<u8> = r_g_x_bytes.iter().cloned().collect();
let mut msg_padded : Vec<u8> = msg.iter().cloned().collect();
msg_padded.resize(32, 0u8);
let c = h_star_s::<E>(&concatenated[..], &msg_padded[..]);
let order_check_pk = self.0.mul(E::Fs::char(), params);
if !order_check_pk.eq(&Point::zero()) {
return false;
}
let order_check_r = sig.r.mul(E::Fs::char(), params);
if !order_check_r.eq(&Point::zero()) {
return false;
}
self.0.mul(c, params).add(&sig.r, params).add(
¶ms.generator(p_g).mul(sig.s, params).negate().into(),
params
).eq(&Point::zero())
}
pub fn verify_musig_sha256(
&self,
msg: &[u8],
sig: &Signature<E>,
p_g: FixedGenerators,
params: &E::Params,
) -> bool {
let (pk_x, _) = self.0.into_xy();
let mut pk_x_bytes = [0u8; 32];
pk_x.into_repr().write_le(& mut pk_x_bytes[..]).expect("has serialized pk_x");
let (r_g_x, _) = sig.r.into_xy();
let mut r_g_x_bytes = [0u8; 32];
r_g_x.into_repr().write_le(& mut r_g_x_bytes[..]).expect("has serialized r_g_x");
let mut concatenated: Vec<u8> = pk_x_bytes.as_ref().to_vec();
concatenated.extend(r_g_x_bytes.as_ref().to_vec().into_iter());
let mut msg_padded : Vec<u8> = msg.iter().cloned().collect();
msg_padded.resize(32, 0u8);
let c = sha256_h_star::<E>(&concatenated[..], &msg_padded[..]);
let order_check_pk = self.0.mul(E::Fs::char(), params);
if !order_check_pk.eq(&Point::zero()) {
return false;
}
let order_check_r = sig.r.mul(E::Fs::char(), params);
if !order_check_r.eq(&Point::zero()) {
return false;
}
self.0.mul(c, params).add(&sig.r, params).add(
¶ms.generator(p_g).mul(sig.s, params).negate().into(),
params
).eq(&Point::zero())
}
pub fn verify_serialized(
&self,
msg: &[u8],
sig: &SerializedSignature,
p_g: FixedGenerators,
params: &E::Params,
) -> bool {
let c = h_star::<E>(&sig.rbar[..], msg);
let r = match Point::read(&sig.rbar[..], params) {
Ok(r) => r,
Err(_) => return false,
};
let s = match read_scalar::<E, &[u8]>(&sig.sbar[..]) {
Ok(s) => s,
Err(_) => return false,
};
self.0.mul(c, params).add(&r, params).add(
¶ms.generator(p_g).mul(s, params).negate().into(),
params
).mul_by_cofactor(params).eq(&Point::zero())
}
}
#[cfg(test)]
mod baby_tests {
use bellman::pairing::bn256::Bn256;
use rand::thread_rng;
use alt_babyjubjub::{AltJubjubBn256, fs::Fs, edwards, FixedGenerators};
use super::*;
#[test]
fn cofactor_check() {
let rng = &mut thread_rng();
let params = &AltJubjubBn256::new();
let zero = edwards::Point::zero();
let p_g = FixedGenerators::SpendingKeyGenerator;
let p8 = loop {
let r = edwards::Point::<Bn256, _>::rand(rng, params).mul(Fs::char(), params);
let r2 = r.double(params);
let r4 = r2.double(params);
let r8 = r4.double(params);
if r2 != zero && r4 != zero && r8 == zero {
break r;
}
};
let sk = PrivateKey::<Bn256>(rng.gen());
let vk = PublicKey::from_private(&sk, p_g, params);
let msg = b"Foo bar";
let sig = sk.sign(msg, rng, p_g, params);
assert!(vk.verify(msg, &sig, p_g, params));
let vktorsion = PublicKey(vk.0.add(&p8, params));
assert!(!vktorsion.verify(msg, &sig, p_g, params));
}
#[test]
fn random_signatures() {
let rng = &mut thread_rng();
let p_g = FixedGenerators::SpendingKeyGenerator;
let params = &AltJubjubBn256::new();
for _ in 0..1000 {
let sk = PrivateKey::<Bn256>(rng.gen());
let vk = PublicKey::from_private(&sk, p_g, params);
let msg1 = b"Foo bar";
let msg2 = b"Spam eggs";
let sig1 = sk.sign(msg1, rng, p_g, params);
let sig2 = sk.sign(msg2, rng, p_g, params);
assert!(vk.verify(msg1, &sig1, p_g, params));
assert!(vk.verify(msg2, &sig2, p_g, params));
assert!(!vk.verify(msg1, &sig2, p_g, params));
assert!(!vk.verify(msg2, &sig1, p_g, params));
let alpha = rng.gen();
let rsk = sk.randomize(alpha);
let rvk = vk.randomize(alpha, p_g, params);
let sig1 = rsk.sign(msg1, rng, p_g, params);
let sig2 = rsk.sign(msg2, rng, p_g, params);
assert!(rvk.verify(msg1, &sig1, p_g, params));
assert!(rvk.verify(msg2, &sig2, p_g, params));
assert!(!rvk.verify(msg1, &sig2, p_g, params));
assert!(!rvk.verify(msg2, &sig1, p_g, params));
}
}
#[test]
fn random_signatures_for_snark() {
let rng = &mut thread_rng();
let p_g = FixedGenerators::SpendingKeyGenerator;
let params = &AltJubjubBn256::new();
for _ in 0..1000 {
let sk = PrivateKey::<Bn256>(rng.gen());
let vk = PublicKey::from_private(&sk, p_g, params);
let msg1 = b"Foo bar";
let msg2 = b"Spam eggs";
let sig1 = sk.sign_schnorr_blake2s(msg1, rng, p_g, params);
let sig2 = sk.sign_schnorr_blake2s(msg2, rng, p_g, params);
assert!(vk.verify_schnorr_blake2s(msg1, &sig1, p_g, params));
assert!(vk.verify_schnorr_blake2s(msg2, &sig2, p_g, params));
assert!(!vk.verify_schnorr_blake2s(msg1, &sig2, p_g, params));
assert!(!vk.verify_schnorr_blake2s(msg2, &sig1, p_g, params));
let alpha = rng.gen();
let rsk = sk.randomize(alpha);
let rvk = vk.randomize(alpha, p_g, params);
let sig1 = rsk.sign_schnorr_blake2s(msg1, rng, p_g, params);
let sig2 = rsk.sign_schnorr_blake2s(msg2, rng, p_g, params);
assert!(rvk.verify_schnorr_blake2s(msg1, &sig1, p_g, params));
assert!(rvk.verify_schnorr_blake2s(msg2, &sig2, p_g, params));
assert!(!rvk.verify_schnorr_blake2s(msg1, &sig2, p_g, params));
assert!(!rvk.verify_schnorr_blake2s(msg2, &sig1, p_g, params));
}
}
#[test]
fn random_signatures_for_raw_message() {
let rng = &mut thread_rng();
let p_g = FixedGenerators::SpendingKeyGenerator;
let params = &AltJubjubBn256::new();
for _ in 0..1000 {
let sk = PrivateKey::<Bn256>(rng.gen());
let vk = PublicKey::from_private(&sk, p_g, params);
let msg1 = b"Foo bar";
let msg2 = b"Spam eggs";
let max_message_size: usize = 16;
let sig1 = sk.sign_raw_message(msg1, rng, p_g, params, max_message_size);
let sig2 = sk.sign_raw_message(msg2, rng, p_g, params, max_message_size);
assert!(vk.verify_for_raw_message(msg1, &sig1, p_g, params, max_message_size));
assert!(vk.verify_for_raw_message(msg2, &sig2, p_g, params, max_message_size));
assert!(!vk.verify_for_raw_message(msg1, &sig2, p_g, params, max_message_size));
assert!(!vk.verify_for_raw_message(msg2, &sig1, p_g, params, max_message_size));
let alpha = rng.gen();
let rsk = sk.randomize(alpha);
let rvk = vk.randomize(alpha, p_g, params);
let sig1 = rsk.sign_raw_message(msg1, rng, p_g, params, max_message_size);
let sig2 = rsk.sign_raw_message(msg2, rng, p_g, params, max_message_size);
assert!(rvk.verify_for_raw_message(msg1, &sig1, p_g, params, max_message_size));
assert!(rvk.verify_for_raw_message(msg2, &sig2, p_g, params, max_message_size));
assert!(!rvk.verify_for_raw_message(msg1, &sig2, p_g, params, max_message_size));
assert!(!rvk.verify_for_raw_message(msg2, &sig1, p_g, params, max_message_size));
}
}
#[test]
fn random_signatures_for_sha256_musig() {
let rng = &mut thread_rng();
let p_g = FixedGenerators::SpendingKeyGenerator;
let params = &AltJubjubBn256::new();
for _ in 0..1000 {
let sk = PrivateKey::<Bn256>(rng.gen());
let vk = PublicKey::from_private(&sk, p_g, params);
let msg1 = b"Foo bar";
let msg2 = b"Spam eggs";
let max_message_size: usize = 16;
let sig1 = sk.musig_sha256_sign(msg1, rng, p_g, params);
let sig2 = sk.musig_sha256_sign(msg2, rng, p_g, params);
assert!(vk.verify_musig_sha256(msg1, &sig1, p_g, params));
assert!(vk.verify_musig_sha256(msg2, &sig2, p_g, params));
assert!(!vk.verify_musig_sha256(msg1, &sig2, p_g, params));
assert!(!vk.verify_musig_sha256(msg2, &sig1, p_g, params));
let alpha = rng.gen();
let rsk = sk.randomize(alpha);
let rvk = vk.randomize(alpha, p_g, params);
let sig1 = rsk.musig_sha256_sign(msg1, rng, p_g, params);
let sig2 = rsk.musig_sha256_sign(msg2, rng, p_g, params);
assert!(rvk.verify_musig_sha256(msg1, &sig1, p_g, params));
assert!(rvk.verify_musig_sha256(msg2, &sig2, p_g, params));
assert!(!rvk.verify_musig_sha256(msg1, &sig2, p_g, params));
assert!(!rvk.verify_musig_sha256(msg2, &sig1, p_g, params));
}
}
#[test]
fn get_generator_for_signatures() {
let rng = &mut thread_rng();
let p_g = FixedGenerators::SpendingKeyGenerator;
let params = &AltJubjubBn256::new();
let s = <Bn256 as JubjubEngine>::Fs::one();
let sk = PrivateKey::<Bn256>(s);
let vk = PublicKey::from_private(&sk, p_g, params);
let (x, y) = vk.0.into_xy();
println!("Public generator x = {}, y = {}", x, y);
}
}