use bls12_381::{G1Affine, G1Projective, G2Affine, G2Projective, Scalar};
use ff::Field;
use rand_core::RngCore;
pub type SecretKey = Scalar;
#[derive(Copy, Clone, Debug, PartialEq, Default)]
pub struct PublicKey {
pub g1: G1Affine,
pub h1: G1Affine,
pub u1: G1Affine,
pub v1: G1Affine,
pub g2: G2Affine,
pub h2: G2Affine,
pub u2: G2Affine,
pub v2: G2Affine,
pub w2: G2Affine,
}
pub struct KeyPair {
pub public_key: PublicKey,
secret_key: SecretKey,
}
impl KeyPair {
pub fn generate(mut rng: impl RngCore) -> KeyPair {
let secret_key: SecretKey = Scalar::random(&mut rng);
let mut public_key = PublicKey::default();
let mut g1_r: Scalar;
let mut h1_r: Scalar;
let mut u1_r: Scalar;
let mut v1_r: Scalar;
loop {
g1_r = Scalar::random(&mut rng);
if g1_r.is_zero().into() {
continue;
}
public_key.g1 = G1Affine::from(G1Affine::generator() * g1_r);
if public_key.g1 == G1Affine::generator() {
continue;
}
break;
}
loop {
h1_r = Scalar::random(&mut rng);
if h1_r.is_zero().into() {
continue;
}
public_key.h1 = G1Affine::from(G1Affine::generator() * h1_r);
if public_key.h1 == G1Affine::generator() {
continue;
}
if public_key.h1 != public_key.g1 {
break;
}
}
loop {
u1_r = Scalar::random(&mut rng);
if u1_r.is_zero().into() {
continue;
}
public_key.u1 = G1Affine::from(G1Affine::generator() * u1_r);
if public_key.u1 == G1Affine::generator() {
continue;
}
if public_key.u1 != public_key.g1 && public_key.u1 != public_key.h1 {
break;
}
}
loop {
v1_r = Scalar::random(&mut rng);
if v1_r.is_zero().into() {
continue;
}
public_key.v1 = G1Affine::from(G1Affine::generator() * v1_r);
if public_key.v1 == G1Affine::generator() {
continue;
}
if public_key.v1 != public_key.g1 && public_key.v1 != public_key.h1 && public_key.v1 != public_key.u1 {
break;
}
}
public_key.g2 = G2Affine::from(G2Projective::generator() * g1_r);
public_key.h2 = G2Affine::from(G2Projective::generator() * h1_r);
public_key.u2 = G2Affine::from(G2Projective::generator() * u1_r);
public_key.v2 = G2Affine::from(G2Projective::generator() * v1_r);
public_key.w2 = G2Affine::from(public_key.g2 * secret_key);
let key_pair = KeyPair { secret_key, public_key };
key_pair
}
}
#[derive(Debug)]
pub enum Error {
InvalidState,
InvalidSignature,
PointNotOnCurve,
InvalidWitness,
ScalarIsZero,
}
pub enum SignerState {
ReadyToSetMessage,
ReadyToCommit,
ReadyToVerifyWitness,
ReadyToSign,
Signed,
Aborted,
}
#[allow(non_snake_case)]
#[allow(dead_code)]
pub struct Signer<'a, R: RngCore> {
key_pair: &'a KeyPair,
rng: R,
state: SignerState,
m0: Scalar,
W: G1Projective,
X: G1Projective,
#[cfg(test)]
l: Scalar,
#[cfg(test)]
r: Scalar,
eta: Scalar,
#[cfg(test)]
b1: Scalar,
#[cfg(test)]
b2: Scalar,
#[cfg(test)]
b3: Scalar,
}
impl<'a, R: RngCore> Signer<'a, R> {
pub fn new(key_pair: &'a KeyPair, rng: R) -> Self {
Self {
key_pair,
rng,
state: SignerState::ReadyToSetMessage,
m0: Scalar::zero(),
W: Default::default(),
X: Default::default(),
#[cfg(test)]
l: Default::default(),
#[cfg(test)]
r: Default::default(),
eta: Default::default(),
#[cfg(test)]
b1: Default::default(),
#[cfg(test)]
b2: Default::default(),
#[cfg(test)]
b3: Default::default(),
}
}
pub fn get_state(&self) -> &SignerState {
&self.state
}
pub fn set_message(&mut self, m0: Scalar) -> Result<(), Error> {
match self.state {
SignerState::ReadyToSetMessage => {}
_ => return Err(Error::InvalidState),
}
self.m0 = m0;
self.state = SignerState::ReadyToCommit;
Ok(())
}
#[allow(non_snake_case)]
pub fn commit(&mut self, W: G1Affine, X: G1Affine) -> Result<&Scalar, Error> {
match self.state {
SignerState::ReadyToCommit => {}
_ => return Err(Error::InvalidState),
}
if !bool::from(W.is_on_curve()) || !bool::from(X.is_on_curve()) {
self.state = SignerState::Aborted;
return Err(Error::PointNotOnCurve);
}
self.eta = Scalar::random(&mut self.rng);
self.W = G1Projective::from(W);
self.X = G1Projective::from(X);
self.state = SignerState::ReadyToVerifyWitness;
Ok(&self.eta)
}
pub fn verify_witness(&mut self, b1: Scalar, b2: Scalar, b3: Scalar) -> Result<(), Error> {
match self.state {
SignerState::ReadyToVerifyWitness => {}
_ => return Err(Error::InvalidState),
}
let pk = &self.key_pair.public_key;
let rhs = self.W + self.X * self.eta;
let lhs = pk.h1 * (self.m0 * b2) + pk.g1 * b1 + pk.u1 * b2 + pk.v1 * b3;
if rhs != lhs {
self.state = SignerState::Aborted;
return Err(Error::InvalidWitness);
}
self.state = SignerState::ReadyToSign;
Ok(())
}
pub fn sign(&mut self) -> Result<(G1Affine, G2Affine, Scalar), Error> {
match self.state {
SignerState::ReadyToSign => {}
_ => return Err(Error::InvalidState),
}
let pk = &self.key_pair.public_key;
let l = Scalar::random(&mut self.rng);
let r = Scalar::random(&mut self.rng);
#[allow(non_snake_case)]
let R = pk.g2 * r;
#[allow(non_snake_case)]
let Y = (self.X + (pk.v1 * l)) * (self.key_pair.secret_key + r).invert().unwrap();
#[cfg(test)]
{
self.l = l;
self.r = r;
}
self.state = SignerState::Signed;
Ok((G1Affine::from(Y), G2Affine::from(R), l))
}
pub fn abort(&mut self) {
self.state = SignerState::Aborted
}
}
pub enum UserState {
ReadyToSetMessage,
ReadyToCommit,
ReadyToComputeWitness,
ReadyToSign,
Signed,
Aborted,
}
#[allow(non_snake_case)]
pub struct User<'a, R: RngCore> {
public_key: &'a PublicKey,
state: UserState,
rng: R,
m0: Scalar,
m1: Scalar,
a1: Scalar,
a2: Scalar,
a3: Scalar,
#[cfg(test)]
f: Scalar,
s: Scalar,
t: Scalar,
#[cfg(test)]
W: G1Projective,
#[cfg(test)]
X: G1Projective,
}
impl<'a, R: RngCore> User<'a, R> {
pub fn new(public_key: &'a PublicKey, rng: R) -> Self {
Self {
public_key,
state: UserState::ReadyToSetMessage,
rng,
m0: Default::default(),
m1: Default::default(),
a1: Default::default(),
a2: Default::default(),
a3: Default::default(),
#[cfg(test)]
f: Default::default(),
s: Default::default(),
t: Default::default(),
#[cfg(test)]
X: Default::default(),
#[cfg(test)]
W: Default::default(),
}
}
pub fn get_state(&self) -> &UserState {
&self.state
}
pub fn set_message(&mut self, m0: Scalar, m1: Scalar) -> Result<(), Error> {
match self.state {
UserState::ReadyToSetMessage => {}
_ => return Err(Error::InvalidState),
}
if m0.is_zero().into() || m1.is_zero().into() {
return Err(Error::ScalarIsZero);
}
self.m0 = m0;
self.m1 = m1;
self.state = UserState::ReadyToCommit;
Ok(())
}
pub fn commit(&mut self) -> Result<(G1Affine, G1Affine), Error> {
match self.state {
UserState::ReadyToCommit => {}
_ => return Err(Error::InvalidState),
}
let a1 = Scalar::random(&mut self.rng);
let a2 = Scalar::random(&mut self.rng);
let a3 = Scalar::random(&mut self.rng);
let s = Scalar::random(&mut self.rng);
let t = Scalar::random(&mut self.rng);
let pk = &self.public_key;
#[allow(non_snake_case)]
let X = pk.h1 * (self.m0 * t) + pk.g1 * (self.m1 * t) + pk.u1 * t + pk.v1 * (s * t);
#[allow(non_snake_case)]
let W = pk.h1 * (self.m0 * a2) + pk.g1 * a1 + pk.u1 * a2 + pk.v1 * a3;
#[cfg(test)]
{
self.X = X.clone();
self.W = W.clone();
}
self.a1 = a1;
self.a2 = a2;
self.a3 = a3;
self.t = t;
self.s = s;
self.state = UserState::ReadyToComputeWitness;
Ok((G1Affine::from(W), G1Affine::from(X)))
}
pub fn compute_witness(&mut self, eta: &Scalar) -> Result<(Scalar, Scalar, Scalar), Error> {
match self.state {
UserState::ReadyToComputeWitness => {}
_ => return Err(Error::InvalidState),
}
let b1 = self.a1 + eta * self.m1 * self.t;
let b2 = self.a2 + eta * self.t;
let b3 = self.a3 + eta * self.s * self.t;
self.state = UserState::ReadyToSign;
Ok((b1, b2, b3))
}
#[allow(non_snake_case)]
pub fn sign(&mut self, Y: &G1Affine, R: &G2Affine, l: &Scalar) -> Result<(G1Affine, G2Affine, Scalar), Error> {
match self.state {
UserState::ReadyToSign => {}
_ => return Err(Error::InvalidState),
}
let pk = &self.public_key;
let f = Scalar::random(&mut self.rng);
let tau = (f * self.t).invert().unwrap();
let sigma = Y * tau;
let alpha = pk.w2 * (f - Scalar::one()) + (R * f);
let beta = self.s + l * self.t.invert().unwrap();
#[cfg(test)]
{
self.f = f;
}
self.state = UserState::Signed;
Ok((G1Affine::from(sigma), G2Affine::from(alpha), beta))
}
pub fn abort(&mut self) {
self.state = UserState::Aborted;
}
}
pub fn verify_signature(
public_key: &PublicKey,
m0: &Scalar,
m1: &Scalar,
sigma: &G1Affine,
alpha: &G2Affine,
beta: &Scalar,
) -> Result<(), Error> {
let lhs2 = G2Affine::from(G2Projective::from(public_key.w2) + alpha);
let rhs2 = G2Affine::from(public_key.h2 * m0 + public_key.g2 * m1 + public_key.u2 + public_key.v2 * beta);
let lhs = bls12_381::pairing(&sigma, &lhs2);
let rhs = bls12_381::pairing(&public_key.g1, &rhs2);
if sigma == &G1Affine::identity() {
return Err(Error::InvalidSignature);
}
if !bool::from(sigma.is_on_curve()) {
return Err(Error::InvalidSignature);
}
if !bool::from(alpha.is_on_curve()) {
return Err(Error::InvalidSignature);
}
if lhs != rhs {
return Err(Error::InvalidSignature);
}
Ok(())
}
#[cfg(test)]
mod tests;