1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#![cfg_attr(not(feature = "std"), no_std)]

use fr::FrElement;
use rand_core::CryptoRngCore;
use cryptix_bigint::property::IsBigInt;
use cryptix_ecc::CurvePoint;
use cryptix_pairing::Pairing;
use cryptix_field::field::{montgomery::MontgomeryOps, MulInverse};
use cryptix_bn254::{pairing::{e1::BN254Fp, e2::BN254Fp2, o_ate::OptimalAte}, galoisfield::{U256, fp12::Fp12Element}};
use sha2::Digest;

pub mod fr;

#[derive(Debug)]
pub struct BLMQ<R: CryptoRngCore> {
    msk: FrElement,
    g: Fp12Element,
    p_pub: BN254Fp2,
    rng: R
}

#[derive(Debug, Clone, Copy)]
pub struct Sigma {
    pub h: FrElement,
    pub s: BN254Fp
}

impl<R: CryptoRngCore> BLMQ<R> {
    pub fn new(mut rng: R) -> Self {
        let msk = FrElement::rand(&mut rng);
        Self { 
            msk, rng,
            p_pub: BN254Fp2::GENERATOR.scalar_mul(msk.repr()).normalize(),
            g: OptimalAte::pairing(BN254Fp::GENERATOR, BN254Fp2::GENERATOR)
        }
    }

    /// returns (pk, sk)
    pub fn extract(&self, id: &[u8]) -> (FrElement, BN254Fp) {
        let pk = Self::hash_to_field(id);
        let t = (pk + self.msk).mont_form().mont_inv().mont_rdc();
        let sk = BN254Fp::GENERATOR.scalar_mul(t.repr()).normalize();

        debug_assert!(sk.on_curve(), "dID not on curve!");
        (t, sk)
    }

    fn hash_to_field(buf: &[u8]) -> FrElement {
        let hash = sha2::Sha256::digest(buf);
        U256::from_bytes(&hash).into()
    }

    fn msg_hash_field(u: Fp12Element, msg: &[u8]) -> FrElement {
        const HASH_LEN: usize = 32;
        const FP12_BYTE_LEN: usize = U256::BYTE_LEN * 12;
        const BUF_LEN: usize = FP12_BYTE_LEN + HASH_LEN;

        let mut buf = [0_u8; BUF_LEN];
        let hash = sha2::Sha256::digest(msg);
        let u_bytes: [u8; FP12_BYTE_LEN] = u.into();
        buf[..FP12_BYTE_LEN].copy_from_slice(&u_bytes);
        buf[FP12_BYTE_LEN..BUF_LEN].copy_from_slice(&hash);
        Self::hash_to_field(&buf)
    }

    pub fn sign(&mut self, sk: BN254Fp, msg: &[u8]) -> Sigma {
        let r = FrElement::rand(&mut self.rng);
        let u = self.g.mont_rdc().mont_exp(r.repr());

        let h = Self::msg_hash_field(u, msg);
        let t = h + r;
        let s = sk.scalar_mul(t.repr()).normalize();
        debug_assert!(s.on_curve(), "S not on curve");

        Sigma { h, s }
    }

    /// e(Q_1, Q_2)^r e(Q_1, Q_2)^h = e(S, MQ_2 + R)
    /// S = (r + h)(M + s)^-1Q_1
    pub fn verify(&self, sig: &Sigma, id: &[u8], msg: &[u8]) -> bool {
        let pk = Self::hash_to_field(id);
        let w = self.g.mont_rdc().mont_exp(sig.h.repr()).mul_inv();

        let u = OptimalAte::pairing(
            sig.s, 
            (BN254Fp2::GENERATOR.scalar_mul(pk.repr()) + self.p_pub).normalize()
        ).mont_mul(w);

        //   e(SM, Q_2)e(S, R)
        // = e(S, Q_2)^Me(S, R)
        // = e(S, MQ_2)e(S, R)
        // = e(S, MQ_2 + R)
        // let u = OptimalAte::pairing(r, E2Point::GENERATOR);
        // let v = OptimalAte::pairing(sig.s, self.p_pub);

        // let u = u.mont_mul(v).mont_mul(w).mont_rdc();
        let h = Self::msg_hash_field(u, msg);

        h == sig.h
    }
}