blob: 8900254d0d2c81f67acaee9f26b9411394ac7ac2 [file] [log] [blame]
/*
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.
*/
use std::io;
extern crate amcl;
use amcl::mpin;
use amcl::ecp;
use amcl::ecp2;
use amcl::fp;
use amcl::fp2;
use amcl::fp4;
use amcl::fp12;
use amcl::pair;
use amcl::big;
use amcl::dbig;
use amcl::rand;
use amcl::hash256;
use amcl::hash384;
use amcl::hash512;
use amcl::aes;
use amcl::rom;
use rand::RAND;
pub fn printbinary(array: &[u8]) {
for i in 0..array.len() {
print!("{:02X}", array[i])
}
println!("")
}
#[test]
fn test_mpin()
{
let mut raw:[u8;100]=[0;100];
let mut s:[u8;mpin::EGS]=[0;mpin::EGS];
const RM:usize=rom::MODBYTES as usize;
let mut hcid:[u8;RM]=[0;RM];
let mut hsid:[u8;RM]=[0;RM];
const G1S:usize=2*mpin::EFS+1; /* Group 1 Size */
const G2S:usize=4*mpin::EFS; /* Group 2 Size */
const EAS:usize=16;
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*mpin::EFS]=[0;12*mpin::EFS];
let mut g2: [u8;12*mpin::EFS]=[0;12*mpin::EFS];
let mut xid: [u8;G1S]=[0;G1S];
let mut xcid: [u8;G1S]=[0;G1S];
let mut x: [u8;mpin::EGS]=[0;mpin::EGS];
let mut y: [u8;mpin::EGS]=[0;mpin::EGS];
let mut sec: [u8;G1S]=[0;G1S];
let mut r: [u8;mpin::EGS]=[0;mpin::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;mpin::EGS]=[0;mpin::EGS];
let mut t: [u8;G1S]=[0;G1S];
let mut e: [u8;12*mpin::EFS]=[0;12*mpin::EFS];
let mut f: [u8;12*mpin::EFS]=[0;12*mpin::EFS];
let mut h: [u8;RM]=[0;RM];
let mut ck: [u8;EAS]=[0;EAS];
let mut sk: [u8;EAS]=[0;EAS];
let sha=mpin::HASH_TYPE;
let mut rng=RAND::new();
rng.clean();
for i in 0..100 {raw[i]=(i+1) as u8}
rng.seed(100,&raw);
/* 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 mpin::FULL {
mpin::precompute(&token,&hcid,&mut g1,&mut g2);
}
let mut date=0;
if mpin::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 mpin::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 mpin::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 !mpin::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 mpin::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 mpin::FULL {
let mut pxcid=None;
if mpin::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);
}
}