witnet-bn 0.5.1

Pairing cryptography with the Barreto-Naehrig curve
Documentation
mod fp;
mod fq12;
mod fq2;
mod fq6;

use crate::arith::U256;
use alloc::fmt::Debug;
use core::ops::{Add, Mul, Neg, Sub};
use rand::Rng;

pub use self::{
    fp::{Fq, Fr, const_fq},
    fq2::{Fq2, fq2_nonresidue},
    fq6::Fq6,
    fq12::Fq12,
};

pub trait FieldElement:
    Sized
    + Copy
    + Clone
    + Add<Output = Self>
    + Sub<Output = Self>
    + Mul<Output = Self>
    + Neg<Output = Self>
    + PartialEq
    + Eq
    + Debug
{
    fn zero() -> Self;
    fn one() -> Self;
    fn random<R: Rng>(_: &mut R) -> Self;
    fn is_zero(&self) -> bool;
    fn squared(&self) -> Self {
        (*self) * (*self)
    }
    fn inverse(self) -> Option<Self>;
    fn pow<I: Into<U256>>(&self, by: I) -> Self {
        let mut res = Self::one();

        for i in by.into().bits() {
            res = res.squared();
            if i {
                res = *self * res;
            }
        }

        res
    }
}

#[cfg(test)]
mod tests;

#[test]
fn test_fr() {
    tests::field_trials::<Fr>();
}

#[test]
fn test_fq() {
    tests::field_trials::<Fq>();
}

#[test]
fn test_fq2() {
    tests::field_trials::<Fq2>();
}

#[test]
fn test_str() {
    assert_eq!(
        -Fr::one(),
        Fr::from_str(
            "21888242871839275222246405745257275088548364400416034343698204186575808495616"
        )
        .unwrap()
    );
    assert_eq!(
        -Fq::one(),
        Fq::from_str(
            "21888242871839275222246405745257275088696311157297823662689037894645226208582"
        )
        .unwrap()
    );
}

#[test]
fn test_fq6() {
    tests::field_trials::<Fq6>();
}

#[test]
fn test_fq12() {
    tests::field_trials::<Fq12>();
}

#[test]
fn fq12_test_vector() {
    let start = Fq12::new(
        Fq6::new(
            Fq2::new(
                Fq::from_str(
                    "19797905000333868150253315089095386158892526856493194078073564469188852136946",
                )
                .unwrap(),
                Fq::from_str(
                    "10509658143212501778222314067134547632307419253211327938344904628569123178733",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "208316612133170645758860571704540129781090973693601051684061348604461399206",
                )
                .unwrap(),
                Fq::from_str(
                    "12617661120538088237397060591907161689901553895660355849494983891299803248390",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "2897490589776053688661991433341220818937967872052418196321943489809183508515",
                )
                .unwrap(),
                Fq::from_str(
                    "2730506433347642574983433139433778984782882168213690554721050571242082865799",
                )
                .unwrap(),
            ),
        ),
        Fq6::new(
            Fq2::new(
                Fq::from_str(
                    "17870056122431653936196746815433147921488990391314067765563891966783088591110",
                )
                .unwrap(),
                Fq::from_str(
                    "14314041658607615069703576372547568077123863812415914883625850585470406221594",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "10123533891707846623287020000407963680629966110211808794181173248765209982878",
                )
                .unwrap(),
                Fq::from_str(
                    "5062091880848845693514855272640141851746424235009114332841857306926659567101",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "9839781502639936537333620974973645053542086898304697594692219798017709586567",
                )
                .unwrap(),
                Fq::from_str(
                    "1583892292110602864638265389721494775152090720173641072176370350017825640703",
                )
                .unwrap(),
            ),
        ),
    );

    // Do a bunch of arbitrary stuff to the element

    let mut next = start.clone();
    for _ in 0..100 {
        next = next * start;
    }

    let cpy = next.clone();

    for _ in 0..10 {
        next = next.squared();
    }

    for _ in 0..10 {
        next = next + start;
        next = next - cpy;
        next = -next;
    }

    next = next.squared();

    let finally = Fq12::new(
        Fq6::new(
            Fq2::new(
                Fq::from_str(
                    "18388750939593263065521177085001223024106699964957029146547831509155008229833",
                )
                .unwrap(),
                Fq::from_str(
                    "18370529854582635460997127698388761779167953912610241447912705473964014492243",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "3691824277096717481466579496401243638295254271265821828017111951446539785268",
                )
                .unwrap(),
                Fq::from_str(
                    "20513494218085713799072115076991457239411567892860153903443302793553884247235",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "12214155472433286415803224222551966441740960297013786627326456052558698216399",
                )
                .unwrap(),
                Fq::from_str(
                    "10987494248070743195602580056085773610850106455323751205990078881956262496575",
                )
                .unwrap(),
            ),
        ),
        Fq6::new(
            Fq2::new(
                Fq::from_str(
                    "5134522153456102954632718911439874984161223687865160221119284322136466794876",
                )
                .unwrap(),
                Fq::from_str(
                    "20119236909927036376726859192821071338930785378711977469360149362002019539920",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "8839766648621210419302228913265679710586991805716981851373026244791934012854",
                )
                .unwrap(),
                Fq::from_str(
                    "9103032146464138788288547957401673544458789595252696070370942789051858719203",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "10378379548636866240502412547812481928323945124508039853766409196375806029865",
                )
                .unwrap(),
                Fq::from_str(
                    "9021627154807648093720460686924074684389554332435186899318369174351765754041",
                )
                .unwrap(),
            ),
        ),
    );

    assert_eq!(finally, next);
}

#[test]
fn test_cyclotomic_exp() {
    let orig = Fq12::new(
        Fq6::new(
            Fq2::new(
                Fq::from_str(
                    "2259924035228092997691937637688451143058635253053054071159756458902878894295",
                )
                .unwrap(),
                Fq::from_str(
                    "13145690032701362144460254305183927872683620413225364127064863863535255135244",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "9910063591662383599552477067956819406417086889312288278252482503717089428441",
                )
                .unwrap(),
                Fq::from_str(
                    "537414042055419261990282459138081732565514913399498746664966841152381183961",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "15311812409497308894370893420777496684951030254049554818293571309705780605004",
                )
                .unwrap(),
                Fq::from_str(
                    "13657107176064455789881282546557276003626320193974643644160350907227082365810",
                )
                .unwrap(),
            ),
        ),
        Fq6::new(
            Fq2::new(
                Fq::from_str(
                    "4913017949003742946864670837361832856526234260447029873580022776602534856819",
                )
                .unwrap(),
                Fq::from_str(
                    "7834351480852267338070670220119081676575418514182895774094743209915633114041",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "12837298223308203788092748646758194441270207338661891973231184407371206766993",
                )
                .unwrap(),
                Fq::from_str(
                    "12756474445699147370503225379431475413909971718057034061593007812727141391799",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "9473802207170192255373153510655867502408045964296373712891954747252332944018",
                )
                .unwrap(),
                Fq::from_str(
                    "4583089109360519374075173304035813179013579459429335467869926761027310749713",
                )
                .unwrap(),
            ),
        ),
    );

    let expected = Fq12::new(
        Fq6::new(
            Fq2::new(
                Fq::from_str(
                    "14722956046055152398903846391223329501345567382234608299399030576415080188350",
                )
                .unwrap(),
                Fq::from_str(
                    "14280703280777926697010730619606819467080027543707671882210769811674790473417",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "19969875076083990244184003223190771301761436396530543002586073549972410735411",
                )
                .unwrap(),
                Fq::from_str(
                    "10717335566913889643303549252432531178405520196706173198634734518494041323243",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "6063612626166484870786832843320782567259894784043383626084549455432890717937",
                )
                .unwrap(),
                Fq::from_str(
                    "17089783040131779205038789608891431427943860868115199598200376195935079808729",
                )
                .unwrap(),
            ),
        ),
        Fq6::new(
            Fq2::new(
                Fq::from_str(
                    "10029863438921507421569931792104023129735006154272482043027653425575205672906",
                )
                .unwrap(),
                Fq::from_str(
                    "6406252222753462799887280578845937185621081001436094637606245493619821542775",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "1048245462913506652602966692378792381004227332967846949234978073448561848050",
                )
                .unwrap(),
                Fq::from_str(
                    "1444281375189053827455518242624554285012408033699861764136810522738182087554",
                )
                .unwrap(),
            ),
            Fq2::new(
                Fq::from_str(
                    "8839610992666735109106629514135300820412539620261852250193684883379364789120",
                )
                .unwrap(),
                Fq::from_str(
                    "11347360242067273846784836674906058940820632082713814508736182487171407730718",
                )
                .unwrap(),
            ),
        ),
    );

    let e = orig.exp_by_neg_z();

    assert_eq!(e, expected);
}