blob: cef42d737d7345670a6535e66bc8f3b552394cbd [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.
*/
//
// TestECDH.swift
//
// Created by Michael Scott on 02/07/2015.
// Copyright (c) 2015 Michael Scott. All rights reserved.
//
import Foundation
import amcl // comment out for Xcode
import ed25519
import nist256
import goldilocks
import bn254
import bls383
import bls24
import bls48
import rsa2048
public func printBinary(_ array: [UInt8])
{
for i in 0 ..< array.count
{
let h=String(format:"%02x",array[i])
print("\(h)", terminator: "")
}
print(" ");
}
public func TestRSA_2048(_ rng: inout RAND)
{
let RFS=RSA.RFS
var message="Hello World\n"
var pub=rsa_public_key(Int(FF.FFLEN))
var priv=rsa_private_key(Int(FF.HFLEN))
var ML=[UInt8](repeating: 0,count: RFS)
var C=[UInt8](repeating: 0,count: RFS)
var S=[UInt8](repeating: 0,count: RFS)
print("\nGenerating RSA public/private key pair")
RSA.KEY_PAIR(&rng,65537,&priv,&pub)
let M=[UInt8](message.utf8)
print("Encrypting test string\n");
let E=RSA.OAEP_ENCODE(RSA.HASH_TYPE,M,&rng,nil); /* OAEP encode message m to e */
RSA.ENCRYPT(pub,E,&C); /* encrypt encoded message */
print("Ciphertext= 0x", terminator: ""); printBinary(C)
print("Decrypting test string\n");
RSA.DECRYPT(priv,C,&ML)
var MS=RSA.OAEP_DECODE(RSA.HASH_TYPE,nil,&ML) /* OAEP encode message m to e */
message=""
for i in 0 ..< MS.count
{
message+=String(UnicodeScalar(MS[i]))
}
print(message);
print("Signing message")
RSA.PKCS15(RSA.HASH_TYPE,M,&C)
RSA.DECRYPT(priv,C,&S); // create signature in S
print("Signature= 0x",terminator: ""); printBinary(S)
RSA.ENCRYPT(pub,S,&ML);
var cmp=true
if C.count != ML.count {cmp=false}
else
{
for j in 0 ..< C.count
{
if C[j] != ML[j] {cmp=false}
}
}
if cmp {print("\nSignature is valid\n")}
else {print("\nSignature is INVALID\n")}
RSA.PRIVATE_KEY_KILL(priv);
}
public func TestECDH_ed25519(_ rng: inout RAND)
{
let pp=String("M0ng00se");
let EGS=ed25519.ECDH.EGS
let EFS=ed25519.ECDH.EFS
let EAS=ed25519.ECP.AESKEY
let sha=ed25519.ECP.HASH_TYPE
var S1=[UInt8](repeating: 0,count: EGS)
var W0=[UInt8](repeating: 0,count: 2*EFS+1)
var W1=[UInt8](repeating: 0,count: 2*EFS+1)
var Z0=[UInt8](repeating: 0,count: EFS)
var Z1=[UInt8](repeating: 0,count: EFS)
var SALT=[UInt8](repeating: 0,count: 8)
var P1=[UInt8](repeating: 0,count: 3)
var P2=[UInt8](repeating: 0,count: 4)
var V=[UInt8](repeating: 0,count: 2*EFS+1)
var M=[UInt8](repeating: 0,count: 17)
var T=[UInt8](repeating: 0,count: 12)
var CS=[UInt8](repeating: 0,count: EGS)
var DS=[UInt8](repeating: 0,count: EGS)
var NULLRNG : RAND? = nil
var REALRNG : RAND? = rng
for i in 0 ..< 8 {SALT[i]=UInt8(i+1)} // set Salt
print("\nAlice's Passphrase= " + pp)
let PW=[UInt8]( (pp).utf8 )
/* private key S0 of size EGS bytes derived from Password and Salt */
/* Note use of curve name here to disambiguate between supported curves!! */
/* Not needed if only one curve supported */
var S0=ed25519.ECDH.PBKDF2(sha,PW,SALT,1000,EGS)
print("Alice's private key= 0x",terminator: ""); printBinary(S0)
/* Generate Key pair S/W */
ed25519.ECDH.KEY_PAIR_GENERATE(&NULLRNG,&S0,&W0);
print("Alice's public key= 0x",terminator: ""); printBinary(W0)
var res=ed25519.ECDH.PUBLIC_KEY_VALIDATE(W0);
if res != 0
{
print("ECP Public Key is invalid!");
return;
}
/* Random private key for other party */
ed25519.ECDH.KEY_PAIR_GENERATE(&REALRNG,&S1,&W1)
print("Servers private key= 0x",terminator: ""); printBinary(S1)
print("Servers public key= 0x",terminator: ""); printBinary(W1);
res=ed25519.ECDH.PUBLIC_KEY_VALIDATE(W1)
if res != 0
{
print("ECP Public Key is invalid!")
return
}
/* Calculate common key using DH - IEEE 1363 method */
ed25519.ECDH.ECPSVDP_DH(S0,W1,&Z0)
ed25519.ECDH.ECPSVDP_DH(S1,W0,&Z1)
var same=true
for i in 0 ..< EFS
{
if Z0[i] != Z1[i] {same=false}
}
if (!same)
{
print("*** ECPSVDP-DH Failed")
return
}
let KEY=ed25519.ECDH.KDF2(sha,Z0,nil,EAS)
print("Alice's DH Key= 0x",terminator: ""); printBinary(KEY)
print("Servers DH Key= 0x",terminator: ""); printBinary(KEY)
if ed25519.ECP.CURVETYPE != ed25519.ECP.MONTGOMERY
{
print("Testing ECIES")
P1[0]=0x0; P1[1]=0x1; P1[2]=0x2
P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3
for i in 0...16 {M[i]=UInt8(i&0xff)}
let C=ed25519.ECDH.ECIES_ENCRYPT(sha,P1,P2,&REALRNG,W1,M,&V,&T)
print("Ciphertext= ")
print("V= 0x",terminator: ""); printBinary(V)
print("C= 0x",terminator: ""); printBinary(C)
print("T= 0x",terminator: ""); printBinary(T)
M=ed25519.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1)
if M.count==0
{
print("*** ECIES Decryption Failed\n")
return
}
else {print("Decryption succeeded")}
print("Message is 0x",terminator: ""); printBinary(M)
print("Testing ECDSA")
if ed25519.ECDH.ECPSP_DSA(sha,&rng,S0,M,&CS,&DS) != 0
{
print("***ECDSA Signature Failed")
return
}
print("Signature= ")
print("C= 0x",terminator: ""); printBinary(CS)
print("D= 0x",terminator: ""); printBinary(DS)
if ed25519.ECDH.ECPVP_DSA(sha,W0,M,CS,DS) != 0
{
print("***ECDSA Verification Failed")
return
}
else {print("ECDSA Signature/Verification succeeded ")}
}
rng=REALRNG!
}
public func TestECDH_nist256(_ rng: inout RAND)
{
let pp=String("M0ng00se");
let EGS=nist256.ECDH.EGS
let EFS=nist256.ECDH.EFS
let EAS=nist256.ECP.AESKEY
let sha=nist256.ECP.HASH_TYPE
var S1=[UInt8](repeating: 0,count: EGS)
var W0=[UInt8](repeating: 0,count: 2*EFS+1)
var W1=[UInt8](repeating: 0,count: 2*EFS+1)
var Z0=[UInt8](repeating: 0,count: EFS)
var Z1=[UInt8](repeating: 0,count: EFS)
var SALT=[UInt8](repeating: 0,count: 8)
var P1=[UInt8](repeating: 0,count: 3)
var P2=[UInt8](repeating: 0,count: 4)
var V=[UInt8](repeating: 0,count: 2*EFS+1)
var M=[UInt8](repeating: 0,count: 17)
var T=[UInt8](repeating: 0,count: 12)
var CS=[UInt8](repeating: 0,count: EGS)
var DS=[UInt8](repeating: 0,count: EGS)
var NULLRNG : RAND? = nil
var REALRNG : RAND? = rng
for i in 0 ..< 8 {SALT[i]=UInt8(i+1)} // set Salt
print("\nAlice's Passphrase= " + pp)
let PW=[UInt8]( (pp).utf8 )
/* private key S0 of size EGS bytes derived from Password and Salt */
/* Note use of curve name here to disambiguate between supported curves!! */
/* Not needed if only one curve supported */
var S0=nist256.ECDH.PBKDF2(sha,PW,SALT,1000,EGS)
print("Alice's private key= 0x",terminator: ""); printBinary(S0)
/* Generate Key pair S/W */
nist256.ECDH.KEY_PAIR_GENERATE(&NULLRNG,&S0,&W0);
print("Alice's public key= 0x",terminator: ""); printBinary(W0)
var res=nist256.ECDH.PUBLIC_KEY_VALIDATE(W0);
if res != 0
{
print("ECP Public Key is invalid!");
return;
}
/* Random private key for other party */
nist256.ECDH.KEY_PAIR_GENERATE(&REALRNG,&S1,&W1)
print("Servers private key= 0x",terminator: ""); printBinary(S1)
print("Servers public key= 0x",terminator: ""); printBinary(W1);
res=nist256.ECDH.PUBLIC_KEY_VALIDATE(W1)
if res != 0
{
print("ECP Public Key is invalid!")
return
}
/* Calculate common key using DH - IEEE 1363 method */
nist256.ECDH.ECPSVDP_DH(S0,W1,&Z0)
nist256.ECDH.ECPSVDP_DH(S1,W0,&Z1)
var same=true
for i in 0 ..< EFS
{
if Z0[i] != Z1[i] {same=false}
}
if (!same)
{
print("*** ECPSVDP-DH Failed")
return
}
let KEY=nist256.ECDH.KDF2(sha,Z0,nil,EAS)
print("Alice's DH Key= 0x",terminator: ""); printBinary(KEY)
print("Servers DH Key= 0x",terminator: ""); printBinary(KEY)
if nist256.ECP.CURVETYPE != nist256.ECP.MONTGOMERY
{
print("Testing ECIES")
P1[0]=0x0; P1[1]=0x1; P1[2]=0x2
P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3
for i in 0...16 {M[i]=UInt8(i&0xff)}
let C=nist256.ECDH.ECIES_ENCRYPT(sha,P1,P2,&REALRNG,W1,M,&V,&T)
print("Ciphertext= ")
print("V= 0x",terminator: ""); printBinary(V)
print("C= 0x",terminator: ""); printBinary(C)
print("T= 0x",terminator: ""); printBinary(T)
M=nist256.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1)
if M.count==0
{
print("*** ECIES Decryption Failed\n")
return
}
else {print("Decryption succeeded")}
print("Message is 0x",terminator: ""); printBinary(M)
print("Testing ECDSA")
if nist256.ECDH.ECPSP_DSA(sha,&rng,S0,M,&CS,&DS) != 0
{
print("***ECDSA Signature Failed")
return
}
print("Signature= ")
print("C= 0x",terminator: ""); printBinary(CS)
print("D= 0x",terminator: ""); printBinary(DS)
if nist256.ECDH.ECPVP_DSA(sha,W0,M,CS,DS) != 0
{
print("***ECDSA Verification Failed")
return
}
else {print("ECDSA Signature/Verification succeeded ")}
}
rng=REALRNG!
}
public func TestECDH_goldilocks(_ rng: inout RAND)
{
let pp=String("M0ng00se");
let EGS=goldilocks.ECDH.EGS
let EFS=goldilocks.ECDH.EFS
let EAS=goldilocks.ECP.AESKEY
let sha=goldilocks.ECP.HASH_TYPE
var S1=[UInt8](repeating: 0,count: EGS)
var W0=[UInt8](repeating: 0,count: 2*EFS+1)
var W1=[UInt8](repeating: 0,count: 2*EFS+1)
var Z0=[UInt8](repeating: 0,count: EFS)
var Z1=[UInt8](repeating: 0,count: EFS)
var SALT=[UInt8](repeating: 0,count: 8)
var P1=[UInt8](repeating: 0,count: 3)
var P2=[UInt8](repeating: 0,count: 4)
var V=[UInt8](repeating: 0,count: 2*EFS+1)
var M=[UInt8](repeating: 0,count: 17)
var T=[UInt8](repeating: 0,count: 12)
var CS=[UInt8](repeating: 0,count: EGS)
var DS=[UInt8](repeating: 0,count: EGS)
var NULLRNG : RAND? = nil
var REALRNG : RAND? = rng
for i in 0 ..< 8 {SALT[i]=UInt8(i+1)} // set Salt
print("\nAlice's Passphrase= " + pp)
let PW=[UInt8]( (pp).utf8 )
/* private key S0 of size EGS bytes derived from Password and Salt */
/* Note use of curve name here to disambiguate between supported curves!! */
/* Not needed if only one curve supported */
var S0=goldilocks.ECDH.PBKDF2(sha,PW,SALT,1000,EGS)
print("Alice's private key= 0x",terminator: ""); printBinary(S0)
/* Generate Key pair S/W */
goldilocks.ECDH.KEY_PAIR_GENERATE(&NULLRNG,&S0,&W0);
print("Alice's public key= 0x",terminator: ""); printBinary(W0)
var res=goldilocks.ECDH.PUBLIC_KEY_VALIDATE(W0);
if res != 0
{
print("ECP Public Key is invalid!");
return;
}
/* Random private key for other party */
goldilocks.ECDH.KEY_PAIR_GENERATE(&REALRNG,&S1,&W1)
print("Servers private key= 0x",terminator: ""); printBinary(S1)
print("Servers public key= 0x",terminator: ""); printBinary(W1);
res=goldilocks.ECDH.PUBLIC_KEY_VALIDATE(W1)
if res != 0
{
print("ECP Public Key is invalid!")
return
}
/* Calculate common key using DH - IEEE 1363 method */
goldilocks.ECDH.ECPSVDP_DH(S0,W1,&Z0)
goldilocks.ECDH.ECPSVDP_DH(S1,W0,&Z1)
var same=true
for i in 0 ..< EFS
{
if Z0[i] != Z1[i] {same=false}
}
if (!same)
{
print("*** ECPSVDP-DH Failed")
return
}
let KEY=goldilocks.ECDH.KDF2(sha,Z0,nil,EAS)
print("Alice's DH Key= 0x",terminator: ""); printBinary(KEY)
print("Servers DH Key= 0x",terminator: ""); printBinary(KEY)
if goldilocks.ECP.CURVETYPE != goldilocks.ECP.MONTGOMERY
{
print("Testing ECIES")
P1[0]=0x0; P1[1]=0x1; P1[2]=0x2
P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3
for i in 0...16 {M[i]=UInt8(i&0xff)}
let C=goldilocks.ECDH.ECIES_ENCRYPT(sha,P1,P2,&REALRNG,W1,M,&V,&T)
print("Ciphertext= ")
print("V= 0x",terminator: ""); printBinary(V)
print("C= 0x",terminator: ""); printBinary(C)
print("T= 0x",terminator: ""); printBinary(T)
M=goldilocks.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1)
if M.count==0
{
print("*** ECIES Decryption Failed\n")
return
}
else {print("Decryption succeeded")}
print("Message is 0x",terminator: ""); printBinary(M)
print("Testing ECDSA")
if goldilocks.ECDH.ECPSP_DSA(sha,&rng,S0,M,&CS,&DS) != 0
{
print("***ECDSA Signature Failed")
return
}
print("Signature= ")
print("C= 0x",terminator: ""); printBinary(CS)
print("D= 0x",terminator: ""); printBinary(DS)
if goldilocks.ECDH.ECPVP_DSA(sha,W0,M,CS,DS) != 0
{
print("***ECDSA Verification Failed")
return
}
else {print("ECDSA Signature/Verification succeeded ")}
}
rng=REALRNG!
}
public func TestMPIN_bn254(_ rng: inout RAND)
{
let PERMITS=true
let PINERROR=true
let FULL=true
let SINGLE_PASS=true
let EGS=bn254.MPIN.EFS
let EFS=bn254.MPIN.EGS
let G1S=2*EFS+1 // Group 1 Size
let G2S=4*EFS; // Group 2 Size
let EAS=bn254.ECP.AESKEY
let sha=bn254.ECP.HASH_TYPE
var S=[UInt8](repeating: 0,count: EGS)
var SST=[UInt8](repeating: 0,count: G2S)
var TOKEN=[UInt8](repeating: 0,count: G1S)
var PERMIT=[UInt8](repeating: 0,count: G1S)
var SEC=[UInt8](repeating: 0,count: G1S)
var xID=[UInt8](repeating: 0,count: G1S)
var xCID=[UInt8](repeating: 0,count: G1S)
var X=[UInt8](repeating: 0,count: EGS)
var Y=[UInt8](repeating: 0,count: EGS)
var E=[UInt8](repeating: 0,count: 12*EFS)
var F=[UInt8](repeating: 0,count: 12*EFS)
var HID=[UInt8](repeating: 0,count: G1S)
var HTID=[UInt8](repeating: 0,count: G1S)
var G1=[UInt8](repeating: 0,count: 12*EFS)
var G2=[UInt8](repeating: 0,count: 12*EFS)
var R=[UInt8](repeating: 0,count: EGS)
var Z=[UInt8](repeating: 0,count: G1S)
var W=[UInt8](repeating: 0,count: EGS)
var T=[UInt8](repeating: 0,count: G1S)
var CK=[UInt8](repeating: 0,count: EAS)
var SK=[UInt8](repeating: 0,count: EAS)
var HSID=[UInt8]()
// Trusted Authority set-up
bn254.MPIN.RANDOM_GENERATE(&rng,&S)
print("\nMPIN Master Secret s: 0x",terminator: ""); printBinary(S)
// Create Client Identity
let IDstr = "testUser@miracl.com"
let CLIENT_ID=[UInt8](IDstr.utf8)
var HCID=bn254.MPIN.HASH_ID(sha,CLIENT_ID) // Either Client or TA calculates Hash(ID) - you decide!
print("Client ID= "); printBinary(CLIENT_ID)
// Client and Server are issued secrets by DTA
bn254.MPIN.GET_SERVER_SECRET(S,&SST);
print("Server Secret SS: 0x",terminator: ""); printBinary(SST);
bn254.MPIN.GET_CLIENT_SECRET(&S,HCID,&TOKEN);
print("Client Secret CS: 0x",terminator: ""); printBinary(TOKEN);
// Client extracts PIN from secret to create Token
var pin:Int32=1234
print("Client extracts PIN= \(pin)")
var rtn=bn254.MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,&TOKEN)
if rtn != 0 {print("FAILURE: EXTRACT_PIN rtn: \(rtn)")}
print("Client Token TK: 0x",terminator: ""); printBinary(TOKEN);
if FULL
{
bn254.MPIN.PRECOMPUTE(TOKEN,HCID,&G1,&G2);
}
var date:Int32=0
if (PERMITS)
{
date=bn254.MPIN.today()
// Client gets "Time Token" permit from DTA
bn254.MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,&PERMIT)
print("Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
// This encoding makes Time permit look random - Elligator squared
bn254.MPIN.ENCODING(&rng,&PERMIT);
print("Encoded Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
bn254.MPIN.DECODING(&PERMIT)
print("Decoded Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
}
// ***** NOW ENTER PIN *******
pin=1234
// **************************
// Set date=0 and PERMIT=null if time permits not in use
//Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and PERMIT. Output xID =x .H(CLIENT_ID) and re-combined secret SEC
//If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H(date|H(CLIENT_ID)))
//Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
//IMPORTANT: To save space and time..
//If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
//If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
//If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.
var pxID:[UInt8]?=xID
var pxCID:[UInt8]?=xCID
var pHID:[UInt8]=HID
var pHTID:[UInt8]?=HTID
var pE:[UInt8]?=E
var pF:[UInt8]?=F
var pPERMIT:[UInt8]?=PERMIT
var REALRNG : RAND? = rng
if date != 0
{
if (!PINERROR)
{
pxID=nil; // problem here - either comment out here or dont use with ! later on
// pHID=nil;
}
}
else
{
pPERMIT=nil;
pxCID=nil;
pHTID=nil;
}
if (!PINERROR)
{
pE=nil;
pF=nil;
}
if (SINGLE_PASS)
{
print("MPIN Single Pass")
let timeValue = bn254.MPIN.GET_TIME()
rtn=bn254.MPIN.CLIENT(sha,date,CLIENT_ID,&REALRNG,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT,timeValue,&Y)
if rtn != 0 {print("FAILURE: CLIENT rtn: \(rtn)")}
if (FULL)
{
HCID=bn254.MPIN.HASH_ID(sha,CLIENT_ID);
bn254.MPIN.GET_G1_MULTIPLE(&REALRNG,1,&R,HCID,&Z); // Also Send Z=r.ID to Server, remember random r
}
rtn=bn254.MPIN.SERVER(sha,date,&pHID,&pHTID,&Y,SST,pxID,pxCID!,SEC,&pE,&pF,CLIENT_ID,timeValue)
if rtn != 0 {print("FAILURE: SERVER rtn: \(rtn)")}
if (FULL)
{ // Also send T=w.ID to client, remember random w
HSID=bn254.MPIN.HASH_ID(sha,CLIENT_ID);
if date != 0 {bn254.MPIN.GET_G1_MULTIPLE(&REALRNG,0,&W,pHTID!,&T)}
else {bn254.MPIN.GET_G1_MULTIPLE(&REALRNG,0,&W,pHID,&T)}
}
}
else
{
print("MPIN Multi Pass");
// Send U=x.ID to server, and recreate secret from token and pin
rtn=bn254.MPIN.CLIENT_1(sha,date,CLIENT_ID,&REALRNG,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT)
if rtn != 0 {print("FAILURE: CLIENT_1 rtn: \(rtn)")}
if (FULL)
{
HCID=bn254.MPIN.HASH_ID(sha,CLIENT_ID);
bn254.MPIN.GET_G1_MULTIPLE(&REALRNG,1,&R,HCID,&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.
bn254.MPIN.SERVER_1(sha,date,CLIENT_ID,&pHID,&pHTID);
// Server generates Random number Y and sends it to Client
bn254.MPIN.RANDOM_GENERATE(&REALRNG!,&Y);
if (FULL)
{ // Also send T=w.ID to client, remember random w
HSID=bn254.MPIN.HASH_ID(sha,CLIENT_ID);
if date != 0 {bn254.MPIN.GET_G1_MULTIPLE(&REALRNG,0,&W,pHTID!,&T)}
else {bn254.MPIN.GET_G1_MULTIPLE(&REALRNG,0,&W,pHID,&T)}
}
// Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC
rtn=bn254.MPIN.CLIENT_2(X,Y,&SEC);
if rtn != 0 {print("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
rtn=bn254.MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,&pE,&pF);
if rtn != 0 {print("FAILURE: SERVER_1 rtn: \(rtn)")}
}
if (rtn == bn254.MPIN.BAD_PIN)
{
print("Server says - Bad Pin. I don't know you. Feck off.\n");
if (PINERROR)
{
let err=bn254.MPIN.KANGAROO(pE,pF);
if err != 0 {print("(Client PIN is out by \(err))\n")}
}
return;
}
else {print("Server says - PIN is good! You really are "+IDstr)}
if (FULL)
{
var H=bn254.MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
bn254.MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,&CK);
print("Client Key = 0x",terminator: ""); printBinary(CK)
H=bn254.MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
bn254.MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID!,pxCID,&SK);
print("Server Key = 0x",terminator: ""); printBinary(SK)
}
rng=REALRNG!
}
public func TestMPIN_bls383(_ rng: inout RAND)
{
let PERMITS=true
let PINERROR=true
let FULL=true
let SINGLE_PASS=true
let EGS=bls383.MPIN.EFS
let EFS=bls383.MPIN.EGS
let G1S=2*EFS+1 // Group 1 Size
let G2S=4*EFS; // Group 2 Size
let EAS=bls383.ECP.AESKEY
let sha=bls383.ECP.HASH_TYPE
var S=[UInt8](repeating: 0,count: EGS)
var SST=[UInt8](repeating: 0,count: G2S)
var TOKEN=[UInt8](repeating: 0,count: G1S)
var PERMIT=[UInt8](repeating: 0,count: G1S)
var SEC=[UInt8](repeating: 0,count: G1S)
var xID=[UInt8](repeating: 0,count: G1S)
var xCID=[UInt8](repeating: 0,count: G1S)
var X=[UInt8](repeating: 0,count: EGS)
var Y=[UInt8](repeating: 0,count: EGS)
var E=[UInt8](repeating: 0,count: 12*EFS)
var F=[UInt8](repeating: 0,count: 12*EFS)
var HID=[UInt8](repeating: 0,count: G1S)
var HTID=[UInt8](repeating: 0,count: G1S)
var G1=[UInt8](repeating: 0,count: 12*EFS)
var G2=[UInt8](repeating: 0,count: 12*EFS)
var R=[UInt8](repeating: 0,count: EGS)
var Z=[UInt8](repeating: 0,count: G1S)
var W=[UInt8](repeating: 0,count: EGS)
var T=[UInt8](repeating: 0,count: G1S)
var CK=[UInt8](repeating: 0,count: EAS)
var SK=[UInt8](repeating: 0,count: EAS)
var HSID=[UInt8]()
// Trusted Authority set-up
bls383.MPIN.RANDOM_GENERATE(&rng,&S)
print("\nMPIN Master Secret s: 0x",terminator: ""); printBinary(S)
// Create Client Identity
let IDstr = "testUser@miracl.com"
let CLIENT_ID=[UInt8](IDstr.utf8)
var HCID=bls383.MPIN.HASH_ID(sha,CLIENT_ID) // Either Client or TA calculates Hash(ID) - you decide!
print("Client ID= "); printBinary(CLIENT_ID)
// Client and Server are issued secrets by DTA
bls383.MPIN.GET_SERVER_SECRET(S,&SST);
print("Server Secret SS: 0x",terminator: ""); printBinary(SST);
bls383.MPIN.GET_CLIENT_SECRET(&S,HCID,&TOKEN);
print("Client Secret CS: 0x",terminator: ""); printBinary(TOKEN);
// Client extracts PIN from secret to create Token
var pin:Int32=1234
print("Client extracts PIN= \(pin)")
var rtn=bls383.MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,&TOKEN)
if rtn != 0 {print("FAILURE: EXTRACT_PIN rtn: \(rtn)")}
print("Client Token TK: 0x",terminator: ""); printBinary(TOKEN);
if FULL
{
bls383.MPIN.PRECOMPUTE(TOKEN,HCID,&G1,&G2);
}
var date:Int32=0
if (PERMITS)
{
date=bls383.MPIN.today()
// Client gets "Time Token" permit from DTA
bls383.MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,&PERMIT)
print("Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
// This encoding makes Time permit look random - Elligator squared
bls383.MPIN.ENCODING(&rng,&PERMIT);
print("Encoded Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
bls383.MPIN.DECODING(&PERMIT)
print("Decoded Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
}
// ***** NOW ENTER PIN *******
pin=1234
// **************************
// Set date=0 and PERMIT=null if time permits not in use
//Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and PERMIT. Output xID =x .H(CLIENT_ID) and re-combined secret SEC
//If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H(date|H(CLIENT_ID)))
//Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
//IMPORTANT: To save space and time..
//If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
//If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
//If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.
var pxID:[UInt8]?=xID
var pxCID:[UInt8]?=xCID
var pHID:[UInt8]=HID
var pHTID:[UInt8]?=HTID
var pE:[UInt8]?=E
var pF:[UInt8]?=F
var pPERMIT:[UInt8]?=PERMIT
var REALRNG : RAND? = rng
if date != 0
{
if (!PINERROR)
{
pxID=nil; // problem here - either comment out here or dont use with ! later on
// pHID=nil;
}
}
else
{
pPERMIT=nil;
pxCID=nil;
pHTID=nil;
}
if (!PINERROR)
{
pE=nil;
pF=nil;
}
if (SINGLE_PASS)
{
print("MPIN Single Pass")
let timeValue = bls383.MPIN.GET_TIME()
rtn=bls383.MPIN.CLIENT(sha,date,CLIENT_ID,&REALRNG,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT,timeValue,&Y)
if rtn != 0 {print("FAILURE: CLIENT rtn: \(rtn)")}
if (FULL)
{
HCID=bls383.MPIN.HASH_ID(sha,CLIENT_ID);
bls383.MPIN.GET_G1_MULTIPLE(&REALRNG,1,&R,HCID,&Z); // Also Send Z=r.ID to Server, remember random r
}
rtn=bls383.MPIN.SERVER(sha,date,&pHID,&pHTID,&Y,SST,pxID,pxCID!,SEC,&pE,&pF,CLIENT_ID,timeValue)
if rtn != 0 {print("FAILURE: SERVER rtn: \(rtn)")}
if (FULL)
{ // Also send T=w.ID to client, remember random w
HSID=bls383.MPIN.HASH_ID(sha,CLIENT_ID);
if date != 0 {bls383.MPIN.GET_G1_MULTIPLE(&REALRNG,0,&W,pHTID!,&T)}
else {bls383.MPIN.GET_G1_MULTIPLE(&REALRNG,0,&W,pHID,&T)}
}
}
else
{
print("MPIN Multi Pass");
// Send U=x.ID to server, and recreate secret from token and pin
rtn=bls383.MPIN.CLIENT_1(sha,date,CLIENT_ID,&REALRNG,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT)
if rtn != 0 {print("FAILURE: CLIENT_1 rtn: \(rtn)")}
if (FULL)
{
HCID=bls383.MPIN.HASH_ID(sha,CLIENT_ID);
bls383.MPIN.GET_G1_MULTIPLE(&REALRNG,1,&R,HCID,&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.
bls383.MPIN.SERVER_1(sha,date,CLIENT_ID,&pHID,&pHTID);
// Server generates Random number Y and sends it to Client
bls383.MPIN.RANDOM_GENERATE(&REALRNG!,&Y);
if (FULL)
{ // Also send T=w.ID to client, remember random w
HSID=bls383.MPIN.HASH_ID(sha,CLIENT_ID);
if date != 0 {bls383.MPIN.GET_G1_MULTIPLE(&REALRNG,0,&W,pHTID!,&T)}
else {bls383.MPIN.GET_G1_MULTIPLE(&REALRNG,0,&W,pHID,&T)}
}
// Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC
rtn=bls383.MPIN.CLIENT_2(X,Y,&SEC);
if rtn != 0 {print("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
rtn=bls383.MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,&pE,&pF);
if rtn != 0 {print("FAILURE: SERVER_1 rtn: \(rtn)")}
}
if (rtn == bls383.MPIN.BAD_PIN)
{
print("Server says - Bad Pin. I don't know you. Feck off.\n");
if (PINERROR)
{
let err=bls383.MPIN.KANGAROO(pE,pF);
if err != 0 {print("(Client PIN is out by \(err))\n")}
}
return;
}
else {print("Server says - PIN is good! You really are "+IDstr)}
if (FULL)
{
var H=bls383.MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
bls383.MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,&CK);
print("Client Key = 0x",terminator: ""); printBinary(CK)
H=bls383.MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
bls383.MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID!,pxCID,&SK);
print("Server Key = 0x",terminator: ""); printBinary(SK)
}
rng=REALRNG!
}
public func TestMPIN_bls24(_ rng: inout RAND)
{
let PERMITS=true
let PINERROR=true
let FULL=true
let SINGLE_PASS=true
let EGS=bls24.MPIN192.EFS
let EFS=bls24.MPIN192.EGS
let G1S=2*EFS+1 // Group 1 Size
let G2S=8*EFS; // Group 2 Size
let EAS=bls24.ECP.AESKEY
let sha=bls24.ECP.HASH_TYPE
var S=[UInt8](repeating: 0,count: EGS)
var SST=[UInt8](repeating: 0,count: G2S)
var TOKEN=[UInt8](repeating: 0,count: G1S)
var PERMIT=[UInt8](repeating: 0,count: G1S)
var SEC=[UInt8](repeating: 0,count: G1S)
var xID=[UInt8](repeating: 0,count: G1S)
var xCID=[UInt8](repeating: 0,count: G1S)
var X=[UInt8](repeating: 0,count: EGS)
var Y=[UInt8](repeating: 0,count: EGS)
var E=[UInt8](repeating: 0,count: 24*EFS)
var F=[UInt8](repeating: 0,count: 24*EFS)
var HID=[UInt8](repeating: 0,count: G1S)
var HTID=[UInt8](repeating: 0,count: G1S)
var G1=[UInt8](repeating: 0,count: 24*EFS)
var G2=[UInt8](repeating: 0,count: 24*EFS)
var R=[UInt8](repeating: 0,count: EGS)
var Z=[UInt8](repeating: 0,count: G1S)
var W=[UInt8](repeating: 0,count: EGS)
var T=[UInt8](repeating: 0,count: G1S)
var CK=[UInt8](repeating: 0,count: EAS)
var SK=[UInt8](repeating: 0,count: EAS)
var HSID=[UInt8]()
// Trusted Authority set-up
MPIN192.RANDOM_GENERATE(&rng,&S)
print("\nMPIN Master Secret s: 0x",terminator: ""); printBinary(S)
// Create Client Identity
let IDstr = "testUser@miracl.com"
let CLIENT_ID=[UInt8](IDstr.utf8)
var HCID=MPIN192.HASH_ID(sha,CLIENT_ID) // Either Client or TA calculates Hash(ID) - you decide!
print("Client ID= "); printBinary(CLIENT_ID)
// Client and Server are issued secrets by DTA
MPIN192.GET_SERVER_SECRET(S,&SST);
print("Server Secret SS: 0x",terminator: ""); printBinary(SST);
MPIN192.GET_CLIENT_SECRET(&S,HCID,&TOKEN);
print("Client Secret CS: 0x",terminator: ""); printBinary(TOKEN);
// Client extracts PIN from secret to create Token
var pin:Int32=1234
print("Client extracts PIN= \(pin)")
var rtn=MPIN192.EXTRACT_PIN(sha,CLIENT_ID,pin,&TOKEN)
if rtn != 0 {print("FAILURE: EXTRACT_PIN rtn: \(rtn)")}
print("Client Token TK: 0x",terminator: ""); printBinary(TOKEN);
if FULL
{
MPIN192.PRECOMPUTE(TOKEN,HCID,&G1,&G2);
}
var date:Int32=0
if (PERMITS)
{
date=MPIN192.today()
// Client gets "Time Token" permit from DTA
MPIN192.GET_CLIENT_PERMIT(sha,date,S,HCID,&PERMIT)
print("Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
// This encoding makes Time permit look random - Elligator squared
MPIN192.ENCODING(&rng,&PERMIT);
print("Encoded Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
MPIN192.DECODING(&PERMIT)
print("Decoded Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
}
// ***** NOW ENTER PIN *******
pin=1234
// **************************
// Set date=0 and PERMIT=null if time permits not in use
//Client First pass: Inputs CLIENT_ID, optional rng, pin, TOKEN and PERMIT. Output xID =x .H(CLIENT_ID) and re-combined secret SEC
//If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H(date|H(CLIENT_ID)))
//Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
//IMPORTANT: To save space and time..
//If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
//If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
//If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.
var pxID:[UInt8]?=xID
var pxCID:[UInt8]?=xCID
var pHID:[UInt8]=HID
var pHTID:[UInt8]?=HTID
var pE:[UInt8]?=E
var pF:[UInt8]?=F
var pPERMIT:[UInt8]?=PERMIT
var REALRNG : RAND? = rng
if date != 0
{
if (!PINERROR)
{
pxID=nil; // problem here - either comment out here or dont use with ! later on
// pHID=nil;
}
}
else
{
pPERMIT=nil;
pxCID=nil;
pHTID=nil;
}
if (!PINERROR)
{
pE=nil;
pF=nil;
}
if (SINGLE_PASS)
{
print("MPIN Single Pass")
let timeValue = MPIN192.GET_TIME()
rtn=MPIN192.CLIENT(sha,date,CLIENT_ID,&REALRNG,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT,timeValue,&Y)
if rtn != 0 {print("FAILURE: CLIENT rtn: \(rtn)")}
if (FULL)
{
HCID=MPIN192.HASH_ID(sha,CLIENT_ID);
MPIN192.GET_G1_MULTIPLE(&REALRNG,1,&R,HCID,&Z); // Also Send Z=r.ID to Server, remember random r
}
rtn=MPIN192.SERVER(sha,date,&pHID,&pHTID,&Y,SST,pxID,pxCID!,SEC,&pE,&pF,CLIENT_ID,timeValue)
if rtn != 0 {print("FAILURE: SERVER rtn: \(rtn)")}
if (FULL)
{ // Also send T=w.ID to client, remember random w
HSID=MPIN192.HASH_ID(sha,CLIENT_ID);
if date != 0 {MPIN192.GET_G1_MULTIPLE(&REALRNG,0,&W,pHTID!,&T)}
else {MPIN192.GET_G1_MULTIPLE(&REALRNG,0,&W,pHID,&T)}
}
}
else
{
print("MPIN Multi Pass");
// Send U=x.ID to server, and recreate secret from token and pin
rtn=MPIN192.CLIENT_1(sha,date,CLIENT_ID,&REALRNG,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT)
if rtn != 0 {print("FAILURE: CLIENT_1 rtn: \(rtn)")}
if (FULL)
{
HCID=MPIN192.HASH_ID(sha,CLIENT_ID);
MPIN192.GET_G1_MULTIPLE(&REALRNG,1,&R,HCID,&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.
MPIN192.SERVER_1(sha,date,CLIENT_ID,&pHID,&pHTID);
// Server generates Random number Y and sends it to Client
MPIN192.RANDOM_GENERATE(&REALRNG!,&Y);
if (FULL)
{ // Also send T=w.ID to client, remember random w
HSID=MPIN192.HASH_ID(sha,CLIENT_ID);
if date != 0 {MPIN192.GET_G1_MULTIPLE(&REALRNG,0,&W,pHTID!,&T)}
else {MPIN192.GET_G1_MULTIPLE(&REALRNG,0,&W,pHID,&T)}
}
// Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC
rtn=MPIN192.CLIENT_2(X,Y,&SEC);
if rtn != 0 {print("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
rtn=MPIN192.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,&pE,&pF);
if rtn != 0 {print("FAILURE: SERVER_1 rtn: \(rtn)")}
}
if (rtn == MPIN192.BAD_PIN)
{
print("Server says - Bad Pin. I don't know you. Feck off.\n");
if (PINERROR)
{
let err=MPIN192.KANGAROO(pE,pF);
if err != 0 {print("(Client PIN is out by \(err))\n")}
}
return;
}
else {print("Server says - PIN is good! You really are "+IDstr)}
if (FULL)
{
var H=MPIN192.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
MPIN192.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,&CK);
print("Client Key = 0x",terminator: ""); printBinary(CK)
H=MPIN192.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
MPIN192.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID!,pxCID,&SK);
print("Server Key = 0x",terminator: ""); printBinary(SK)
}
rng=REALRNG!
}
public func TestMPIN_bls48(_ rng: inout RAND)
{
let PERMITS=true
let PINERROR=true
let FULL=true
let SINGLE_PASS=true
let EGS=bls48.MPIN256.EFS
let EFS=bls48.MPIN256.EGS
let G1S=2*EFS+1 // Group 1 Size
let G2S=16*EFS; // Group 2 Size
let EAS=bls48.ECP.AESKEY
let sha=bls48.ECP.HASH_TYPE
var S=[UInt8](repeating: 0,count: EGS)
var SST=[UInt8](repeating: 0,count: G2S)
var TOKEN=[UInt8](repeating: 0,count: G1S)
var PERMIT=[UInt8](repeating: 0,count: G1S)
var SEC=[UInt8](repeating: 0,count: G1S)
var xID=[UInt8](repeating: 0,count: G1S)
var xCID=[UInt8](repeating: 0,count: G1S)
var X=[UInt8](repeating: 0,count: EGS)
var Y=[UInt8](repeating: 0,count: EGS)
var E=[UInt8](repeating: 0,count: 48*EFS)
var F=[UInt8](repeating: 0,count: 48*EFS)
var HID=[UInt8](repeating: 0,count: G1S)
var HTID=[UInt8](repeating: 0,count: G1S)
var G1=[UInt8](repeating: 0,count: 48*EFS)
var G2=[UInt8](repeating: 0,count: 48*EFS)
var R=[UInt8](repeating: 0,count: EGS)
var Z=[UInt8](repeating: 0,count: G1S)
var W=[UInt8](repeating: 0,count: EGS)
var T=[UInt8](repeating: 0,count: G1S)
var CK=[UInt8](repeating: 0,count: EAS)
var SK=[UInt8](repeating: 0,count: EAS)
var HSID=[UInt8]()
// Trusted Authority set-up
MPIN256.RANDOM_GENERATE(&rng,&S)
print("\nMPIN Master Secret s: 0x",terminator: ""); printBinary(S)
// Create Client Identity
let IDstr = "testUser@miracl.com"
let CLIENT_ID=[UInt8](IDstr.utf8)
var HCID=MPIN256.HASH_ID(sha,CLIENT_ID) // Either Client or TA calculates Hash(ID) - you decide!
print("Client ID= "); printBinary(CLIENT_ID)
// Client and Server are issued secrets by DTA
MPIN256.GET_SERVER_SECRET(S,&SST);
print("Server Secret SS: 0x",terminator: ""); printBinary(SST);
MPIN256.GET_CLIENT_SECRET(&S,HCID,&TOKEN);
print("Client Secret CS: 0x",terminator: ""); printBinary(TOKEN);
// Client extracts PIN from secret to create Token
var pin:Int32=1234
print("Client extracts PIN= \(pin)")
var rtn=MPIN256.EXTRACT_PIN(sha,CLIENT_ID,pin,&TOKEN)
if rtn != 0 {print("FAILURE: EXTRACT_PIN rtn: \(rtn)")}
print("Client Token TK: 0x",terminator: ""); printBinary(TOKEN);
if FULL
{
MPIN256.PRECOMPUTE(TOKEN,HCID,&G1,&G2);
}
var date:Int32=0
if (PERMITS)
{
date=MPIN256.today()
// Client gets "Time Token" permit from DTA
MPIN256.GET_CLIENT_PERMIT(sha,date,S,HCID,&PERMIT)
print("Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
// This encoding makes Time permit look random - Elligator squared
MPIN256.ENCODING(&rng,&PERMIT);
print("Encoded Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
MPIN256.DECODING(&PERMIT)
print("Decoded Time Permit TP: 0x",terminator: ""); printBinary(PERMIT)
}
// ***** NOW ENTER PIN *******
pin=1234
// **************************
// Set date=0 and PERMIT=null if time permits not in use
//Client First pass: Inputs CLIENT_ID, optional rng, pin, TOKEN and PERMIT. Output xID =x .H(CLIENT_ID) and re-combined secret SEC
//If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H(date|H(CLIENT_ID)))
//Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
//IMPORTANT: To save space and time..
//If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
//If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
//If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.
var pxID:[UInt8]?=xID
var pxCID:[UInt8]?=xCID
var pHID:[UInt8]=HID
var pHTID:[UInt8]?=HTID
var pE:[UInt8]?=E
var pF:[UInt8]?=F
var pPERMIT:[UInt8]?=PERMIT
var REALRNG : RAND? = rng
if date != 0
{
if (!PINERROR)
{
pxID=nil; // problem here - either comment out here or dont use with ! later on
// pHID=nil;
}
}
else
{
pPERMIT=nil;
pxCID=nil;
pHTID=nil;
}
if (!PINERROR)
{
pE=nil;
pF=nil;
}
if (SINGLE_PASS)
{
print("MPIN Single Pass")
let timeValue = MPIN256.GET_TIME()
rtn=MPIN256.CLIENT(sha,date,CLIENT_ID,&REALRNG,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT,timeValue,&Y)
if rtn != 0 {print("FAILURE: CLIENT rtn: \(rtn)")}
if (FULL)
{
HCID=MPIN256.HASH_ID(sha,CLIENT_ID);
MPIN256.GET_G1_MULTIPLE(&REALRNG,1,&R,HCID,&Z); // Also Send Z=r.ID to Server, remember random r
}
rtn=MPIN256.SERVER(sha,date,&pHID,&pHTID,&Y,SST,pxID,pxCID!,SEC,&pE,&pF,CLIENT_ID,timeValue)
if rtn != 0 {print("FAILURE: SERVER rtn: \(rtn)")}
if (FULL)
{ // Also send T=w.ID to client, remember random w
HSID=MPIN256.HASH_ID(sha,CLIENT_ID);
if date != 0 {MPIN256.GET_G1_MULTIPLE(&REALRNG,0,&W,pHTID!,&T)}
else {MPIN256.GET_G1_MULTIPLE(&REALRNG,0,&W,pHID,&T)}
}
}
else
{
print("MPIN Multi Pass");
// Send U=x.ID to server, and recreate secret from token and pin
rtn=MPIN256.CLIENT_1(sha,date,CLIENT_ID,&REALRNG,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT)
if rtn != 0 {print("FAILURE: CLIENT_1 rtn: \(rtn)")}
if (FULL)
{
HCID=MPIN256.HASH_ID(sha,CLIENT_ID);
MPIN256.GET_G1_MULTIPLE(&REALRNG,1,&R,HCID,&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.
MPIN256.SERVER_1(sha,date,CLIENT_ID,&pHID,&pHTID);
// Server generates Random number Y and sends it to Client
MPIN256.RANDOM_GENERATE(&REALRNG!,&Y);
if (FULL)
{ // Also send T=w.ID to client, remember random w
HSID=MPIN256.HASH_ID(sha,CLIENT_ID);
if date != 0 {MPIN256.GET_G1_MULTIPLE(&REALRNG,0,&W,pHTID!,&T)}
else {MPIN256.GET_G1_MULTIPLE(&REALRNG,0,&W,pHID,&T)}
}
// Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC
rtn=MPIN256.CLIENT_2(X,Y,&SEC);
if rtn != 0 {print("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
rtn=MPIN256.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,&pE,&pF);
if rtn != 0 {print("FAILURE: SERVER_1 rtn: \(rtn)")}
}
if (rtn == MPIN256.BAD_PIN)
{
print("Server says - Bad Pin. I don't know you. Feck off.\n");
if (PINERROR)
{
let err=MPIN256.KANGAROO(pE,pF);
if err != 0 {print("(Client PIN is out by \(err))\n")}
}
return;
}
else {print("Server says - PIN is good! You really are "+IDstr)}
if (FULL)
{
var H=MPIN256.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
MPIN256.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,&CK);
print("Client Key = 0x",terminator: ""); printBinary(CK)
H=MPIN256.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
MPIN256.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID!,pxCID,&SK);
print("Server Key = 0x",terminator: ""); printBinary(SK)
}
rng=REALRNG!
}
var RAW=[UInt8](repeating: 0,count: 100)
var rng=RAND()
rng.clean();
for i in 0 ..< 100 {RAW[i]=UInt8(i&0xff)}
rng.seed(100,RAW)
TestECDH_ed25519(&rng)
TestECDH_nist256(&rng)
TestECDH_goldilocks(&rng)
TestRSA_2048(&rng)
TestMPIN_bn254(&rng)
TestMPIN_bls383(&rng)
TestMPIN_bls24(&rng)
TestMPIN_bls48(&rng)