blob: 60b0b1196f597e78e04a380846fe7a03a7cf5cb3 [file] [log] [blame]
#!/usr/bin/env python
"""
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.
"""
"""
Generates a set of test vectors for testing the JavaScript. The output file is
testVectors.json. This script uses the AMCL library.
usage: genVectorsOnePass.py [success authentication] [failed authentication] [epoch days test] [DEBUG}
"""
import sys
import json
import os
import datetime
import json
import random
import mpin
if len(sys.argv) == 5:
nPos = int(sys.argv[1])
nNeg = int(sys.argv[2])
nEpoch = int(sys.argv[3])
if (sys.argv[4] == "DEBUG"):
DEBUG = True
elif len(sys.argv) == 4:
nPos = int(sys.argv[1])
nNeg = int(sys.argv[2])
nEpoch = int(sys.argv[3])
DEBUG = False
else:
print "Usage: genVectorsOnePass.py [success authentication] [failed authentication] [epoch days test] [DEBUG]"
sys.exit(1)
print "Generate nPos = %s nNeg = %s nEpoch = %s" % (nPos, nNeg, nEpoch)
# Seed
seed = os.urandom(32)
# Assign a seed value
RAW = mpin.ffi.new("octet*")
RAWval = mpin.ffi.new("char [%s]" % len(seed), seed)
RAW[0].val = RAWval
RAW[0].len = len(seed)
RAW[0].max = len(seed)
# random number generator
RNG = mpin.ffi.new("csprng*")
mpin.libmpin.CREATE_CSPRNG(RNG,RAW)
# Master Secret Shares
MS1 = mpin.ffi.new("octet*")
MS1val = mpin.ffi.new("char []", mpin.PGS)
MS1[0].val = MS1val
MS1[0].max = mpin.PGS
MS1[0].len = mpin.PGS
MS2 = mpin.ffi.new("octet*")
MS2val = mpin.ffi.new("char []", mpin.PGS)
MS2[0].val = MS2val
MS2[0].max = mpin.PGS
MS2[0].len = mpin.PGS
# Hash value of MPIN_ID
HASH_MPIN_ID = mpin.ffi.new("octet*")
HASH_MPIN_IDval = mpin.ffi.new("char []", mpin.HASH_BYTES)
HASH_MPIN_ID[0].val = HASH_MPIN_IDval
HASH_MPIN_ID[0].max = mpin.HASH_BYTES
HASH_MPIN_ID[0].len = mpin.HASH_BYTES
# Server secret and shares
SS1 = mpin.ffi.new("octet*")
SS1val = mpin.ffi.new("char []", mpin.G2)
SS1[0].val = SS1val
SS1[0].max = mpin.G2
SS1[0].len = mpin.G2
SS2 = mpin.ffi.new("octet*")
SS2val = mpin.ffi.new("char []", mpin.G2)
SS2[0].val = SS2val
SS2[0].max = mpin.G2
SS2[0].len = mpin.G2
SERVER_SECRET = mpin.ffi.new("octet*")
SERVER_SECRETval = mpin.ffi.new("char []", mpin.G2)
SERVER_SECRET[0].val = SERVER_SECRETval
SERVER_SECRET[0].max = mpin.G2
SERVER_SECRET[0].len = mpin.G2
# Time Permit and shares
TP1 = mpin.ffi.new("octet*")
TP1val = mpin.ffi.new("char []", mpin.G1)
TP1[0].val = TP1val
TP1[0].max = mpin.G1
TP1[0].len = mpin.G1
TP2 = mpin.ffi.new("octet*")
TP2val = mpin.ffi.new("char []", mpin.G1)
TP2[0].val = TP2val
TP2[0].max = mpin.G1
TP2[0].len = mpin.G1
TIME_PERMIT = mpin.ffi.new("octet*")
TIME_PERMITval = mpin.ffi.new("char []", mpin.G1)
TIME_PERMIT[0].val = TIME_PERMITval
TIME_PERMIT[0].max = mpin.G1
TIME_PERMIT[0].len = mpin.G1
# Client Secret
CS1 = mpin.ffi.new("octet*")
CS1val = mpin.ffi.new("char []", mpin.G1)
CS1[0].val = CS1val
CS1[0].max = mpin.G1
CS1[0].len = mpin.G1
CS2 = mpin.ffi.new("octet*")
CS2val = mpin.ffi.new("char []", mpin.G1)
CS2[0].val = CS2val
CS2[0].max = mpin.G1
CS2[0].len = mpin.G1
SEC = mpin.ffi.new("octet*")
SECval = mpin.ffi.new("char []", mpin.G1)
SEC[0].val = SECval
SEC[0].max = mpin.G1
SEC[0].len = mpin.G1
# Token stored on computer
TOKEN = mpin.ffi.new("octet*")
TOKEN[0].val = mpin.ffi.new("char []", mpin.G1)
TOKEN[0].max = mpin.G1
TOKEN[0].len = mpin.G1
UT = mpin.ffi.new("octet*")
UTval = mpin.ffi.new("char []", mpin.G1)
UT[0].val = UTval
UT[0].max = mpin.G1
UT[0].len = mpin.G1
U = mpin.ffi.new("octet*")
Uval = mpin.ffi.new("char []", mpin.G1)
U[0].val = Uval
U[0].max = mpin.G1
U[0].len = mpin.G1
X = mpin.ffi.new("octet*")
Xval = mpin.ffi.new("char []", mpin.PGS)
X[0].val = Xval
X[0].max = mpin.PGS
X[0].len = mpin.PGS
Y1 = mpin.ffi.new("octet*")
Y1val = mpin.ffi.new("char []", mpin.PGS)
Y1[0].val = Y1val
Y1[0].max = mpin.PGS
Y1[0].len = mpin.PGS
Y2 = mpin.ffi.new("octet*")
Y2val = mpin.ffi.new("char []", mpin.PGS)
Y2[0].val = Y2val
Y2[0].max = mpin.PGS
Y2[0].len = mpin.PGS
lenEF = 12 * mpin.PFS
E = mpin.ffi.new("octet*")
Eval = mpin.ffi.new("char []", lenEF)
E[0].val = Eval
E[0].max = lenEF
E[0].len = lenEF
F = mpin.ffi.new("octet*")
Fval = mpin.ffi.new("char []", lenEF)
F[0].val = Fval
F[0].max = lenEF
F[0].len = lenEF
# H(ID)
HID = mpin.ffi.new("octet*")
HIDval = mpin.ffi.new("char []", mpin.G1)
HID[0].val = HIDval
HID[0].max = mpin.G1
HID[0].len = mpin.G1
# H(T|H(ID))
HTID = mpin.ffi.new("octet*")
HTIDval = mpin.ffi.new("char []", mpin.G1)
HTID[0].val = HTIDval
HTID[0].max = mpin.G1
HTID[0].len = mpin.G1
def genVector(mpin_id, date, PIN1, PIN2, test_no):
"""Generate a single test vector
Use mpin_id and date to generate a
valid Client Secret and Time Permit
Args::
mpin_id: The M-Pin ID
date: The date of M-Pin Authentication
PIN1: PIN for generating token
PIN2: PIN for authenticating
test_no: Test vector identifier
Returns:
vector: A test vector
Raises:
Exception
"""
vector = {}
if DEBUG:
print test_no
vector['test_no'] = test_no
vector['mpin_id'] = mpin_id
# Generate master secret shares
rtn = mpin.libmpin.MPIN_RANDOM_GENERATE(RNG,MS1)
assert rtn is 0, "MS1"
vector['MS1'] = mpin.toHex(MS1)
rtn = mpin.libmpin.MPIN_RANDOM_GENERATE(RNG,MS2)
assert rtn is 0, "MS2"
vector['MS2'] = mpin.toHex(MS2)
# Generate server secret shares
rtn = mpin.libmpin.MPIN_GET_SERVER_SECRET(MS1,SS1)
assert rtn is 0, "SS1"
vector['SS1'] = mpin.toHex(SS1)
rtn = mpin.libmpin.MPIN_GET_SERVER_SECRET(MS2,SS2)
assert rtn is 0, "SS2"
vector['SS2'] = mpin.toHex(SS2)
# Combine server secret shares
rtn = mpin.libmpin.MPIN_RECOMBINE_G2(SS1, SS2, SERVER_SECRET)
assert rtn is 0, "SERVER_SECRET"
vector['SERVER_SECRET'] = mpin.toHex(SERVER_SECRET)
# Identity
MPIN_ID = mpin.ffi.new("octet*")
MPIN_IDval = mpin.ffi.new("char [%s]" % len(mpin_id), mpin_id)
MPIN_ID[0].val = MPIN_IDval
MPIN_ID[0].max = len(mpin_id)
MPIN_ID[0].len = len(mpin_id)
vector['MPIN_ID_HEX'] = mpin.toHex(MPIN_ID)
# Hash MPIN_ID
mpin.libmpin.MPIN_HASH_ID(MPIN_ID, HASH_MPIN_ID)
vector['HASH_MPIN_ID_HEX'] = mpin.toHex(HASH_MPIN_ID)
# Generate client secret shares
rtn = mpin.libmpin.MPIN_GET_CLIENT_SECRET(MS1,HASH_MPIN_ID,CS1)
assert rtn is 0, "CS1"
vector['CS1'] = mpin.toHex(CS1)
rtn = mpin.libmpin.MPIN_GET_CLIENT_SECRET(MS2,HASH_MPIN_ID,CS2)
assert rtn is 0, "CS2"
vector['CS2'] = mpin.toHex(CS2)
# Combine client secret shares : TOKEN is the full client secret
rtn = mpin.libmpin.MPIN_RECOMBINE_G1(CS1, CS2, TOKEN)
assert rtn is 0, "CS1+CS2"
vector['CLIENT_SECRET'] = mpin.toHex(TOKEN)
# Generate Time Permit shares
rtn = mpin.libmpin.MPIN_GET_CLIENT_PERMIT(date,MS1,HASH_MPIN_ID,TP1)
assert rtn is 0, "TP1"
vector['TP1'] = mpin.toHex(TP1)
vector['DATE'] = date
rtn = mpin.libmpin.MPIN_GET_CLIENT_PERMIT(date,MS2,HASH_MPIN_ID,TP2)
assert rtn is 0, "TP2"
vector['TP2'] = mpin.toHex(TP2)
# Combine Time Permit shares
rtn = mpin.libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT)
assert rtn is 0, "TP1+TP2"
vector['TIME_PERMIT'] = mpin.toHex(TIME_PERMIT)
# Client extracts PIN from secret to create Token
rtn = mpin.libmpin.MPIN_EXTRACT_PIN(MPIN_ID, PIN1, TOKEN)
assert rtn is 0, "TOKEN"
vector['PIN1'] = PIN1
vector['TOKEN'] = mpin.toHex(TOKEN)
# Client pass
TimeValue = mpin.libmpin.MPIN_GET_TIME()
rtn = mpin.libmpin.MPIN_CLIENT(date, MPIN_ID, RNG, X, PIN2, TOKEN, SEC, U, UT, TIME_PERMIT, TimeValue, Y1)
assert rtn is 0, "MPIN_CLIENT"
vector['PIN2'] = PIN2
vector['X'] = mpin.toHex(X)
vector['U'] = mpin.toHex(U)
vector['UT'] = mpin.toHex(UT)
vector['SEC'] = mpin.toHex(SEC)
vector['TimeValue'] = TimeValue
vector['Y'] = mpin.toHex(Y1)
# Server pass
rtn = mpin.libmpin.MPIN_SERVER(date, HID, HTID, Y2, SERVER_SECRET, U, UT, SEC, E, F, MPIN_ID, TimeValue)
assert mpin.toHex(Y1) == mpin.toHex(Y2), "Y equal"
vector['SERVER_OUTPUT'] = rtn
if PIN1 == PIN2:
assert rtn == 0, "successful authentication"
else:
assert rtn == -19, "failed authentication"
return vector
if __name__ == '__main__':
# List of test vectors
vectors = []
# Today's date in epoch days
date = mpin.libmpin.today()
# Generate test vectors for successful authentication
for i in range(0,nPos):
# Assign the User an ID
name = os.urandom(16).encode("hex")
userID = name + "@miracl.com"
issued = datetime.datetime.utcnow().isoformat("T").split(".")[0] + "Z"
# userID = "testUser@miracl.com"
# issued = "2014-01-30T19:17:48Z"
mobile = 1
salt = os.urandom(16).encode("hex")
# Form MPin ID
endUserdata = {
"issued": issued,
"userID": userID,
"mobile": mobile,
"salt": salt
}
mpin_id = json.dumps(endUserdata)
PIN1 = random.randint(0,10000)
PIN2 = PIN1
vector = genVector(mpin_id, date, PIN1, PIN2, i)
vectors.append(vector)
# print i
# Generate test vectors for failed authentication
for i in range(0,nNeg):
# Assign the User an ID
name = os.urandom(16).encode("hex")
userID = name + "@miracl.com"
issued = datetime.datetime.utcnow().isoformat("T").split(".")[0] + "Z"
# userID = "testUser@miracl.com"
# issued = "2014-01-30T19:17:48Z"
mobile = 1
salt = os.urandom(8).encode("hex")
# Form MPin ID
endUserdata = {
"issued": issued,
"userID": userID,
"mobile": mobile,
"salt": salt
}
mpin_id = json.dumps(endUserdata)
PIN1 = random.randint(0,10000)
PIN2 = PIN1 - 1
test_no = nPos + i
vector = genVector(mpin_id, date, PIN1, PIN2, test_no)
vectors.append(vector)
# print i
# Generate test vectors for days in future
# Assign the User an ID
name = os.urandom(16).encode("hex")
userID = name + "@miracl.com"
issued = datetime.datetime.utcnow().isoformat("T").split(".")[0] + "Z"
# userID = "testUser@miracl.com"
# issued = "2014-01-30T19:17:48Z"
mobile = 1
salt = os.urandom(8).encode("hex")
# Form MPin ID
endUserdata = {
"issued": issued,
"userID": userID,
"mobile": mobile,
"salt": salt
}
mpin_id = json.dumps(endUserdata)
PIN1 = random.randint(0,10000)
PIN2 = PIN1
for i in range(0,nEpoch):
test_no = nPos + nNeg + i
vector = genVector(mpin_id, date, PIN1, PIN2, test_no)
vectors.append(vector)
date = date + 1
# Write to JSON file
json.dump(vectors, open("testVectorsOnePass.json", "w"))