You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@milagro.apache.org by km...@apache.org on 2019/12/13 16:34:13 UTC
[incubator-milagro-crypto-rust] 15/18: Duplicate tests in cargo test
This is an automated email from the ASF dual-hosted git repository.
kmccusker pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto-rust.git
commit de198225b44463a96b48e3bc6b5fc4494e86628d
Author: Kirk Baird <ba...@outlook.com>
AuthorDate: Fri Dec 13 17:18:41 2019 +1100
Duplicate tests in cargo test
Signed-off-by: Kirk Baird <ba...@outlook.com>
---
tests/test_all.rs | 1473 +++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/test_bls.rs | 190 +++++++
tests/test_nhs.rs | 71 +++
3 files changed, 1734 insertions(+)
diff --git a/tests/test_all.rs b/tests/test_all.rs
new file mode 100644
index 0000000..c543dac
--- /dev/null
+++ b/tests/test_all.rs
@@ -0,0 +1,1473 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+extern crate amcl;
+
+use std::io;
+use std::str;
+
+use amcl::rand::RAND;
+use amcl::types::CurveType;
+
+pub fn printbinary(array: &[u8]) {
+ for i in 0..array.len() {
+ print!("{:02X}", array[i])
+ }
+ println!("")
+}
+
+fn create_rng() -> RAND {
+ let mut raw: [u8; 100] = [0; 100];
+
+ let mut rng = RAND::new();
+ rng.clean();
+ for i in 0..100 {
+ raw[i] = i as u8
+ }
+
+ rng.seed(100, &raw);
+ rng
+}
+
+#[test]
+fn ecdh_ed25519() {
+ //use amcl::ed25519;
+ use amcl::ed25519::ecdh;
+ use amcl::ed25519::ecp;
+
+ let mut rng = create_rng();
+
+ let pw = "M0ng00se";
+ let pp: &[u8] = b"M0ng00se";
+ const EFS: usize = ecdh::EFS;
+ const EGS: usize = ecdh::EGS;
+ const EAS: usize = ecp::AESKEY;
+
+ let sha = ecp::HASH_TYPE;
+ let mut salt: [u8; 8] = [0; 8];
+ let mut s1: [u8; EGS] = [0; EGS];
+ let mut w0: [u8; 2 * EFS + 1] = [0; 2 * EFS + 1];
+ let mut w1: [u8; 2 * EFS + 1] = [0; 2 * EFS + 1];
+ let mut z0: [u8; EFS] = [0; EFS];
+ let mut z1: [u8; EFS] = [0; EFS];
+ let mut key: [u8; EAS] = [0; EAS];
+ let mut cs: [u8; EGS] = [0; EGS];
+ let mut ds: [u8; EGS] = [0; EGS];
+ let mut m: Vec<u8> = vec![0; 32]; // array that could be of any length. So use heap.
+ let mut p1: [u8; 3] = [0; 3];
+ let mut p2: [u8; 4] = [0; 4];
+ let mut v: [u8; 2 * EFS + 1] = [0; 2 * EFS + 1];
+ let mut t: [u8; 12] = [0; 12];
+
+ for i in 0..8 {
+ salt[i] = (i + 1) as u8
+ } // set Salt
+
+ println!("\nTesting ECDH/ECDSA/ECIES");
+ println!("Alice's Passphrase= {}", pw);
+
+ let mut s0: [u8; EFS] = [0; EGS];
+ ecdh::pbkdf2(sha, pp, &salt, 1000, EGS, &mut s0);
+
+ print!("Alice's private key= 0x");
+ printbinary(&s0);
+
+ /* Generate Key pair S/W */
+ ecdh::key_pair_generate(None, &mut s0, &mut w0);
+
+ print!("Alice's public key= 0x");
+ printbinary(&w0);
+
+ let mut res = ecdh::public_key_validate(&w0);
+ if res != 0 {
+ println!("ECP Public Key is invalid!");
+ return;
+ }
+
+ /* Random private key for other party */
+ ecdh::key_pair_generate(Some(&mut rng), &mut s1, &mut w1);
+
+ print!("Servers private key= 0x");
+ printbinary(&s1);
+
+ print!("Servers public key= 0x");
+ printbinary(&w1);
+
+ res = ecdh::public_key_validate(&w1);
+ if res != 0 {
+ println!("ECP Public Key is invalid!");
+ return;
+ }
+ /* Calculate common key using DH - IEEE 1363 method */
+
+ ecdh::ecpsvdp_dh(&s0, &w1, &mut z0);
+ ecdh::ecpsvdp_dh(&s1, &w0, &mut z1);
+
+ let mut same = true;
+ for i in 0..EFS {
+ if z0[i] != z1[i] {
+ same = false
+ }
+ }
+
+ if !same {
+ println!("*** ECPSVDP-DH Failed");
+ return;
+ }
+
+ ecdh::kdf2(sha, &z0, None, EAS, &mut key);
+
+ print!("Alice's DH Key= 0x");
+ printbinary(&key);
+ print!("Servers DH Key= 0x");
+ printbinary(&key);
+
+ if ecp::CURVETYPE != CurveType::Montgomery {
+ for i in 0..17 {
+ m[i] = i as u8
+ }
+
+ println!("Testing ECIES");
+
+ p1[0] = 0x0;
+ p1[1] = 0x1;
+ p1[2] = 0x2;
+ p2[0] = 0x0;
+ p2[1] = 0x1;
+ p2[2] = 0x2;
+ p2[3] = 0x3;
+
+ let cc = ecdh::ecies_encrypt(sha, &p1, &p2, &mut rng, &w1, &m[0..17], &mut v, &mut t);
+
+ if let Some(mut c) = cc {
+ println!("Ciphertext= ");
+ print!("V= 0x");
+ printbinary(&v);
+ print!("C= 0x");
+ printbinary(&c);
+ print!("T= 0x");
+ printbinary(&t);
+
+ let mm = ecdh::ecies_decrypt(sha, &p1, &p2, &v, &mut c, &t, &s1);
+ if let Some(rm) = mm {
+ println!("Decryption succeeded");
+ print!("Message is 0x");
+ printbinary(&rm);
+ } else {
+ println!("*** ECIES Decryption Failed");
+ return;
+ }
+ } else {
+ println!("*** ECIES Encryption Failed");
+ return;
+ }
+
+ println!("Testing ECDSA");
+
+ if ecdh::ecpsp_dsa(sha, &mut rng, &s0, &m[0..17], &mut cs, &mut ds) != 0 {
+ println!("***ECDSA Signature Failed");
+ return;
+ }
+ println!("Signature= ");
+ print!("C= 0x");
+ printbinary(&cs);
+ print!("D= 0x");
+ printbinary(&ds);
+
+ if ecdh::ecpvp_dsa(sha, &w0, &m[0..17], &cs, &ds) != 0 {
+ println!("***ECDSA Verification Failed");
+ return;
+ } else {
+ println!("ECDSA Signature/Verification succeeded ")
+ }
+ }
+}
+
+#[test]
+fn ecdh_nist256() {
+ use amcl::nist256::ecdh;
+ use amcl::nist256::ecp;
+
+ let mut rng = create_rng();
+
+ let pw = "M0ng00se";
+ let pp: &[u8] = b"M0ng00se";
+ const EFS: usize = ecdh::EFS;
+ const EGS: usize = ecdh::EGS;
+ const EAS: usize = ecp::AESKEY;
+
+ let sha = ecp::HASH_TYPE;
+ let mut salt: [u8; 8] = [0; 8];
+ let mut s1: [u8; EGS] = [0; EGS];
+ let mut w0: [u8; 2 * EFS + 1] = [0; 2 * EFS + 1];
+ let mut w1: [u8; 2 * EFS + 1] = [0; 2 * EFS + 1];
+ let mut z0: [u8; EFS] = [0; EFS];
+ let mut z1: [u8; EFS] = [0; EFS];
+ let mut key: [u8; EAS] = [0; EAS];
+ let mut cs: [u8; EGS] = [0; EGS];
+ let mut ds: [u8; EGS] = [0; EGS];
+ let mut m: Vec<u8> = vec![0; 32]; // array that could be of any length. So use heap.
+ let mut p1: [u8; 3] = [0; 3];
+ let mut p2: [u8; 4] = [0; 4];
+ let mut v: [u8; 2 * EFS + 1] = [0; 2 * EFS + 1];
+ let mut t: [u8; 12] = [0; 12];
+
+ for i in 0..8 {
+ salt[i] = (i + 1) as u8
+ } // set Salt
+
+ println!("\nTesting ECDH/ECDSA/ECIES");
+ println!("Alice's Passphrase= {}", pw);
+
+ let mut s0: [u8; EFS] = [0; EGS];
+ ecdh::pbkdf2(sha, pp, &salt, 1000, EGS, &mut s0);
+
+ print!("Alice's private key= 0x");
+ printbinary(&s0);
+
+ /* Generate Key pair S/W */
+ ecdh::key_pair_generate(None, &mut s0, &mut w0);
+
+ print!("Alice's public key= 0x");
+ printbinary(&w0);
+
+ let mut res = ecdh::public_key_validate(&w0);
+ if res != 0 {
+ println!("ECP Public Key is invalid!");
+ return;
+ }
+
+ /* Random private key for other party */
+ ecdh::key_pair_generate(Some(&mut rng), &mut s1, &mut w1);
+
+ print!("Servers private key= 0x");
+ printbinary(&s1);
+
+ print!("Servers public key= 0x");
+ printbinary(&w1);
+
+ res = ecdh::public_key_validate(&w1);
+ if res != 0 {
+ println!("ECP Public Key is invalid!");
+ return;
+ }
+ /* Calculate common key using DH - IEEE 1363 method */
+
+ ecdh::ecpsvdp_dh(&s0, &w1, &mut z0);
+ ecdh::ecpsvdp_dh(&s1, &w0, &mut z1);
+
+ let mut same = true;
+ for i in 0..EFS {
+ if z0[i] != z1[i] {
+ same = false
+ }
+ }
+
+ if !same {
+ println!("*** ECPSVDP-DH Failed");
+ return;
+ }
+
+ ecdh::kdf2(sha, &z0, None, EAS, &mut key);
+
+ print!("Alice's DH Key= 0x");
+ printbinary(&key);
+ print!("Servers DH Key= 0x");
+ printbinary(&key);
+
+ if ecp::CURVETYPE != CurveType::Montgomery {
+ for i in 0..17 {
+ m[i] = i as u8
+ }
+
+ println!("Testing ECIES");
+
+ p1[0] = 0x0;
+ p1[1] = 0x1;
+ p1[2] = 0x2;
+ p2[0] = 0x0;
+ p2[1] = 0x1;
+ p2[2] = 0x2;
+ p2[3] = 0x3;
+
+ let cc = ecdh::ecies_encrypt(sha, &p1, &p2, &mut rng, &w1, &m[0..17], &mut v, &mut t);
+
+ if let Some(mut c) = cc {
+ println!("Ciphertext= ");
+ print!("V= 0x");
+ printbinary(&v);
+ print!("C= 0x");
+ printbinary(&c);
+ print!("T= 0x");
+ printbinary(&t);
+
+ let mm = ecdh::ecies_decrypt(sha, &p1, &p2, &v, &mut c, &t, &s1);
+ if let Some(rm) = mm {
+ println!("Decryption succeeded");
+ print!("Message is 0x");
+ printbinary(&rm);
+ } else {
+ println!("*** ECIES Decryption Failed");
+ return;
+ }
+ } else {
+ println!("*** ECIES Encryption Failed");
+ return;
+ }
+
+ println!("Testing ECDSA");
+
+ if ecdh::ecpsp_dsa(sha, &mut rng, &s0, &m[0..17], &mut cs, &mut ds) != 0 {
+ println!("***ECDSA Signature Failed");
+ return;
+ }
+ println!("Signature= ");
+ print!("C= 0x");
+ printbinary(&cs);
+ print!("D= 0x");
+ printbinary(&ds);
+
+ if ecdh::ecpvp_dsa(sha, &w0, &m[0..17], &cs, &ds) != 0 {
+ println!("***ECDSA Verification Failed");
+ return;
+ } else {
+ println!("ECDSA Signature/Verification succeeded ")
+ }
+ }
+}
+
+#[test]
+fn ecdh_goldilocks() {
+ use amcl::goldilocks::ecdh;
+ use amcl::goldilocks::ecp;
+
+ let mut rng = create_rng();
+
+ let pw = "M0ng00se";
+ let pp: &[u8] = b"M0ng00se";
+ const EFS: usize = ecdh::EFS;
+ const EGS: usize = ecdh::EGS;
+ const EAS: usize = ecp::AESKEY;
+
+ let sha = ecp::HASH_TYPE;
+ let mut salt: [u8; 8] = [0; 8];
+ let mut s1: [u8; EGS] = [0; EGS];
+ let mut w0: [u8; 2 * EFS + 1] = [0; 2 * EFS + 1];
+ let mut w1: [u8; 2 * EFS + 1] = [0; 2 * EFS + 1];
+ let mut z0: [u8; EFS] = [0; EFS];
+ let mut z1: [u8; EFS] = [0; EFS];
+ let mut key: [u8; EAS] = [0; EAS];
+ let mut cs: [u8; EGS] = [0; EGS];
+ let mut ds: [u8; EGS] = [0; EGS];
+ let mut m: Vec<u8> = vec![0; 32]; // array that could be of any length. So use heap.
+ let mut p1: [u8; 3] = [0; 3];
+ let mut p2: [u8; 4] = [0; 4];
+ let mut v: [u8; 2 * EFS + 1] = [0; 2 * EFS + 1];
+ let mut t: [u8; 12] = [0; 12];
+
+ for i in 0..8 {
+ salt[i] = (i + 1) as u8
+ } // set Salt
+
+ println!("\nTesting ECDH/ECDSA/ECIES");
+ println!("Alice's Passphrase= {}", pw);
+
+ let mut s0: [u8; EFS] = [0; EGS];
+ ecdh::pbkdf2(sha, pp, &salt, 1000, EGS, &mut s0);
+
+ print!("Alice's private key= 0x");
+ printbinary(&s0);
+
+ /* Generate Key pair S/W */
+ ecdh::key_pair_generate(None, &mut s0, &mut w0);
+
+ print!("Alice's public key= 0x");
+ printbinary(&w0);
+
+ let mut res = ecdh::public_key_validate(&w0);
+ if res != 0 {
+ println!("ECP Public Key is invalid!");
+ return;
+ }
+
+ /* Random private key for other party */
+ ecdh::key_pair_generate(Some(&mut rng), &mut s1, &mut w1);
+
+ print!("Servers private key= 0x");
+ printbinary(&s1);
+
+ print!("Servers public key= 0x");
+ printbinary(&w1);
+
+ res = ecdh::public_key_validate(&w1);
+ if res != 0 {
+ println!("ECP Public Key is invalid!");
+ return;
+ }
+ /* Calculate common key using DH - IEEE 1363 method */
+
+ ecdh::ecpsvdp_dh(&s0, &w1, &mut z0);
+ ecdh::ecpsvdp_dh(&s1, &w0, &mut z1);
+
+ let mut same = true;
+ for i in 0..EFS {
+ if z0[i] != z1[i] {
+ same = false
+ }
+ }
+
+ if !same {
+ println!("*** ECPSVDP-DH Failed");
+ return;
+ }
+
+ ecdh::kdf2(sha, &z0, None, EAS, &mut key);
+
+ print!("Alice's DH Key= 0x");
+ printbinary(&key);
+ print!("Servers DH Key= 0x");
+ printbinary(&key);
+
+ if ecp::CURVETYPE != CurveType::Montgomery {
+ for i in 0..17 {
+ m[i] = i as u8
+ }
+
+ println!("Testing ECIES");
+
+ p1[0] = 0x0;
+ p1[1] = 0x1;
+ p1[2] = 0x2;
+ p2[0] = 0x0;
+ p2[1] = 0x1;
+ p2[2] = 0x2;
+ p2[3] = 0x3;
+
+ let cc = ecdh::ecies_encrypt(sha, &p1, &p2, &mut rng, &w1, &m[0..17], &mut v, &mut t);
+
+ if let Some(mut c) = cc {
+ println!("Ciphertext= ");
+ print!("V= 0x");
+ printbinary(&v);
+ print!("C= 0x");
+ printbinary(&c);
+ print!("T= 0x");
+ printbinary(&t);
+
+ let mm = ecdh::ecies_decrypt(sha, &p1, &p2, &v, &mut c, &t, &s1);
+ if let Some(rm) = mm {
+ println!("Decryption succeeded");
+ print!("Message is 0x");
+ printbinary(&rm);
+ } else {
+ println!("*** ECIES Decryption Failed");
+ return;
+ }
+ } else {
+ println!("*** ECIES Encryption Failed");
+ return;
+ }
+
+ println!("Testing ECDSA");
+
+ if ecdh::ecpsp_dsa(sha, &mut rng, &s0, &m[0..17], &mut cs, &mut ds) != 0 {
+ println!("***ECDSA Signature Failed");
+ return;
+ }
+ println!("Signature= ");
+ print!("C= 0x");
+ printbinary(&cs);
+ print!("D= 0x");
+ printbinary(&ds);
+
+ if ecdh::ecpvp_dsa(sha, &w0, &m[0..17], &cs, &ds) != 0 {
+ println!("***ECDSA Verification Failed");
+ return;
+ } else {
+ println!("ECDSA Signature/Verification succeeded ")
+ }
+ }
+}
+
+#[test]
+fn mpin_bn254() {
+ use amcl::bn254::ecp;
+ use amcl::bn254::mpin;
+
+ let mut rng = create_rng();
+
+ pub const PERMITS: bool = true;
+ pub const PINERROR: bool = true;
+ pub const FULL: bool = true;
+ //pub const SINGLE_PASS:bool=false;
+
+ const EFS: usize = mpin::EFS;
+ const EGS: usize = mpin::EGS;
+
+ let mut s: [u8; EGS] = [0; EGS];
+ const RM: usize = EFS as usize;
+ let mut hcid: [u8; RM] = [0; RM];
+ let mut hsid: [u8; RM] = [0; RM];
+
+ const G1S: usize = 2 * EFS + 1; /* Group 1 Size */
+ const G2S: usize = 4 * EFS; /* Group 2 Size */
+ const EAS: usize = ecp::AESKEY;
+
+ let mut sst: [u8; G2S] = [0; G2S];
+ let mut token: [u8; G1S] = [0; G1S];
+ let mut permit: [u8; G1S] = [0; G1S];
+ let mut g1: [u8; 12 * EFS] = [0; 12 * EFS];
+ let mut g2: [u8; 12 * EFS] = [0; 12 * EFS];
+ let mut xid: [u8; G1S] = [0; G1S];
+ let mut xcid: [u8; G1S] = [0; G1S];
+ let mut x: [u8; EGS] = [0; EGS];
+ let mut y: [u8; EGS] = [0; EGS];
+ let mut sec: [u8; G1S] = [0; G1S];
+ let mut r: [u8; EGS] = [0; EGS];
+ let mut z: [u8; G1S] = [0; G1S];
+ let mut hid: [u8; G1S] = [0; G1S];
+ let mut htid: [u8; G1S] = [0; G1S];
+ let mut rhid: [u8; G1S] = [0; G1S];
+ let mut w: [u8; EGS] = [0; EGS];
+ let mut t: [u8; G1S] = [0; G1S];
+ let mut e: [u8; 12 * EFS] = [0; 12 * EFS];
+ let mut f: [u8; 12 * EFS] = [0; 12 * EFS];
+ let mut h: [u8; RM] = [0; RM];
+ let mut ck: [u8; EAS] = [0; EAS];
+ let mut sk: [u8; EAS] = [0; EAS];
+
+ let sha = ecp::HASH_TYPE;
+
+ println!("\nTesting MPIN - PIN is 1234");
+ /* Trusted Authority set-up */
+
+ mpin::random_generate(&mut rng, &mut s);
+ print!("Master Secret s: 0x");
+ printbinary(&s);
+
+ /* Create Client Identity */
+ let name = "testUser@miracl.com";
+ let client_id = name.as_bytes();
+
+ print!("Client ID= ");
+ printbinary(&client_id);
+
+ mpin::hash_id(sha, &client_id, &mut hcid); /* Either Client or TA calculates Hash(ID) - you decide! */
+
+ /* Client and Server are issued secrets by DTA */
+ mpin::get_server_secret(&s, &mut sst);
+ print!("Server Secret SS: 0x");
+ printbinary(&sst);
+
+ mpin::get_client_secret(&mut s, &hcid, &mut token);
+ print!("Client Secret CS: 0x");
+ printbinary(&token);
+
+ /* Client extracts PIN from secret to create Token */
+ let pin: i32 = 1234;
+ println!("Client extracts PIN= {}", pin);
+ let mut rtn = mpin::extract_pin(sha, &client_id, pin, &mut token);
+ if rtn != 0 {
+ println!("FAILURE: EXTRACT_PIN rtn: {}", rtn);
+ }
+
+ print!("Client Token TK: 0x");
+ printbinary(&token);
+
+ if FULL {
+ mpin::precompute(&token, &hcid, &mut g1, &mut g2);
+ }
+
+ let mut date = 0;
+ if PERMITS {
+ date = mpin::today();
+ /* Client gets "Time Token" permit from DTA */
+
+ mpin::get_client_permit(sha, date, &s, &hcid, &mut permit);
+ print!("Time Permit TP: 0x");
+ printbinary(&permit);
+
+ /* This encoding makes Time permit look random - Elligator squared */
+ mpin::encoding(&mut rng, &mut permit);
+ print!("Encoded Time Permit TP: 0x");
+ printbinary(&permit);
+ mpin::decoding(&mut permit);
+ print!("Decoded Time Permit TP: 0x");
+ printbinary(&permit);
+ }
+
+ print!("\nPIN= ");
+ let _ = io::Write::flush(&mut io::stdout());
+ let mut input_text = String::new();
+ let _ = io::stdin().read_line(&mut input_text);
+
+ let pin = input_text.trim().parse::<usize>().unwrap();
+
+ println!("MPIN Multi Pass");
+ /* Send U=x.ID to server, and recreate secret from token and pin */
+ rtn = mpin::client_1(
+ sha,
+ date,
+ &client_id,
+ Some(&mut rng),
+ &mut x,
+ pin,
+ &token,
+ &mut sec,
+ Some(&mut xid[..]),
+ Some(&mut xcid[..]),
+ Some(&permit[..]),
+ );
+ if rtn != 0 {
+ println!("FAILURE: CLIENT_1 rtn: {}", rtn);
+ }
+
+ if FULL {
+ mpin::hash_id(sha, &client_id, &mut hcid);
+ mpin::get_g1_multiple(Some(&mut rng), 1, &mut r, &hcid, &mut z); /* Also Send Z=r.ID to Server, remember random r */
+ }
+
+ /* Server calculates H(ID) and H(T|H(ID)) (if time mpin::PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+
+ mpin::server_1(sha, date, &client_id, &mut hid, Some(&mut htid[..]));
+
+ if date != 0 {
+ rhid.clone_from_slice(&htid[..]);
+ } else {
+ rhid.clone_from_slice(&hid[..]);
+ }
+
+ /* Server generates Random number Y and sends it to Client */
+ mpin::random_generate(&mut rng, &mut y);
+
+ if FULL {
+ mpin::hash_id(sha, &client_id, &mut hsid);
+ mpin::get_g1_multiple(Some(&mut rng), 0, &mut w, &rhid, &mut t); /* Also send T=w.ID to client, remember random w */
+ }
+
+ /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+ rtn = mpin::client_2(&x, &y, &mut sec);
+ if rtn != 0 {
+ println!("FAILURE: CLIENT_2 rtn: {}", rtn);
+ }
+
+ /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+ /* If PIN error not required, set E and F = null */
+
+ if !PINERROR {
+ rtn = mpin::server_2(
+ date,
+ &hid,
+ Some(&htid[..]),
+ &y,
+ &sst,
+ Some(&xid[..]),
+ Some(&xcid[..]),
+ &sec,
+ None,
+ None,
+ );
+ } else {
+ rtn = mpin::server_2(
+ date,
+ &hid,
+ Some(&htid[..]),
+ &y,
+ &sst,
+ Some(&xid[..]),
+ Some(&xcid[..]),
+ &sec,
+ Some(&mut e),
+ Some(&mut f),
+ );
+ }
+
+ if rtn == mpin::BAD_PIN {
+ println!("Server says - Bad Pin. I don't know you. Feck off.");
+ if PINERROR {
+ let err = mpin::kangaroo(&e, &f);
+ if err != 0 {
+ println!("(Client PIN is out by {})", err)
+ }
+ }
+ return;
+ } else {
+ println!("Server says - PIN is good! You really are {}", name);
+ }
+
+ if FULL {
+ let mut pxcid = None;
+ if PERMITS {
+ pxcid = Some(&xcid[..])
+ };
+
+ mpin::hash_all(sha, &hcid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+ mpin::client_key(sha, &g1, &g2, pin, &r, &x, &h, &t, &mut ck);
+ print!("Client Key = 0x");
+ printbinary(&ck);
+
+ mpin::hash_all(sha, &hsid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+ mpin::server_key(sha, &z, &sst, &w, &h, &hid, &xid, pxcid, &mut sk);
+ print!("Server Key = 0x");
+ printbinary(&sk);
+ }
+}
+
+#[test]
+fn mpin_bls383() {
+ //use amcl::bls383;
+ use amcl::bls383::ecp;
+ use amcl::bls383::mpin;
+
+ let mut rng = create_rng();
+
+ pub const PERMITS: bool = true;
+ pub const PINERROR: bool = true;
+ pub const FULL: bool = true;
+ //pub const SINGLE_PASS:bool=false;
+
+ const EFS: usize = mpin::EFS;
+ const EGS: usize = mpin::EGS;
+
+ let mut s: [u8; EGS] = [0; EGS];
+ const RM: usize = EFS as usize;
+ let mut hcid: [u8; RM] = [0; RM];
+ let mut hsid: [u8; RM] = [0; RM];
+
+ const G1S: usize = 2 * EFS + 1; /* Group 1 Size */
+ const G2S: usize = 4 * EFS; /* Group 2 Size */
+ const EAS: usize = ecp::AESKEY;
+
+ let mut sst: [u8; G2S] = [0; G2S];
+ let mut token: [u8; G1S] = [0; G1S];
+ let mut permit: [u8; G1S] = [0; G1S];
+ let mut g1: [u8; 12 * EFS] = [0; 12 * EFS];
+ let mut g2: [u8; 12 * EFS] = [0; 12 * EFS];
+ let mut xid: [u8; G1S] = [0; G1S];
+ let mut xcid: [u8; G1S] = [0; G1S];
+ let mut x: [u8; EGS] = [0; EGS];
+ let mut y: [u8; EGS] = [0; EGS];
+ let mut sec: [u8; G1S] = [0; G1S];
+ let mut r: [u8; EGS] = [0; EGS];
+ let mut z: [u8; G1S] = [0; G1S];
+ let mut hid: [u8; G1S] = [0; G1S];
+ let mut htid: [u8; G1S] = [0; G1S];
+ let mut rhid: [u8; G1S] = [0; G1S];
+ let mut w: [u8; EGS] = [0; EGS];
+ let mut t: [u8; G1S] = [0; G1S];
+ let mut e: [u8; 12 * EFS] = [0; 12 * EFS];
+ let mut f: [u8; 12 * EFS] = [0; 12 * EFS];
+ let mut h: [u8; RM] = [0; RM];
+ let mut ck: [u8; EAS] = [0; EAS];
+ let mut sk: [u8; EAS] = [0; EAS];
+
+ let sha = ecp::HASH_TYPE;
+
+ println!("\nTesting MPIN - PIN is 1234");
+ /* Trusted Authority set-up */
+
+ mpin::random_generate(&mut rng, &mut s);
+ print!("Master Secret s: 0x");
+ printbinary(&s);
+
+ /* Create Client Identity */
+ let name = "testUser@miracl.com";
+ let client_id = name.as_bytes();
+
+ print!("Client ID= ");
+ printbinary(&client_id);
+
+ mpin::hash_id(sha, &client_id, &mut hcid); /* Either Client or TA calculates Hash(ID) - you decide! */
+
+ /* Client and Server are issued secrets by DTA */
+ mpin::get_server_secret(&s, &mut sst);
+ print!("Server Secret SS: 0x");
+ printbinary(&sst);
+
+ mpin::get_client_secret(&mut s, &hcid, &mut token);
+ print!("Client Secret CS: 0x");
+ printbinary(&token);
+
+ /* Client extracts PIN from secret to create Token */
+ let pin: i32 = 1234;
+ println!("Client extracts PIN= {}", pin);
+ let mut rtn = mpin::extract_pin(sha, &client_id, pin, &mut token);
+ if rtn != 0 {
+ println!("FAILURE: EXTRACT_PIN rtn: {}", rtn);
+ }
+
+ print!("Client Token TK: 0x");
+ printbinary(&token);
+
+ if FULL {
+ mpin::precompute(&token, &hcid, &mut g1, &mut g2);
+ }
+
+ let mut date = 0;
+ if PERMITS {
+ date = mpin::today();
+ /* Client gets "Time Token" permit from DTA */
+
+ mpin::get_client_permit(sha, date, &s, &hcid, &mut permit);
+ print!("Time Permit TP: 0x");
+ printbinary(&permit);
+
+ /* This encoding makes Time permit look random - Elligator squared */
+ mpin::encoding(&mut rng, &mut permit);
+ print!("Encoded Time Permit TP: 0x");
+ printbinary(&permit);
+ mpin::decoding(&mut permit);
+ print!("Decoded Time Permit TP: 0x");
+ printbinary(&permit);
+ }
+
+ print!("\nPIN= ");
+ let _ = io::Write::flush(&mut io::stdout());
+ let mut input_text = String::new();
+ let _ = io::stdin().read_line(&mut input_text);
+
+ let pin = input_text.trim().parse::<usize>().unwrap();
+
+ println!("MPIN Multi Pass");
+ /* Send U=x.ID to server, and recreate secret from token and pin */
+ rtn = mpin::client_1(
+ sha,
+ date,
+ &client_id,
+ Some(&mut rng),
+ &mut x,
+ pin,
+ &token,
+ &mut sec,
+ Some(&mut xid[..]),
+ Some(&mut xcid[..]),
+ Some(&permit[..]),
+ );
+ if rtn != 0 {
+ println!("FAILURE: CLIENT_1 rtn: {}", rtn);
+ }
+
+ if FULL {
+ mpin::hash_id(sha, &client_id, &mut hcid);
+ mpin::get_g1_multiple(Some(&mut rng), 1, &mut r, &hcid, &mut z); /* Also Send Z=r.ID to Server, remember random r */
+ }
+
+ /* Server calculates H(ID) and H(T|H(ID)) (if time mpin::PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+
+ mpin::server_1(sha, date, &client_id, &mut hid, Some(&mut htid[..]));
+
+ if date != 0 {
+ rhid.clone_from_slice(&htid[..]);
+ } else {
+ rhid.clone_from_slice(&hid[..]);
+ }
+
+ /* Server generates Random number Y and sends it to Client */
+ mpin::random_generate(&mut rng, &mut y);
+
+ if FULL {
+ mpin::hash_id(sha, &client_id, &mut hsid);
+ mpin::get_g1_multiple(Some(&mut rng), 0, &mut w, &rhid, &mut t); /* Also send T=w.ID to client, remember random w */
+ }
+
+ /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+ rtn = mpin::client_2(&x, &y, &mut sec);
+ if rtn != 0 {
+ println!("FAILURE: CLIENT_2 rtn: {}", rtn);
+ }
+
+ /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+ /* If PIN error not required, set E and F = null */
+
+ if !PINERROR {
+ rtn = mpin::server_2(
+ date,
+ &hid,
+ Some(&htid[..]),
+ &y,
+ &sst,
+ Some(&xid[..]),
+ Some(&xcid[..]),
+ &sec,
+ None,
+ None,
+ );
+ } else {
+ rtn = mpin::server_2(
+ date,
+ &hid,
+ Some(&htid[..]),
+ &y,
+ &sst,
+ Some(&xid[..]),
+ Some(&xcid[..]),
+ &sec,
+ Some(&mut e),
+ Some(&mut f),
+ );
+ }
+
+ if rtn == mpin::BAD_PIN {
+ println!("Server says - Bad Pin. I don't know you. Feck off.");
+ if PINERROR {
+ let err = mpin::kangaroo(&e, &f);
+ if err != 0 {
+ println!("(Client PIN is out by {})", err)
+ }
+ }
+ return;
+ } else {
+ println!("Server says - PIN is good! You really are {}", name);
+ }
+
+ if FULL {
+ let mut pxcid = None;
+ if PERMITS {
+ pxcid = Some(&xcid[..])
+ };
+
+ mpin::hash_all(sha, &hcid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+ mpin::client_key(sha, &g1, &g2, pin, &r, &x, &h, &t, &mut ck);
+ print!("Client Key = 0x");
+ printbinary(&ck);
+
+ mpin::hash_all(sha, &hsid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+ mpin::server_key(sha, &z, &sst, &w, &h, &hid, &xid, pxcid, &mut sk);
+ print!("Server Key = 0x");
+ printbinary(&sk);
+ }
+}
+
+#[test]
+fn mpin_bls24() {
+ //use amcl::bls24;
+ use amcl::bls24::ecp;
+ use amcl::bls24::mpin192;
+
+ let mut rng = create_rng();
+
+ pub const PERMITS: bool = true;
+ pub const PINERROR: bool = true;
+ pub const FULL: bool = true;
+ //pub const SINGLE_PASS:bool=false;
+
+ const EFS: usize = mpin192::EFS;
+ const EGS: usize = mpin192::EGS;
+
+ let mut s: [u8; EGS] = [0; EGS];
+ const RM: usize = EFS as usize;
+ let mut hcid: [u8; RM] = [0; RM];
+ let mut hsid: [u8; RM] = [0; RM];
+
+ const G1S: usize = 2 * EFS + 1; /* Group 1 Size */
+ const G2S: usize = 8 * EFS; /* Group 2 Size */
+ const EAS: usize = ecp::AESKEY;
+
+ let mut sst: [u8; G2S] = [0; G2S];
+ let mut token: [u8; G1S] = [0; G1S];
+ let mut permit: [u8; G1S] = [0; G1S];
+ let mut g1: [u8; 24 * EFS] = [0; 24 * EFS];
+ let mut g2: [u8; 24 * EFS] = [0; 24 * EFS];
+ let mut xid: [u8; G1S] = [0; G1S];
+ let mut xcid: [u8; G1S] = [0; G1S];
+ let mut x: [u8; EGS] = [0; EGS];
+ let mut y: [u8; EGS] = [0; EGS];
+ let mut sec: [u8; G1S] = [0; G1S];
+ let mut r: [u8; EGS] = [0; EGS];
+ let mut z: [u8; G1S] = [0; G1S];
+ let mut hid: [u8; G1S] = [0; G1S];
+ let mut htid: [u8; G1S] = [0; G1S];
+ let mut rhid: [u8; G1S] = [0; G1S];
+ let mut w: [u8; EGS] = [0; EGS];
+ let mut t: [u8; G1S] = [0; G1S];
+ let mut e: [u8; 24 * EFS] = [0; 24 * EFS];
+ let mut f: [u8; 24 * EFS] = [0; 24 * EFS];
+ let mut h: [u8; RM] = [0; RM];
+ let mut ck: [u8; EAS] = [0; EAS];
+ let mut sk: [u8; EAS] = [0; EAS];
+
+ let sha = ecp::HASH_TYPE;
+
+ println!("\nTesting MPIN - PIN is 1234");
+ /* Trusted Authority set-up */
+
+ mpin192::random_generate(&mut rng, &mut s);
+ print!("Master Secret s: 0x");
+ printbinary(&s);
+
+ /* Create Client Identity */
+ let name = "testUser@miracl.com";
+ let client_id = name.as_bytes();
+
+ print!("Client ID= ");
+ printbinary(&client_id);
+
+ mpin192::hash_id(sha, &client_id, &mut hcid); /* Either Client or TA calculates Hash(ID) - you decide! */
+
+ /* Client and Server are issued secrets by DTA */
+ mpin192::get_server_secret(&s, &mut sst);
+ print!("Server Secret SS: 0x");
+ printbinary(&sst);
+
+ mpin192::get_client_secret(&mut s, &hcid, &mut token);
+ print!("Client Secret CS: 0x");
+ printbinary(&token);
+
+ /* Client extracts PIN from secret to create Token */
+ let pin: i32 = 1234;
+ println!("Client extracts PIN= {}", pin);
+ let mut rtn = mpin192::extract_pin(sha, &client_id, pin, &mut token);
+ if rtn != 0 {
+ println!("FAILURE: EXTRACT_PIN rtn: {}", rtn);
+ }
+
+ print!("Client Token TK: 0x");
+ printbinary(&token);
+
+ if FULL {
+ mpin192::precompute(&token, &hcid, &mut g1, &mut g2);
+ }
+
+ let mut date = 0;
+ if PERMITS {
+ date = mpin192::today();
+ /* Client gets "Time Token" permit from DTA */
+
+ mpin192::get_client_permit(sha, date, &s, &hcid, &mut permit);
+ print!("Time Permit TP: 0x");
+ printbinary(&permit);
+
+ /* This encoding makes Time permit look random - Elligator squared */
+ mpin192::encoding(&mut rng, &mut permit);
+ print!("Encoded Time Permit TP: 0x");
+ printbinary(&permit);
+ mpin192::decoding(&mut permit);
+ print!("Decoded Time Permit TP: 0x");
+ printbinary(&permit);
+ }
+
+ print!("\nPIN= ");
+ let _ = io::Write::flush(&mut io::stdout());
+ let mut input_text = String::new();
+ let _ = io::stdin().read_line(&mut input_text);
+
+ let pin = input_text.trim().parse::<usize>().unwrap();
+
+ println!("MPIN Multi Pass");
+ /* Send U=x.ID to server, and recreate secret from token and pin */
+ rtn = mpin192::client_1(
+ sha,
+ date,
+ &client_id,
+ Some(&mut rng),
+ &mut x,
+ pin,
+ &token,
+ &mut sec,
+ Some(&mut xid[..]),
+ Some(&mut xcid[..]),
+ Some(&permit[..]),
+ );
+ if rtn != 0 {
+ println!("FAILURE: CLIENT_1 rtn: {}", rtn);
+ }
+
+ if FULL {
+ mpin192::hash_id(sha, &client_id, &mut hcid);
+ mpin192::get_g1_multiple(Some(&mut rng), 1, &mut r, &hcid, &mut z); /* Also Send Z=r.ID to Server, remember random r */
+ }
+
+ /* Server calculates H(ID) and H(T|H(ID)) (if time mpin192::PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+
+ mpin192::server_1(sha, date, &client_id, &mut hid, Some(&mut htid[..]));
+
+ if date != 0 {
+ rhid.clone_from_slice(&htid[..]);
+ } else {
+ rhid.clone_from_slice(&hid[..]);
+ }
+
+ /* Server generates Random number Y and sends it to Client */
+ mpin192::random_generate(&mut rng, &mut y);
+
+ if FULL {
+ mpin192::hash_id(sha, &client_id, &mut hsid);
+ mpin192::get_g1_multiple(Some(&mut rng), 0, &mut w, &rhid, &mut t); /* Also send T=w.ID to client, remember random w */
+ }
+
+ /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+ rtn = mpin192::client_2(&x, &y, &mut sec);
+ if rtn != 0 {
+ println!("FAILURE: CLIENT_2 rtn: {}", rtn);
+ }
+
+ /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+ /* If PIN error not required, set E and F = null */
+
+ if !PINERROR {
+ rtn = mpin192::server_2(
+ date,
+ &hid,
+ Some(&htid[..]),
+ &y,
+ &sst,
+ Some(&xid[..]),
+ Some(&xcid[..]),
+ &sec,
+ None,
+ None,
+ );
+ } else {
+ rtn = mpin192::server_2(
+ date,
+ &hid,
+ Some(&htid[..]),
+ &y,
+ &sst,
+ Some(&xid[..]),
+ Some(&xcid[..]),
+ &sec,
+ Some(&mut e),
+ Some(&mut f),
+ );
+ }
+
+ if rtn == mpin192::BAD_PIN {
+ println!("Server says - Bad Pin. I don't know you. Feck off.");
+ if PINERROR {
+ let err = mpin192::kangaroo(&e, &f);
+ if err != 0 {
+ println!("(Client PIN is out by {})", err)
+ }
+ }
+ return;
+ } else {
+ println!("Server says - PIN is good! You really are {}", name);
+ }
+
+ if FULL {
+ let mut pxcid = None;
+ if PERMITS {
+ pxcid = Some(&xcid[..])
+ };
+
+ mpin192::hash_all(sha, &hcid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+ mpin192::client_key(sha, &g1, &g2, pin, &r, &x, &h, &t, &mut ck);
+ print!("Client Key = 0x");
+ printbinary(&ck);
+
+ mpin192::hash_all(sha, &hsid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+ mpin192::server_key(sha, &z, &sst, &w, &h, &hid, &xid, pxcid, &mut sk);
+ print!("Server Key = 0x");
+ printbinary(&sk);
+ }
+}
+
+#[test]
+fn mpin_bls48() {
+ //use amcl::bls48;
+ use amcl::bls48::ecp;
+ use amcl::bls48::mpin256;
+
+ let mut rng = create_rng();
+
+ pub const PERMITS: bool = true;
+ pub const PINERROR: bool = true;
+ pub const FULL: bool = true;
+ //pub const SINGLE_PASS:bool=false;
+
+ const EFS: usize = mpin256::EFS;
+ const EGS: usize = mpin256::EGS;
+
+ let mut s: [u8; EGS] = [0; EGS];
+ const RM: usize = EFS as usize;
+ let mut hcid: [u8; RM] = [0; RM];
+ let mut hsid: [u8; RM] = [0; RM];
+
+ const G1S: usize = 2 * EFS + 1; /* Group 1 Size */
+ const G2S: usize = 16 * EFS; /* Group 2 Size */
+ const EAS: usize = ecp::AESKEY;
+
+ let mut sst: [u8; G2S] = [0; G2S];
+ let mut token: [u8; G1S] = [0; G1S];
+ let mut permit: [u8; G1S] = [0; G1S];
+ let mut g1: [u8; 48 * EFS] = [0; 48 * EFS];
+ let mut g2: [u8; 48 * EFS] = [0; 48 * EFS];
+ let mut xid: [u8; G1S] = [0; G1S];
+ let mut xcid: [u8; G1S] = [0; G1S];
+ let mut x: [u8; EGS] = [0; EGS];
+ let mut y: [u8; EGS] = [0; EGS];
+ let mut sec: [u8; G1S] = [0; G1S];
+ let mut r: [u8; EGS] = [0; EGS];
+ let mut z: [u8; G1S] = [0; G1S];
+ let mut hid: [u8; G1S] = [0; G1S];
+ let mut htid: [u8; G1S] = [0; G1S];
+ let mut rhid: [u8; G1S] = [0; G1S];
+ let mut w: [u8; EGS] = [0; EGS];
+ let mut t: [u8; G1S] = [0; G1S];
+ let mut e: [u8; 48 * EFS] = [0; 48 * EFS];
+ let mut f: [u8; 48 * EFS] = [0; 48 * EFS];
+ let mut h: [u8; RM] = [0; RM];
+ let mut ck: [u8; EAS] = [0; EAS];
+ let mut sk: [u8; EAS] = [0; EAS];
+
+ let sha = ecp::HASH_TYPE;
+
+ println!("\nTesting MPIN - PIN is 1234");
+ /* Trusted Authority set-up */
+
+ mpin256::random_generate(&mut rng, &mut s);
+ print!("Master Secret s: 0x");
+ printbinary(&s);
+
+ /* Create Client Identity */
+ let name = "testUser@miracl.com";
+ let client_id = name.as_bytes();
+
+ print!("Client ID= ");
+ printbinary(&client_id);
+
+ mpin256::hash_id(sha, &client_id, &mut hcid); /* Either Client or TA calculates Hash(ID) - you decide! */
+
+ /* Client and Server are issued secrets by DTA */
+ mpin256::get_server_secret(&s, &mut sst);
+ print!("Server Secret SS: 0x");
+ printbinary(&sst);
+
+ mpin256::get_client_secret(&mut s, &hcid, &mut token);
+ print!("Client Secret CS: 0x");
+ printbinary(&token);
+
+ /* Client extracts PIN from secret to create Token */
+ let pin: i32 = 1234;
+ println!("Client extracts PIN= {}", pin);
+ let mut rtn = mpin256::extract_pin(sha, &client_id, pin, &mut token);
+ if rtn != 0 {
+ println!("FAILURE: EXTRACT_PIN rtn: {}", rtn);
+ }
+
+ print!("Client Token TK: 0x");
+ printbinary(&token);
+
+ if FULL {
+ mpin256::precompute(&token, &hcid, &mut g1, &mut g2);
+ }
+
+ let mut date = 0;
+ if PERMITS {
+ date = mpin256::today();
+ /* Client gets "Time Token" permit from DTA */
+
+ mpin256::get_client_permit(sha, date, &s, &hcid, &mut permit);
+ print!("Time Permit TP: 0x");
+ printbinary(&permit);
+
+ /* This encoding makes Time permit look random - Elligator squared */
+ mpin256::encoding(&mut rng, &mut permit);
+ print!("Encoded Time Permit TP: 0x");
+ printbinary(&permit);
+ mpin256::decoding(&mut permit);
+ print!("Decoded Time Permit TP: 0x");
+ printbinary(&permit);
+ }
+
+ print!("\nPIN= ");
+ let _ = io::Write::flush(&mut io::stdout());
+ let mut input_text = String::new();
+ let _ = io::stdin().read_line(&mut input_text);
+
+ let pin = input_text.trim().parse::<usize>().unwrap();
+
+ println!("MPIN Multi Pass");
+ /* Send U=x.ID to server, and recreate secret from token and pin */
+ rtn = mpin256::client_1(
+ sha,
+ date,
+ &client_id,
+ Some(&mut rng),
+ &mut x,
+ pin,
+ &token,
+ &mut sec,
+ Some(&mut xid[..]),
+ Some(&mut xcid[..]),
+ Some(&permit[..]),
+ );
+ if rtn != 0 {
+ println!("FAILURE: CLIENT_1 rtn: {}", rtn);
+ }
+
+ if FULL {
+ mpin256::hash_id(sha, &client_id, &mut hcid);
+ mpin256::get_g1_multiple(Some(&mut rng), 1, &mut r, &hcid, &mut z); /* Also Send Z=r.ID to Server, remember random r */
+ }
+
+ /* Server calculates H(ID) and H(T|H(ID)) (if time mpin256::PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+
+ mpin256::server_1(sha, date, &client_id, &mut hid, Some(&mut htid[..]));
+
+ if date != 0 {
+ rhid.clone_from_slice(&htid[..]);
+ } else {
+ rhid.clone_from_slice(&hid[..]);
+ }
+
+ /* Server generates Random number Y and sends it to Client */
+ mpin256::random_generate(&mut rng, &mut y);
+
+ if FULL {
+ mpin256::hash_id(sha, &client_id, &mut hsid);
+ mpin256::get_g1_multiple(Some(&mut rng), 0, &mut w, &rhid, &mut t); /* Also send T=w.ID to client, remember random w */
+ }
+
+ /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+ rtn = mpin256::client_2(&x, &y, &mut sec);
+ if rtn != 0 {
+ println!("FAILURE: CLIENT_2 rtn: {}", rtn);
+ }
+
+ /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+ /* If PIN error not required, set E and F = null */
+
+ if !PINERROR {
+ rtn = mpin256::server_2(
+ date,
+ &hid,
+ Some(&htid[..]),
+ &y,
+ &sst,
+ Some(&xid[..]),
+ Some(&xcid[..]),
+ &sec,
+ None,
+ None,
+ );
+ } else {
+ rtn = mpin256::server_2(
+ date,
+ &hid,
+ Some(&htid[..]),
+ &y,
+ &sst,
+ Some(&xid[..]),
+ Some(&xcid[..]),
+ &sec,
+ Some(&mut e),
+ Some(&mut f),
+ );
+ }
+
+ if rtn == mpin256::BAD_PIN {
+ println!("Server says - Bad Pin. I don't know you. Feck off.");
+ if PINERROR {
+ let err = mpin256::kangaroo(&e, &f);
+ if err != 0 {
+ println!("(Client PIN is out by {})", err)
+ }
+ }
+ return;
+ } else {
+ println!("Server says - PIN is good! You really are {}", name);
+ }
+
+ if FULL {
+ let mut pxcid = None;
+ if PERMITS {
+ pxcid = Some(&xcid[..])
+ };
+
+ mpin256::hash_all(sha, &hcid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+ mpin256::client_key(sha, &g1, &g2, pin, &r, &x, &h, &t, &mut ck);
+ print!("Client Key = 0x");
+ printbinary(&ck);
+
+ mpin256::hash_all(sha, &hsid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+ mpin256::server_key(sha, &z, &sst, &w, &h, &hid, &xid, pxcid, &mut sk);
+ print!("Server Key = 0x");
+ printbinary(&sk);
+ }
+}
+
+#[test]
+fn rsa_2048() {
+ //use amcl::rsa2048;
+ use amcl::rsa2048::ff;
+ use amcl::rsa2048::rsa;
+
+ let mut rng = create_rng();
+
+ let sha = rsa::HASH_TYPE;
+ let message: &[u8] = b"Hello World\n";
+ const RFS: usize = rsa::RFS;
+
+ let mut pbc = rsa::new_public_key(ff::FFLEN);
+ let mut prv = rsa::new_private_key(ff::HFLEN);
+
+ let mut ml: [u8; RFS] = [0; RFS];
+ let mut ms: [u8; RFS] = [0; RFS];
+ let mut c: [u8; RFS] = [0; RFS];
+ let mut s: [u8; RFS] = [0; RFS];
+ let mut e: [u8; RFS] = [0; RFS];
+
+ println!("\nTesting RSA");
+ println!("Generating public/private key pair");
+ rsa::key_pair(&mut rng, 65537, &mut prv, &mut pbc);
+
+ println!("Encrypting test string\n");
+ rsa::oaep_encode(sha, &message, &mut rng, None, &mut e); /* OAEP encode message M to E */
+
+ rsa::encrypt(&pbc, &e, &mut c); /* encrypt encoded message */
+ print!("Ciphertext= 0x");
+ printbinary(&c);
+
+ println!("Decrypting test string");
+ rsa::decrypt(&prv, &c, &mut ml);
+ let mlen = rsa::oaep_decode(sha, None, &mut ml); /* OAEP decode message */
+
+ let mess = str::from_utf8(&ml[0..mlen]).unwrap();
+ print!("{}", &mess);
+
+ println!("Signing message");
+ rsa::pkcs15(sha, message, &mut c);
+
+ rsa::decrypt(&prv, &c, &mut s); /* create signature in S */
+
+ print!("Signature= 0x");
+ printbinary(&s);
+
+ rsa::encrypt(&pbc, &s, &mut ms);
+
+ let mut cmp = true;
+ if c.len() != ms.len() {
+ cmp = false;
+ } else {
+ for j in 0..c.len() {
+ if c[j] != ms[j] {
+ cmp = false
+ }
+ }
+ }
+ if cmp {
+ println!("Signature is valid");
+ } else {
+ println!("Signature is INVALID");
+ }
+
+ rsa::private_key_kill(&mut prv);
+}
diff --git a/tests/test_bls.rs b/tests/test_bls.rs
new file mode 100644
index 0000000..20cf73b
--- /dev/null
+++ b/tests/test_bls.rs
@@ -0,0 +1,190 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+extern crate amcl;
+
+use amcl::rand::RAND;
+
+pub fn printbinary(array: &[u8]) {
+ for i in 0..array.len() {
+ print!("{:02X}", array[i])
+ }
+ println!("")
+}
+
+fn create_rng() -> RAND {
+ let mut raw: [u8; 100] = [0; 100];
+
+ let mut rng = RAND::new();
+ rng.clean();
+ for i in 0..100 {
+ raw[i] = i as u8
+ }
+
+ rng.seed(100, &raw);
+ rng
+}
+
+#[test]
+fn bls_bn254() {
+ use amcl::bn254::bls;
+
+ let mut rng = create_rng();
+
+ const BFS: usize = bls::BFS;
+ const BGS: usize = bls::BGS;
+
+ let mut s: [u8; BGS] = [0; BGS];
+
+ const G1S: usize = BFS + 1; /* Group 1 Size */
+ const G2S: usize = 4 * BFS; /* Group 2 Size */
+
+ let mut w: [u8; G2S] = [0; G2S];
+ let mut sig: [u8; G1S] = [0; G1S];
+
+ let m = String::from("This is a test message");
+
+ bls::key_pair_generate(&mut rng, &mut s, &mut w);
+ print!("Private key : 0x");
+ printbinary(&s);
+ print!("Public key : 0x");
+ printbinary(&w);
+
+ bls::sign(&mut sig, &m, &s);
+ print!("Signature : 0x");
+ printbinary(&sig);
+
+ let res = bls::verify(&sig, &m, &w);
+ if res == 0 {
+ println!("Signature is OK");
+ } else {
+ println!("Signature is *NOT* OK");
+ }
+}
+
+#[test]
+fn bls_bls383() {
+ use amcl::bls383::bls;
+
+ let mut rng = create_rng();
+
+ const BFS: usize = bls::BFS;
+ const BGS: usize = bls::BGS;
+
+ let mut s: [u8; BGS] = [0; BGS];
+
+ const G1S: usize = BFS + 1; /* Group 1 Size */
+ const G2S: usize = 4 * BFS; /* Group 2 Size */
+
+ let mut w: [u8; G2S] = [0; G2S];
+ let mut sig: [u8; G1S] = [0; G1S];
+
+ let m = String::from("This is a test message");
+
+ bls::key_pair_generate(&mut rng, &mut s, &mut w);
+ print!("Private key : 0x");
+ printbinary(&s);
+ print!("Public key : 0x");
+ printbinary(&w);
+
+ bls::sign(&mut sig, &m, &s);
+ print!("Signature : 0x");
+ printbinary(&sig);
+
+ let res = bls::verify(&sig, &m, &w);
+ if res == 0 {
+ println!("Signature is OK");
+ } else {
+ println!("Signature is *NOT* OK");
+ }
+}
+
+#[test]
+fn bls_bls24() {
+ use amcl::bls24::bls192;
+
+ let mut rng = create_rng();
+
+ const BFS: usize = bls192::BFS;
+ const BGS: usize = bls192::BGS;
+
+ let mut s: [u8; BGS] = [0; BGS];
+
+ const G1S: usize = BFS + 1; /* Group 1 Size */
+ const G2S: usize = 8 * BFS; /* Group 2 Size */
+
+ let mut w: [u8; G2S] = [0; G2S];
+ let mut sig: [u8; G1S] = [0; G1S];
+
+ let m = String::from("This is a test message");
+
+ bls192::key_pair_generate(&mut rng, &mut s, &mut w);
+ print!("Private key : 0x");
+ printbinary(&s);
+ print!("Public key : 0x");
+ printbinary(&w);
+
+ bls192::sign(&mut sig, &m, &s);
+ print!("Signature : 0x");
+ printbinary(&sig);
+
+ let res = bls192::verify(&sig, &m, &w);
+ if res == 0 {
+ println!("Signature is OK");
+ } else {
+ println!("Signature is *NOT* OK");
+ }
+}
+
+#[test]
+fn bls_bls48() {
+ use amcl::bls48::bls256;
+
+ let mut rng = create_rng();
+
+ const BFS: usize = bls256::BFS;
+ const BGS: usize = bls256::BGS;
+
+ let mut s: [u8; BGS] = [0; BGS];
+
+ const G1S: usize = BFS + 1; /* Group 1 Size */
+ const G2S: usize = 16 * BFS; /* Group 2 Size */
+
+ let mut w: [u8; G2S] = [0; G2S];
+ let mut sig: [u8; G1S] = [0; G1S];
+
+ let m = String::from("This is a test message");
+
+ bls256::key_pair_generate(&mut rng, &mut s, &mut w);
+ print!("Private key : 0x");
+ printbinary(&s);
+ print!("Public key : 0x");
+ printbinary(&w);
+
+ bls256::sign(&mut sig, &m, &s);
+ print!("Signature : 0x");
+ printbinary(&sig);
+
+ let res = bls256::verify(&sig, &m, &w);
+ if res == 0 {
+ println!("Signature is OK");
+ } else {
+ println!("Signature is *NOT* OK");
+ }
+}
diff --git a/tests/test_nhs.rs b/tests/test_nhs.rs
new file mode 100644
index 0000000..f272291
--- /dev/null
+++ b/tests/test_nhs.rs
@@ -0,0 +1,71 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+// Tests NewHope Simple API
+
+// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
+
+extern crate amcl;
+
+use amcl::nhs;
+use amcl::rand::RAND;
+
+#[test]
+fn test_nhs() {
+ let mut raw: [u8; 100] = [0; 100];
+
+ let mut srng = RAND::new();
+ srng.clean();
+ for i in 0..100 {
+ raw[i] = (i + 1) as u8
+ }
+
+ srng.seed(100, &raw);
+
+ let mut crng = RAND::new();
+ crng.clean();
+ for i in 0..100 {
+ raw[i] = (i + 2) as u8
+ }
+
+ crng.seed(100, &raw);
+
+ let mut ss: [u8; 1792] = [0; 1792];
+ let mut sb: [u8; 1824] = [0; 1824];
+ let mut uc: [u8; 2176] = [0; 2176];
+
+ let mut keya: [u8; 32] = [0; 32];
+ let mut keyb: [u8; 32] = [0; 32];
+
+ nhs::server_1(&mut srng, &mut sb, &mut ss);
+
+ nhs::client(&mut crng, &sb, &mut uc, &mut keyb);
+
+ nhs::server_2(&ss, &uc, &mut keya);
+
+ for i in 0..keya.len() {
+ print!("{:02X}", keya[i]);
+ }
+ println!("");
+
+ for i in 0..keyb.len() {
+ print!("{:02X}", keyb[i]);
+ }
+ println!("");
+}