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 2020/03/25 08:20:32 UTC

[incubator-milagro-crypto-rust] 25/27: Cleaup tests and compiler warnings

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 df62cee823941598acede260afb074bf19b4aed0
Author: Kirk Baird <ba...@outlook.com>
AuthorDate: Wed Mar 25 18:40:57 2020 +1100

    Cleaup tests and compiler warnings
    
    Signed-off-by: Kirk Baird <ba...@outlook.com>
---
 Cargo.toml                                        |    4 +-
 TestALL.rs                                        | 1459 --------------------
 TestBLS.rs                                        |  190 ---
 TestNHS.rs                                        |   77 --
 readme.md                                         |    2 +-
 src/bls.rs                                        |   40 +-
 src/bls192.rs                                     |   38 +
 src/bls256.rs                                     |   38 +
 src/ecdh.rs                                       |  156 +++
 src/ecp.rs                                        |    2 +-
 src/gcm.rs                                        |    2 -
 src/lib.rs                                        |   11 +-
 src/mpin.rs                                       |  226 +++-
 src/mpin192.rs                                    |  227 +++-
 src/mpin256.rs                                    |  227 +++-
 src/nhs.rs                                        |   50 +
 src/roms/{rom_bn254CX_32.rs => rom_bn254cx_32.rs} |    6 +-
 src/roms/{rom_bn254CX_64.rs => rom_bn254cx_64.rs} |    6 +-
 src/rsa.rs                                        |   71 +
 src/test_utils/mod.rs                             |   21 +
 tests/test_all.rs                                 | 1473 ---------------------
 tests/test_bls.rs                                 |  190 ---
 tests/test_nhs.rs                                 |   71 -
 23 files changed, 1107 insertions(+), 3480 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 259e89f..834aa83 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,7 +16,7 @@ path = "src/lib.rs"
 [features]
 default = ["bn254"]
 all = [
-  "anssi","bls24","bls48","bls381","bls383","bls461","bn254","bn254CX",
+  "anssi","bls24","bls48","bls381","bls383","bls461","bn254","bn254cx",
   "brainpool","c25519","c41417","ed25519","fp256BN","fp512BN","goldilocks","hifive",
   "nist256","nist384","nist521","nums256e","nums256w","nums384e","nums384w","nums512e",
   "nums512w","rsa2048","rsa3072","rsa4096","secp256k1",
@@ -28,7 +28,7 @@ bls381 = []
 bls383 = []
 bls461 = []
 bn254 = []
-bn254CX = []
+bn254cx = []
 brainpool = []
 c25519 = []
 c41417 = []
diff --git a/TestALL.rs b/TestALL.rs
deleted file mode 100644
index 9c3e1d0..0000000
--- a/TestALL.rs
+++ /dev/null
@@ -1,1459 +0,0 @@
-/*
-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 ecdh_ed25519(mut rng: &mut RAND) {
-    //use amcl::ed25519;
-    use amcl::ed25519::ecdh;
-    use amcl::ed25519::ecp;
-
-    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 ")
-        }
-    }
-}
-
-fn ecdh_nist256(mut rng: &mut RAND) {
-    //use amcl::nist256;
-    use amcl::nist256::ecdh;
-    use amcl::nist256::ecp;
-
-    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 ")
-        }
-    }
-}
-
-fn ecdh_goldilocks(mut rng: &mut RAND) {
-    //use amcl::goldilocks;
-    use amcl::goldilocks::ecdh;
-    use amcl::goldilocks::ecp;
-
-    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 ")
-        }
-    }
-}
-
-fn mpin_bn254(mut rng: &mut RAND) {
-    //use amcl::bn254;
-    use amcl::bn254::ecp;
-    use amcl::bn254::mpin;
-    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);
-    }
-}
-
-fn mpin_bls383(mut rng: &mut RAND) {
-    //use amcl::bls383;
-    use amcl::bls383::ecp;
-    use amcl::bls383::mpin;
-    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);
-    }
-}
-
-fn mpin_bls24(mut rng: &mut RAND) {
-    //use amcl::bls24;
-    use amcl::bls24::ecp;
-    use amcl::bls24::mpin192;
-
-    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);
-    }
-}
-
-fn mpin_bls48(mut rng: &mut RAND) {
-    //use amcl::bls48;
-    use amcl::bls48::ecp;
-    use amcl::bls48::mpin256;
-
-    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);
-    }
-}
-
-fn rsa_2048(mut rng: &mut RAND) {
-    //use amcl::rsa2048;
-    use amcl::rsa2048::ff;
-    use amcl::rsa2048::rsa;
-
-    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);
-}
-
-//#[test]
-fn main() {
-    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);
-
-    ecdh_ed25519(&mut rng);
-    ecdh_nist256(&mut rng);
-    ecdh_goldilocks(&mut rng);
-    mpin_bn254(&mut rng);
-    mpin_bls383(&mut rng);
-    mpin_bls24(&mut rng);
-    mpin_bls48(&mut rng);
-    rsa_2048(&mut rng);
-}
diff --git a/TestBLS.rs b/TestBLS.rs
deleted file mode 100644
index 1a54ee4..0000000
--- a/TestBLS.rs
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
-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 bls_bn254(mut rng: &mut RAND) {
-    use amcl::bn254::bls;
-
-    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");
-    }
-}
-
-fn bls_bls383(mut rng: &mut RAND) {
-    use amcl::bls383::bls;
-
-    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");
-    }
-}
-
-fn bls_bls24(mut rng: &mut RAND) {
-    use amcl::bls24::bls192;
-
-    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");
-    }
-}
-
-fn bls_bls48(mut rng: &mut RAND) {
-    use amcl::bls48::bls256;
-
-    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");
-    }
-}
-
-fn main() {
-    use amcl::arch;
-
-    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);
-
-    println!("{} bit build", arch::CHUNK);
-
-    println!("Testing BLS signature for curve BN254");
-    bls_bn254(&mut rng);
-    println!("\nTesting BLS signature for curve BLS383");
-    bls_bls383(&mut rng);
-    println!("\nTesting BLS signature for curve BLS24");
-    bls_bls24(&mut rng);
-    println!("\nTesting BLS signature for curve BLS48");
-    bls_bls48(&mut rng);
-}
diff --git a/TestNHS.rs b/TestNHS.rs
deleted file mode 100644
index 4e7ed02..0000000
--- a/TestNHS.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-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.
-*/
-
-//  TestNHS.rs - Tests NewHope Simple API
-
-// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
-
-// rustc TestNHS.rs --extern amcl=libamcl.rlib
-
-extern crate amcl;
-
-//use std::str;
-//use std::io;
-
-use amcl::rand::RAND;
-//use amcl::aes;
-use amcl::nhs;
-
-//#[test]
-fn main()
-{
-	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!("");		
-
-}
\ No newline at end of file
diff --git a/readme.md b/readme.md
index 036defc..17091d5 100644
--- a/readme.md
+++ b/readme.md
@@ -76,7 +76,7 @@ Full list of features:
   * secp256k1
 * Pairing-Friendly Elliptic Curves
   * bn254
-  * bn254CX
+  * bn254cx
   * bls383
   * bls381
   * fp256BN
diff --git a/src/bls.rs b/src/bls.rs
index 07b8353..98c9a8b 100644
--- a/src/bls.rs
+++ b/src/bls.rs
@@ -54,7 +54,7 @@ fn bls_hashit(m: &str) -> ECP {
 pub fn key_pair_generate(mut rng: &mut RAND, s: &mut [u8], w: &mut [u8]) -> isize {
     let q = Big::new_ints(&rom::CURVE_ORDER);
     let g = ECP2::generator();
-    let mut sc = Big::randomnum(&q, &mut rng);
+    let sc = Big::randomnum(&q, &mut rng);
     sc.tobytes(s);
     pair::g2mul(&g, &sc).tobytes(w);
     BLS_OK
@@ -91,3 +91,41 @@ pub fn verify(sig: &[u8], m: &str, w: &[u8]) -> isize {
     }
     BLS_FAIL
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::test_utils::*;
+
+    #[test]
+    fn test_bls() {
+        let mut rng = create_rng();
+
+        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");
+
+        key_pair_generate(&mut rng, &mut s, &mut w);
+        print!("Private key : 0x");
+        printbinary(&s);
+        print!("Public  key : 0x");
+        printbinary(&w);
+
+        sign(&mut sig, &m, &s);
+        print!("Signature : 0x");
+        printbinary(&sig);
+
+        let res = verify(&sig, &m, &w);
+        if res == 0 {
+            println!("Signature is OK");
+        } else {
+            println!("Signature is *NOT* OK");
+        }
+    }
+}
diff --git a/src/bls192.rs b/src/bls192.rs
index 3654452..fb8e836 100644
--- a/src/bls192.rs
+++ b/src/bls192.rs
@@ -93,3 +93,41 @@ pub fn verify(sig: &[u8], m: &str, w: &[u8]) -> isize {
     }
     BLS_FAIL
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::test_utils::*;
+
+    #[test]
+    fn test_bls() {
+        let mut rng = create_rng();
+
+        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");
+
+        key_pair_generate(&mut rng, &mut s, &mut w);
+        print!("Private key : 0x");
+        printbinary(&s);
+        print!("Public  key : 0x");
+        printbinary(&w);
+
+        sign(&mut sig, &m, &s);
+        print!("Signature : 0x");
+        printbinary(&sig);
+
+        let res = verify(&sig, &m, &w);
+        if res == 0 {
+            println!("Signature is OK");
+        } else {
+            println!("Signature is *NOT* OK");
+        }
+    }
+}
diff --git a/src/bls256.rs b/src/bls256.rs
index c3722f3..b36566c 100644
--- a/src/bls256.rs
+++ b/src/bls256.rs
@@ -91,3 +91,41 @@ pub fn verify(sig: &[u8], m: &str, w: &[u8]) -> isize {
     }
     BLS_FAIL
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::test_utils::*;
+
+    #[test]
+    fn test_bls() {
+        let mut rng = create_rng();
+
+        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");
+
+        key_pair_generate(&mut rng, &mut s, &mut w);
+        print!("Private key : 0x");
+        printbinary(&s);
+        print!("Public  key : 0x");
+        printbinary(&w);
+
+        sign(&mut sig, &m, &s);
+        print!("Signature : 0x");
+        printbinary(&sig);
+
+        let res = verify(&sig, &m, &w);
+        if res == 0 {
+            println!("Signature is OK");
+        } else {
+            println!("Signature is *NOT* OK");
+        }
+    }
+}
diff --git a/src/ecdh.rs b/src/ecdh.rs
index 12aa34e..7a84d6b 100644
--- a/src/ecdh.rs
+++ b/src/ecdh.rs
@@ -745,3 +745,159 @@ pub fn ecies_decrypt(
 
     m
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::test_utils::*;
+    use crate::types::CurveType;
+
+    #[test]
+    fn test_ecdh() {
+
+        let mut rng = create_rng();
+
+        let pw = "M0ng00se";
+        let pp: &[u8] = b"M0ng00se";
+        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];
+        pbkdf2(sha, pp, &salt, 1000, EGS, &mut s0);
+
+        print!("Alice's private key= 0x");
+        printbinary(&s0);
+
+        /* Generate Key pair S/W */
+        key_pair_generate(None, &mut s0, &mut w0);
+
+        print!("Alice's public key= 0x");
+        printbinary(&w0);
+
+        let mut res = public_key_validate(&w0);
+        if res != 0 {
+            println!("ECP Public Key is invalid!");
+            return;
+        }
+
+        /* Random private key for other party */
+        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 = public_key_validate(&w1);
+        if res != 0 {
+            println!("ECP Public Key is invalid!");
+            return;
+        }
+        /* Calculate common key using DH - IEEE 1363 method */
+
+        ecpsvdp_dh(&s0, &w1, &mut z0);
+        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;
+        }
+
+        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 = 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 = 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 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 ecpvp_dsa(sha, &w0, &m[0..17], &cs, &ds) != 0 {
+                println!("***ECDSA Verification Failed");
+                return;
+            } else {
+                println!("ECDSA Signature/Verification succeeded ")
+            }
+        }
+    }
+}
diff --git a/src/ecp.rs b/src/ecp.rs
index b779e2d..07e19be 100644
--- a/src/ecp.rs
+++ b/src/ecp.rs
@@ -77,7 +77,7 @@ impl ECP {
         E.y.bcopy(iy);
         E.z.one();
         E.x.norm();
-        let mut rhs = ECP::rhs(&E.x);
+        let rhs = ECP::rhs(&E.x);
         if CURVETYPE == CurveType::Montgomery {
             if rhs.jacobi() != 1 {
                 E.inf();
diff --git a/src/gcm.rs b/src/gcm.rs
index b2c293f..6642781 100644
--- a/src/gcm.rs
+++ b/src/gcm.rs
@@ -22,8 +22,6 @@ const GCM_ACCEPTING_HEADER: usize = 0;
 const GCM_ACCEPTING_CIPHER: usize = 1;
 const GCM_NOT_ACCEPTING_MORE: usize = 2;
 const GCM_FINISHED: usize = 3;
-const GCM_ENCRYPTING: usize = 0;
-const GCM_DECRYPTING: usize = 1;
 
 use crate::aes;
 use crate::aes::AES;
diff --git a/src/lib.rs b/src/lib.rs
index c68a165..9849b2b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -467,14 +467,14 @@ pub mod ed25519 {
     pub mod fp;
 }
 
-#[cfg(feature = "bn254CX")]
+#[cfg(feature = "bn254cx")]
 #[path = "./"]
-pub mod bn254CX {
+pub mod bn254cx {
     #[cfg(target_pointer_width = "32")]
-    #[path = "roms/rom_bn254CX_32.rs"]
+    #[path = "roms/rom_bn254cx_32.rs"]
     pub mod rom;
     #[cfg(target_pointer_width = "64")]
-    #[path = "roms/rom_bn254CX_64.rs"]
+    #[path = "roms/rom_bn254cx_64.rs"]
     pub mod rom;
 
     pub mod big;
@@ -559,3 +559,6 @@ pub mod rsa4096 {
     mod rom;
     pub mod rsa;
 }
+
+#[cfg(test)]
+pub mod test_utils;
diff --git a/src/mpin.rs b/src/mpin.rs
index 425d03e..795fc50 100644
--- a/src/mpin.rs
+++ b/src/mpin.rs
@@ -351,7 +351,7 @@ pub fn recombine_g2(w1: &[u8], w2: &[u8], w: &mut [u8]) -> isize {
 /* create random secret S */
 pub fn random_generate(rng: &mut RAND, s: &mut [u8]) -> isize {
     let r = Big::new_ints(&rom::CURVE_ORDER);
-    let mut sc = Big::randomnum(&r, rng);
+    let sc = Big::randomnum(&r, rng);
     sc.tobytes(s);
     return 0;
 }
@@ -942,3 +942,227 @@ pub fn server_key(
 
     return 0;
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::test_utils::*;
+    use std::io;
+
+    #[test]
+    fn test_mpin() {
+        let mut rng = create_rng();
+
+        pub const PERMITS: bool = true;
+        pub const PINERROR: bool = true;
+        pub const FULL: bool = true;
+
+        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 */
+
+        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);
+
+        hash_id(sha, &client_id, &mut hcid); /* Either Client or TA calculates Hash(ID) - you decide! */
+
+        /* Client and Server are issued secrets by DTA */
+        get_server_secret(&s, &mut sst);
+        print!("Server Secret SS: 0x");
+        printbinary(&sst);
+
+        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 = 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 {
+            precompute(&token, &hcid, &mut g1, &mut g2);
+        }
+
+        let mut date = 0;
+        if PERMITS {
+            date = today();
+            /* Client gets "Time Token" permit from DTA */
+
+            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 */
+            encoding(&mut rng, &mut permit);
+            print!("Encoded Time Permit TP: 0x");
+            printbinary(&permit);
+            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 = 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 {
+            hash_id(sha, &client_id, &mut hcid);
+            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 PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+
+        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 */
+        random_generate(&mut rng, &mut y);
+
+        if FULL {
+            hash_id(sha, &client_id, &mut hsid);
+            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 = 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 = server_2(
+                date,
+                &hid,
+                Some(&htid[..]),
+                &y,
+                &sst,
+                Some(&xid[..]),
+                Some(&xcid[..]),
+                &sec,
+                None,
+                None,
+            );
+        } else {
+            rtn = server_2(
+                date,
+                &hid,
+                Some(&htid[..]),
+                &y,
+                &sst,
+                Some(&xid[..]),
+                Some(&xcid[..]),
+                &sec,
+                Some(&mut e),
+                Some(&mut f),
+            );
+        }
+
+        if rtn == BAD_PIN {
+            println!("Server says - Bad Pin. I don't know you. Feck off.");
+            if PINERROR {
+                let err = 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[..])
+            };
+
+            hash_all(sha, &hcid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+            client_key(sha, &g1, &g2, pin, &r, &x, &h, &t, &mut ck);
+            print!("Client Key =  0x");
+            printbinary(&ck);
+
+            hash_all(sha, &hsid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+            server_key(sha, &z, &sst, &w, &h, &hid, &xid, pxcid, &mut sk);
+            print!("Server Key =  0x");
+            printbinary(&sk);
+        }
+    }
+}
diff --git a/src/mpin192.rs b/src/mpin192.rs
index 63970d1..d2ed7b9 100644
--- a/src/mpin192.rs
+++ b/src/mpin192.rs
@@ -367,7 +367,7 @@ pub fn recombine_g2(w1: &[u8], w2: &[u8], w: &mut [u8]) -> isize {
 /* create random secret S */
 pub fn random_generate(rng: &mut RAND, s: &mut [u8]) -> isize {
     let r = Big::new_ints(&rom::CURVE_ORDER);
-    let mut sc = Big::randomnum(&r, rng);
+    let sc = Big::randomnum(&r, rng);
     sc.tobytes(s);
     return 0;
 }
@@ -957,3 +957,228 @@ pub fn server_key(
 
     return 0;
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::test_utils::*;
+    use std::io;
+
+    #[test]
+    fn test_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;
+
+        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 */
+
+        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);
+
+        hash_id(sha, &client_id, &mut hcid); /* Either Client or TA calculates Hash(ID) - you decide! */
+
+        /* Client and Server are issued secrets by DTA */
+        get_server_secret(&s, &mut sst);
+        print!("Server Secret SS: 0x");
+        printbinary(&sst);
+
+        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 = 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 {
+            precompute(&token, &hcid, &mut g1, &mut g2);
+        }
+
+        let mut date = 0;
+        if PERMITS {
+            date = today();
+            /* Client gets "Time Token" permit from DTA */
+
+            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 */
+            encoding(&mut rng, &mut permit);
+            print!("Encoded Time Permit TP: 0x");
+            printbinary(&permit);
+            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 = 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 {
+            hash_id(sha, &client_id, &mut hcid);
+            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 PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+
+        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 */
+        random_generate(&mut rng, &mut y);
+
+        if FULL {
+            hash_id(sha, &client_id, &mut hsid);
+            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 = 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 = server_2(
+                date,
+                &hid,
+                Some(&htid[..]),
+                &y,
+                &sst,
+                Some(&xid[..]),
+                Some(&xcid[..]),
+                &sec,
+                None,
+                None,
+            );
+        } else {
+            rtn = server_2(
+                date,
+                &hid,
+                Some(&htid[..]),
+                &y,
+                &sst,
+                Some(&xid[..]),
+                Some(&xcid[..]),
+                &sec,
+                Some(&mut e),
+                Some(&mut f),
+            );
+        }
+
+        if rtn == BAD_PIN {
+            println!("Server says - Bad Pin. I don't know you. Feck off.");
+            if PINERROR {
+                let err = 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[..])
+            };
+
+            hash_all(sha, &hcid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+            client_key(sha, &g1, &g2, pin, &r, &x, &h, &t, &mut ck);
+            print!("Client Key =  0x");
+            printbinary(&ck);
+
+            hash_all(sha, &hsid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+            server_key(sha, &z, &sst, &w, &h, &hid, &xid, pxcid, &mut sk);
+            print!("Server Key =  0x");
+            printbinary(&sk);
+        }
+    }
+}
diff --git a/src/mpin256.rs b/src/mpin256.rs
index 5f9cee9..65a06d9 100644
--- a/src/mpin256.rs
+++ b/src/mpin256.rs
@@ -400,7 +400,7 @@ pub fn recombine_g2(w1: &[u8], w2: &[u8], w: &mut [u8]) -> isize {
 /* create random secret S */
 pub fn random_generate(rng: &mut RAND, s: &mut [u8]) -> isize {
     let r = Big::new_ints(&rom::CURVE_ORDER);
-    let mut sc = Big::randomnum(&r, rng);
+    let sc = Big::randomnum(&r, rng);
     sc.tobytes(s);
     return 0;
 }
@@ -991,3 +991,228 @@ pub fn server_key(
 
     return 0;
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::test_utils::*;
+    use std::io;
+
+    #[test]
+    fn test_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;
+
+        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 */
+
+        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);
+
+        hash_id(sha, &client_id, &mut hcid); /* Either Client or TA calculates Hash(ID) - you decide! */
+
+        /* Client and Server are issued secrets by DTA */
+        get_server_secret(&s, &mut sst);
+        print!("Server Secret SS: 0x");
+        printbinary(&sst);
+
+        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 = 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 {
+            precompute(&token, &hcid, &mut g1, &mut g2);
+        }
+
+        let mut date = 0;
+        if PERMITS {
+            date = today();
+            /* Client gets "Time Token" permit from DTA */
+
+            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 */
+            encoding(&mut rng, &mut permit);
+            print!("Encoded Time Permit TP: 0x");
+            printbinary(&permit);
+            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 = 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 {
+            hash_id(sha, &client_id, &mut hcid);
+            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 PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+
+        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 */
+        random_generate(&mut rng, &mut y);
+
+        if FULL {
+            hash_id(sha, &client_id, &mut hsid);
+            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 = 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 = server_2(
+                date,
+                &hid,
+                Some(&htid[..]),
+                &y,
+                &sst,
+                Some(&xid[..]),
+                Some(&xcid[..]),
+                &sec,
+                None,
+                None,
+            );
+        } else {
+            rtn = server_2(
+                date,
+                &hid,
+                Some(&htid[..]),
+                &y,
+                &sst,
+                Some(&xid[..]),
+                Some(&xcid[..]),
+                &sec,
+                Some(&mut e),
+                Some(&mut f),
+            );
+        }
+
+        if rtn == BAD_PIN {
+            println!("Server says - Bad Pin. I don't know you. Feck off.");
+            if PINERROR {
+                let err = 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[..])
+            };
+
+            hash_all(sha, &hcid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+            client_key(sha, &g1, &g2, pin, &r, &x, &h, &t, &mut ck);
+            print!("Client Key =  0x");
+            printbinary(&ck);
+
+            hash_all(sha, &hsid, &xid, pxcid, &sec, &y, &z, &t, &mut h);
+            server_key(sha, &z, &sst, &w, &h, &hid, &xid, pxcid, &mut sk);
+            print!("Server Key =  0x");
+            printbinary(&sk);
+        }
+    }
+}
diff --git a/src/nhs.rs b/src/nhs.rs
index dda49b0..cf0f9c2 100644
--- a/src/nhs.rs
+++ b/src/nhs.rs
@@ -703,3 +703,53 @@ fn main() {
 
 }
 */
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[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];
+
+        server_1(&mut srng, &mut sb, &mut ss);
+
+        client(&mut crng, &sb, &mut uc, &mut keyb);
+
+        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!("");
+    }
+
+}
diff --git a/src/roms/rom_bn254CX_32.rs b/src/roms/rom_bn254cx_32.rs
similarity index 99%
rename from src/roms/rom_bn254CX_32.rs
rename to src/roms/rom_bn254cx_32.rs
index a6e7ef8..8884db3 100644
--- a/src/roms/rom_bn254CX_32.rs
+++ b/src/roms/rom_bn254cx_32.rs
@@ -18,11 +18,11 @@ under the License.
 */
 
 use super::super::arch::Chunk;
-use bn254CX::big::NLEN;
+use bn254cx::big::NLEN;
 use types::{CurvePairingType, CurveType, ModType, SexticTwist, SignOfX};
 
 // Base Bits= 28
-// bn254CX Modulus
+// bn254cx Modulus
 pub const MODULUS: [Chunk; NLEN] = [
     0xC1B55B3, 0x6623EF5, 0x93EE1BE, 0xD6EE180, 0x6D3243F, 0x647A636, 0xDB0BDDF, 0x8702A0,
     0x4000000, 0x2,
@@ -41,7 +41,7 @@ pub const FRB: [Chunk; NLEN] = [
     0xA6F7D0, 0x1,
 ];
 
-// bn254CX Curve
+// bn254cx Curve
 pub const CURVE_COF_I: isize = 1;
 pub const CURVE_A: isize = 0;
 pub const CURVE_B_I: isize = 2;
diff --git a/src/roms/rom_bn254CX_64.rs b/src/roms/rom_bn254cx_64.rs
similarity index 99%
rename from src/roms/rom_bn254CX_64.rs
rename to src/roms/rom_bn254cx_64.rs
index 097e205..8aa4f06 100644
--- a/src/roms/rom_bn254CX_64.rs
+++ b/src/roms/rom_bn254cx_64.rs
@@ -18,11 +18,11 @@ under the License.
 */
 
 use super::super::arch::Chunk;
-use bn254CX::big::NLEN;
+use bn254cx::big::NLEN;
 use types::{CurvePairingType, CurveType, ModType, SexticTwist, SignOfX};
 
 // Base Bits= 56
-// bn254CX Modulus
+// bn254cx Modulus
 pub const MODULUS: [Chunk; NLEN] = [
     0x6623EF5C1B55B3,
     0xD6EE18093EE1BE,
@@ -53,7 +53,7 @@ pub const FRB: [Chunk; NLEN] = [
     0x10A6F7D0,
 ];
 
-// bn254CX Curve
+// bn254cx Curve
 pub const CURVE_COF_I: isize = 1;
 pub const CURVE_A: isize = 0;
 pub const CURVE_B_I: isize = 2;
diff --git a/src/rsa.rs b/src/rsa.rs
index 1a59f7a..a3022e0 100644
--- a/src/rsa.rs
+++ b/src/rsa.rs
@@ -467,3 +467,74 @@ pub fn decrypt(prv: &RsaPrivateKey, g: &[u8], f: &mut [u8]) {
 
     r.tobytes(f);
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::test_utils::*;
+    use std::str;
+
+    #[test]
+    fn test_rsa() {
+        let mut rng = create_rng();
+
+        let sha = super::HASH_TYPE;
+        let message: &[u8] = b"Hello World\n";
+        const RFS: usize = super::RFS;
+
+        let mut pbc = super::new_public_key(ff::FFLEN);
+        let mut prv = super::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");
+        super::key_pair(&mut rng, 65537, &mut prv, &mut pbc);
+
+        println!("Encrypting test string\n");
+        super::oaep_encode(sha, &message, &mut rng, None, &mut e); /* OAEP encode message M to E  */
+
+        super::encrypt(&pbc, &e, &mut c); /* encrypt encoded message */
+        print!("Ciphertext= 0x");
+        printbinary(&c);
+
+        println!("Decrypting test string");
+        super::decrypt(&prv, &c, &mut ml);
+        let mlen = super::oaep_decode(sha, None, &mut ml); /* OAEP decode message  */
+
+        let mess = str::from_utf8(&ml[0..mlen]).unwrap();
+        print!("{}", &mess);
+
+        println!("Signing message");
+        super::pkcs15(sha, message, &mut c);
+
+        super::decrypt(&prv, &c, &mut s); /* create signature in S */
+
+        print!("Signature= 0x");
+        printbinary(&s);
+
+        super::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");
+        }
+
+        super::private_key_kill(&mut prv);
+    }
+}
diff --git a/src/test_utils/mod.rs b/src/test_utils/mod.rs
new file mode 100644
index 0000000..4c85c50
--- /dev/null
+++ b/src/test_utils/mod.rs
@@ -0,0 +1,21 @@
+use crate::rand::RAND;
+
+pub fn printbinary(array: &[u8]) {
+    for i in 0..array.len() {
+        print!("{:02X}", array[i])
+    }
+    println!("")
+}
+
+pub 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
+}
diff --git a/tests/test_all.rs b/tests/test_all.rs
deleted file mode 100644
index c543dac..0000000
--- a/tests/test_all.rs
+++ /dev/null
@@ -1,1473 +0,0 @@
-/*
-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
deleted file mode 100644
index 20cf73b..0000000
--- a/tests/test_bls.rs
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
-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
deleted file mode 100644
index f272291..0000000
--- a/tests/test_nhs.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-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!("");
-}