hacspec-lib 0.1.0-beta.1

The hacspec library.
Documentation
#![allow(non_snake_case)]

use hacspec_lib::prelude::*;
mod test_util;
use test_util::*;

macro_rules! compare_secret {
    ($a:expr,$b:expr) => {
        assert_eq!($a.declassify(), $b);
    };
}

macro_rules! test_integer_macro {
    ($t:ty,$true_val:expr,$false_val:expr,$check:ident) => {
        let (a, a_t, b, b_t) = get_random_numbers::<$t>();
        println!("a:   {} | b:   {}", a, b);
        println!("a_t: {:x} | b_t: {:x}", a_t, b_t);

        println!(" Test modulo");
        if !b_t.equal(<$t>::default()) {
            let r = a_t.modulo(b_t);
            let expected = get_expected("%", &a, &b);
            assert_eq!(format!("0x{:x}", r), expected);
        }

        // Comparison functions returning bool.
        println!(" Test equal");
        assert_eq!(a_t.equal(b_t), a == b);
        assert!(a_t.equal(a_t));
        assert!(b_t.equal(b_t));
        let expected_gt = if get_expected(">", &a, &b) == "0x0" {
            false
        } else {
            true
        };
        println!(" Test greater_than");
        assert_eq!(a_t.greater_than(b_t), expected_gt);
        assert_eq!(a_t.greater_than(a_t), false);
        assert_eq!(b_t.greater_than(b_t), false);
        let expected_gte = if get_expected(">=", &a, &b) == "0x0" {
            false
        } else {
            true
        };
        println!(" Test greater_than_or_equal");
        assert_eq!(a_t.greater_than_or_equal(b_t), expected_gte);
        assert_eq!(a_t.greater_than_or_equal(a_t), true);
        assert_eq!(b_t.greater_than_or_equal(b_t), true);
        let expected_lt = if get_expected("<", &a, &b) == "0x0" {
            false
        } else {
            true
        };
        println!(" Test less_than");
        assert_eq!(a_t.less_than(b_t), expected_lt);
        assert_eq!(a_t.less_than(a_t), false);
        assert_eq!(b_t.less_than(b_t), false);
        let expected_lte = if get_expected("<=", &a, &b) == "0x0" {
            false
        } else {
            true
        };
        println!(" Test less_than_or_equal");
        assert_eq!(a_t.less_than_or_equal(b_t), expected_lte);
        assert_eq!(a_t.less_than_or_equal(a_t), true);
        assert_eq!(b_t.less_than_or_equal(b_t), true);

        // Comparison functions returning a bit mask (0x0..0 or 0xF..F).
        let expected = if a == b { $true_val } else { $false_val };
        println!(" Test equal_bm");
        $check!(a_t.equal_bm(b_t), expected);
        $check!(a_t.equal_bm(a_t), $true_val);
        $check!(b_t.equal_bm(b_t), $true_val);
        let expected = if expected_gt { $true_val } else { $false_val };
        println!(" Test greater_than_bm");
        $check!(a_t.greater_than_bm(b_t), expected);
        $check!(a_t.greater_than_bm(a_t), $false_val);
        $check!(b_t.greater_than_bm(b_t), $false_val);
        let expected = if expected_gte { $true_val } else { $false_val };
        println!(" Test greater_than_or_equal_bm");
        $check!(a_t.greater_than_or_equal_bm(b_t), expected);
        $check!(a_t.greater_than_or_equal_bm(a_t), $true_val);
        $check!(b_t.greater_than_or_equal_bm(b_t), $true_val);
        let expected = if expected_lt { $true_val } else { $false_val };
        println!(" Test less_than_bm");
        $check!(a_t.less_than_bm(b_t), expected);
        $check!(a_t.less_than_bm(a_t), $false_val);
        $check!(b_t.less_than_bm(b_t), $false_val);
        let expected = if expected_lte { $true_val } else { $false_val };
        println!(" Test less_than_or_equal_bm");
        $check!(a_t.less_than_or_equal_bm(b_t), expected);
        $check!(a_t.less_than_or_equal_bm(a_t), $true_val);
        $check!(b_t.less_than_or_equal_bm(b_t), $true_val);
    };
}

macro_rules! generate_test {
    ($t:ty,$name:ident,$true_val:expr,$false_val:expr,$check:ident) => {
        #[test]
        fn $name() {
            test_integer_macro!($t, $true_val, $false_val, $check);
        }
    };
}

// Public machine integers
generate_test!(u8, test_u8_integer, u8::max_value(), 0, assert_eq);
generate_test!(u16, test_u16_integer, u16::max_value(), 0, assert_eq);
generate_test!(u32, test_u32_integer, u32::max_value(), 0, assert_eq);
generate_test!(u64, test_u64_integer, u64::max_value(), 0, assert_eq);
generate_test!(u128, test_u128_integer, u128::max_value(), 0, assert_eq);
generate_test!(i8, test_i8_integer, -1, 0, assert_eq);
generate_test!(i16, test_i16_integer, -1, 0, assert_eq);
generate_test!(i32, test_i32_integer, -1, 0, assert_eq);
generate_test!(i64, test_i64_integer, -1, 0, assert_eq);
generate_test!(i128, test_i128_integer, -1, 0, assert_eq);

// Secret machine integers
generate_test!(
    U8,
    test_U8_integer,
    U8::max_value().declassify(),
    0,
    compare_secret
);
generate_test!(
    U16,
    test_U16_integer,
    U16::max_value().declassify(),
    0,
    compare_secret
);
generate_test!(
    U32,
    test_U32_integer,
    U32::max_value().declassify(),
    0,
    compare_secret
);
generate_test!(
    U64,
    test_U64_integer,
    U64::max_value().declassify(),
    0,
    compare_secret
);
generate_test!(
    U128,
    test_U128_integer,
    U128::max_value().declassify(),
    0,
    compare_secret
);
generate_test!(I8, test_I8_integer, -1, 0, compare_secret);
generate_test!(I16, test_I16_integer, -1, 0, compare_secret);
generate_test!(I32, test_I32_integer, -1, 0, compare_secret);
generate_test!(I64, test_I64_integer, -1, 0, compare_secret);
generate_test!(I128, test_I128_integer, -1, 0, compare_secret);

// Math integers

// Public natural numbers modulo p
public_nat_mod!(
    type_name: PublicP256Elem,
    type_of_canvas: PublicP256Canvas,
    bit_size_of_field: 256,
    modulo_value: "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"
);
generate_test!(
    PublicP256Elem,
    test_PublicNatMod_integer,
    PublicP256Elem::from_hex_string(
        &"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string()
    ),
    PublicP256Elem::ZERO(),
    assert_eq
);

// Secret natural numbers modulo p
nat_mod!(
    type_name: P256Elem,
    type_of_canvas: P256Canvas,
    bit_size_of_field: 256,
    modulo_value: "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"
);
generate_test!(
    P256Elem,
    test_NatMod_integer,
    BigInt::from_str_radix(
        "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
        16
    )
    .unwrap(),
    BigInt::from(0),
    compare_secret
);

// vec integer tests

#[test]
fn test_byte_array_integer() {
    bytes!(State, 8);
    fn test(a: [u8; 8], b: [u8; 8], result: bool) {
        let a = State::from_public_array(a);
        let b = State::from_public_array(b);
        assert_eq!(a.equal(b), result);
    }

    test(
        [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
        [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
        true,
    );
    test(
        [0x11, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
        [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
        false,
    );
    test(
        [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
        [0x11, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
        false,
    );
    test(
        [0x12, 0x34, 0x56, 0x78, 0x91, 0xab, 0xcd, 0xef],
        [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
        false,
    );
    test(
        [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
        [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xee],
        false,
    );
    test(
        [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xee],
        [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
        false,
    );
}