def test_5(self): """test_5 Make sure all client secret are unique""" # random number generator RNG = ffi.new("csprng*") libmpin.MPIN_CREATE_CSPRNG(RNG, self.RAW) # Generate master secret share rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS1) self.assertEqual(rtn, 0) s = set() match = 0 for i in range(1, 1000): rand_val = os.urandom(32) HASH_MPIN_ID = ffi.new("octet*") HASH_MPIN_IDval = ffi.new("char [%s]" % HASH_BYTES, rand_val) HASH_MPIN_ID[0].val = HASH_MPIN_IDval HASH_MPIN_ID[0].max = HASH_BYTES HASH_MPIN_ID[0].len = HASH_BYTES # Generate client secret shares rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, HASH_MPIN_ID, CS1) self.assertEqual(rtn, 0) cs1Hex = toHex(CS1) if cs1Hex in s: match = 1 self.assertEqual(match, 0) s.add(cs1Hex)
def test_3(self): """test_3 Good PIN and bad token""" PIN = 1234 # random number generator RNG = ffi.new("csprng*") libmpin.CREATE_CSPRNG(RNG, self.RAW) # Client first pass rtn = libmpin.MPIN_CLIENT_1(self.date, self.MPIN_ID, RNG, X, PIN, self.TOKEN, SEC, U, UT, self.TIMEPERMIT) self.assertEqual(rtn, 0) # Server calculates H(ID) and H(T|H(ID)) libmpin.MPIN_SERVER_1(self.date, self.MPIN_ID, HID, HTID) # Server generates Random number Y and sends it to Client rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, Y) self.assertEqual(rtn, 0) # Client second pass rtn = libmpin.MPIN_CLIENT_2(X, Y, SEC) self.assertEqual(rtn, 0) # Server second pass # clientSecret aka V is equal to UT to model a bad token rtn = libmpin.MPIN_SERVER_2(self.date, HID, HTID, Y, self.SERVER_SECRET, U, UT, UT, E, F) self.assertEqual(rtn, -19)
def test_8(self): """test_8 Generation of secrets and time permits""" # random number generator RNG = ffi.new("csprng*") libmpin.CREATE_CSPRNG(RNG, self.RAW) # Generate Client master secret share for MIRACL and Customer rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS1) self.assertEqual(rtn, 0) self.assertEqual(self.ms1Hex, toHex(MS1)) rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS2) self.assertEqual(rtn, 0) self.assertEqual(self.ms2Hex, toHex(MS2)) # Generate server secret shares rtn = libmpin.MPIN_GET_SERVER_SECRET(MS1, SS1) self.assertEqual(rtn, 0) self.assertEqual(self.ss1Hex, toHex(SS1)) rtn = libmpin.MPIN_GET_SERVER_SECRET(MS2, SS2) self.assertEqual(rtn, 0) self.assertEqual(self.ss2Hex, toHex(SS2)) # Combine server secret shares rtn = libmpin.MPIN_RECOMBINE_G2(SS1, SS2, SERVER_SECRET) self.assertEqual(rtn, 0) self.assertEqual(self.serverSecretHex, toHex(SERVER_SECRET)) # Generate client secret shares rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, self.HASH_MPIN_ID, CS1) self.assertEqual(rtn, 0) self.assertEqual(self.cs1Hex, toHex(CS1)) rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS2, self.HASH_MPIN_ID, CS2) self.assertEqual(rtn, 0) self.assertEqual(self.cs2Hex, toHex(CS2)) # Combine client secret shares : TOKEN is the full client secret rtn = libmpin.MPIN_RECOMBINE_G1(CS1, CS2, TOKEN) self.assertEqual(rtn, 0) self.assertEqual(self.clientSecretHex, toHex(TOKEN)) # Generate Time Permit shares rtn = libmpin.MPIN_GET_CLIENT_PERMIT(self.date, MS1, self.HASH_MPIN_ID, TP1) self.assertEqual(rtn, 0) self.assertEqual(self.tp1Hex, toHex(TP1)) rtn = libmpin.MPIN_GET_CLIENT_PERMIT(self.date, MS2, self.HASH_MPIN_ID, TP2) self.assertEqual(rtn, 0) self.assertEqual(self.tp2Hex, toHex(TP2)) # Combine Time Permit shares rtn = libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT) self.assertEqual(rtn, 0) self.assertEqual(self.timePermitHex, toHex(TIME_PERMIT)) # Client extracts PIN from secret to create Token PIN = 1234 rtn = libmpin.MPIN_EXTRACT_PIN(self.MPIN_ID, PIN, TOKEN) self.assertEqual(rtn, 0) self.assertEqual(self.tokenHex, toHex(TOKEN))
def test_4(self): """test_4 Test hash function""" HASH_MPIN_ID = ffi.new("octet*") HASH_MPIN_IDval = ffi.new("char []", HASH_BYTES) HASH_MPIN_ID[0].val = HASH_MPIN_IDval HASH_MPIN_ID[0].max = HASH_BYTES HASH_MPIN_ID[0].len = HASH_BYTES for i in range(1, 10000): bytesStr = os.urandom(128) hash_object2 = hashlib.sha256(bytesStr) digest = hash_object2.hexdigest() MPIN_ID = ffi.new("octet*") MPIN_IDval = ffi.new("char [%s]" % len(bytesStr), bytesStr) MPIN_ID[0].val = MPIN_IDval MPIN_ID[0].max = len(bytesStr) MPIN_ID[0].len = len(bytesStr) libmpin.MPIN_HASH_ID(MPIN_ID, HASH_MPIN_ID) self.assertEqual(digest, toHex(HASH_MPIN_ID))
def setUp(self): # Form MPin ID endUserData = { "issued": "2013-10-19T06:12:28Z", "userID": "*****@*****.**", "mobile": 1, "salt": "e985da112a378c222cfc2f7226097b0c" } mpin_id = json.dumps(endUserData) self.MPIN_ID = ffi.new("octet*") self.MPIN_IDval = ffi.new("char [%s]" % len(mpin_id), mpin_id) self.MPIN_ID[0].val = self.MPIN_IDval self.MPIN_ID[0].max = len(mpin_id) self.MPIN_ID[0].len = len(mpin_id) # Hash value of MPIN_ID self.HASH_MPIN_ID = ffi.new("octet*") self.HASH_MPIN_IDval = ffi.new("char []", HASH_BYTES) self.HASH_MPIN_ID[0].val = self.HASH_MPIN_IDval self.HASH_MPIN_ID[0].max = HASH_BYTES self.HASH_MPIN_ID[0].len = HASH_BYTES libmpin.MPIN_HASH_ID(self.MPIN_ID, self.HASH_MPIN_ID) # Assign a seed value seedHex = "3ade3d4a5c698e8910bf92f25d97ceeb7c25ed838901a5cb5db2cf25434c1fe76c7f79b7af2e5e1e4988e4294dbd9bd9fa3960197fb7aec373609fb890d74b16a4b14b2ae7e23b75f15d36c21791272372863c4f8af39980283ae69a79cf4e48e908f9e0" self.seed = seedHex.decode("hex") self.RAW = ffi.new("octet*") self.RAWval = ffi.new("char [%s]" % len(self.seed), self.seed) self.RAW[0].val = self.RAWval self.RAW[0].len = len(self.seed) self.RAW[0].max = len(self.seed) self.date = 16238
def test_10(self): """test_10 Test mss starting with 00 are handled correctly""" for i in range(1, 1000): # Assign a seed value seed = os.urandom(32) RAW = ffi.new("octet*") RAWval = 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 = ffi.new("csprng*") libmpin.CREATE_CSPRNG(RNG, RAW) # Generate master secret - ms1 rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS1) self.assertEqual(rtn, 0) ms1_hex = toHex(MS1) ms1 = ms1_hex.decode("hex") # Assign ms1 to ms2 if it starts with "00" if ms1_hex.startswith('00'): MS2 = ffi.new("octet*") MS2val = ffi.new("char [%s]" % PGS, ms1) MS2[0].val = MS2val MS2[0].max = PGS MS2[0].len = PGS # Generate client secret shares rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, self.HASH_MPIN_ID, CS1) self.assertEqual(rtn, 0) cs1_hex = toHex(CS1) rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS2, self.HASH_MPIN_ID, CS2) self.assertEqual(rtn, 0) cs2_hex = toHex(CS2) self.assertEqual(cs1_hex, cs2_hex)
def test_7(self): """test_7 Make sure all random values are random i.e. they should collide""" # random number generator RNG = ffi.new("csprng*") libmpin.MPIN_CREATE_CSPRNG(RNG, self.RAW) # Generate 100 byte random number RANDOMlen = 3 RANDOM = ffi.new("octet*") RANDOMval = ffi.new("char []", RANDOMlen) RANDOM[0].val = RANDOMval RANDOM[0].max = RANDOMlen RANDOM[0].len = RANDOMlen s = set() match = 0 for i in range(1, 10000): libmpin.generateRandom(RNG, RANDOM) random = toHex(RANDOM) if random in s: # print i match = 1 s.add(random) self.assertEqual(match, 1)
def test_6(self): """test_6 Make sure all one time passwords are random i.e. they should collide""" # random number generator RNG = ffi.new("csprng*") libmpin.MPIN_CREATE_CSPRNG(RNG, self.RAW) s = set() match = 0 for i in range(1, 10000): OTP = libmpin.generateOTP(RNG) if OTP in s: # print i match = 1 s.add(OTP) self.assertEqual(match, 1)
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. """ import unittest import json from mpin import ffi, G1, G2, HASH_BYTES, libmpin, PFS, PGS, toHex # Master Secret Shares MS1 = ffi.new("octet*") MS1val = ffi.new("char []", PGS) MS1[0].val = MS1val MS1[0].max = PGS MS1[0].len = PGS MS2 = ffi.new("octet*") MS2val = ffi.new("char []", PGS) MS2[0].val = MS2val MS2[0].max = PGS MS2[0].len = PGS # Client secret and shares CS1 = ffi.new("octet*") CS1val = ffi.new("char []", G1) CS1[0].val = CS1val
def test_10(self): """test_10 AES-GCM: Failed encryption and decryption by changing a header byte""" # Generate 16 byte key key_val = os.urandom(PAS) AES_KEY = ffi.new("octet*") AES_KEYval = ffi.new("char [%s]" % PAS, key_val) AES_KEY[0].val = AES_KEYval AES_KEY[0].max = PAS AES_KEY[0].len = PAS # Generate 12 byte IV iv_val = os.urandom(IVL) IV = ffi.new("octet*") IVval = ffi.new("char [%s]" % IVL, iv_val) IV[0].val = IVval IV[0].max = IVL IV[0].len = IVL # Generate a 32 byte random header header_val = os.urandom(32) HEADER = ffi.new("octet*") HEADERval = ffi.new("char [%s]" % len(header_val), header_val) HEADER[0].val = HEADERval HEADER[0].max = len(header_val) HEADER[0].len = len(header_val) # Plaintext input plaintext1 = "A test message" PLAINTEXT1 = ffi.new("octet*") PLAINTEXT1val = ffi.new("char [%s]" % len(plaintext1), plaintext1) PLAINTEXT1[0].val = PLAINTEXT1val PLAINTEXT1[0].max = len(plaintext1) PLAINTEXT1[0].len = len(plaintext1) # print "Input message: %s" % ffi.string(PLAINTEXT1[0].val, PLAINTEXT1[0].len) # Ciphertext CIPHERTEXT = ffi.new("octet*") CIPHERTEXTval = ffi.new("char []", len(plaintext1)) CIPHERTEXT[0].val = CIPHERTEXTval CIPHERTEXT[0].max = len(plaintext1) # 16 byte authentication tag TAG1 = ffi.new("octet*") TAG1val = ffi.new("char []", PAS) TAG1[0].val = TAG1val TAG1[0].max = PAS libmpin.MPIN_AES_GCM_ENCRYPT(AES_KEY, IV, HEADER, PLAINTEXT1, CIPHERTEXT, TAG1) # Plaintext output PLAINTEXT2 = ffi.new("octet*") PLAINTEXT2val = ffi.new("char []", CIPHERTEXT[0].len) PLAINTEXT2[0].val = PLAINTEXT2val PLAINTEXT2[0].max = CIPHERTEXT[0].len PLAINTEXT2[0].len = CIPHERTEXT[0].len # Change one byte of header HEADER[0].val[0] = "\xa5" # 16 byte authentication tag TAG2 = ffi.new("octet*") TAG2val = ffi.new("char []", PAS) TAG2[0].val = TAG2val TAG2[0].max = PAS libmpin.MPIN_AES_GCM_DECRYPT(AES_KEY, IV, HEADER, CIPHERTEXT, PLAINTEXT2, TAG2) self.assertNotEqual(toHex(TAG1), toHex(TAG2)) self.assertEqual(toHex(PLAINTEXT1), toHex(PLAINTEXT2))
DEBUG = False nIter = 1000 if __name__ == "__main__": # Print hex values DEBUG = False MULTI_PASS = False # Seed seedHex = "79dd3f23c70bb529a8e3b221cf62da0dd4bd3ca35bd0c515cd9cde5ffa6a5c4d" seed = seedHex.decode("hex") # Identity identity = "*****@*****.**" MPIN_ID = ffi.new("octet*") MPIN_IDval = ffi.new("char [%s]" % len(identity), identity) MPIN_ID[0].val = MPIN_IDval MPIN_ID[0].max = len(identity) MPIN_ID[0].len = len(identity) # Master Secret Shares MS1 = ffi.new("octet*") MS1val = ffi.new("char []", PGS) MS1[0].val = MS1val MS1[0].max = PGS MS1[0].len = PGS MS2 = ffi.new("octet*") MS2val = ffi.new("char []", PGS) MS2[0].val = MS2val
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. """ import os import unittest import json import hashlib from mpin import ffi, G1, G2, HASH_BYTES, IVL, libmpin, PAS, PFS, PGS, toHex # Master Secret Shares MS1 = ffi.new("octet*") MS1val = ffi.new("char []", PGS) MS1[0].val = MS1val MS1[0].max = PGS MS1[0].len = PGS MS2 = ffi.new("octet*") MS2val = ffi.new("char []", PGS) MS2[0].val = MS2val MS2[0].max = PGS MS2[0].len = PGS # Client secret and shares CS1 = ffi.new("octet*") CS1val = ffi.new("char []", G1) CS1[0].val = CS1val
def test_1(self): """test_1 Good PIN and good token""" vectors = json.load(open("./MPINTestVectors.json", "r")) for vector in vectors: print "Test vector {}".format(vector['test_no']) PIN1 = vector['PIN1'] PIN2 = vector['PIN2'] date = vector['DATE'] # random number generator RNG = ffi.new("csprng*") libmpin.MPIN_CREATE_CSPRNG(RNG, self.RAW) MS1_HEX = vector['MS1'] MS2_HEX = vector['MS2'] ms1_bin = MS1_HEX.decode("hex") MS1 = ffi.new("octet*") MS1val = ffi.new("char [%s]" % len(ms1_bin), ms1_bin) MS1[0].val = MS1val MS1[0].max = PGS MS1[0].len = PGS ms2_bin = MS2_HEX.decode("hex") MS2 = ffi.new("octet*") MS2val = ffi.new("char [%s]" % len(ms2_bin), ms2_bin) MS2[0].val = MS2val MS2[0].max = PGS MS2[0].len = PGS # Generate server secret shares rtn = libmpin.MPIN_GET_SERVER_SECRET(MS1, SS1) self.assertEqual(rtn, 0) self.assertEqual(vector['SS1'], toHex(SS1)) rtn = libmpin.MPIN_GET_SERVER_SECRET(MS2, SS2) self.assertEqual(rtn, 0) self.assertEqual(vector['SS2'], toHex(SS2)) # Combine server secret shares rtn = libmpin.MPIN_RECOMBINE_G2(SS1, SS2, SERVER_SECRET) self.assertEqual(rtn, 0) self.assertEqual(vector['SERVER_SECRET'], toHex(SERVER_SECRET)) mpin_id = vector['MPIN_ID_HEX'].decode("hex") MPIN_ID = ffi.new("octet*") MPIN_IDval = 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) # Hash value of MPIN_ID HASH_MPIN_ID = ffi.new("octet*") HASH_MPIN_IDval = ffi.new("char []", HASH_BYTES) HASH_MPIN_ID[0].val = HASH_MPIN_IDval HASH_MPIN_ID[0].max = HASH_BYTES HASH_MPIN_ID[0].len = HASH_BYTES libmpin.MPIN_HASH_ID(MPIN_ID, HASH_MPIN_ID) self.assertEqual(vector['HASH_MPIN_ID_HEX'], toHex(HASH_MPIN_ID)) # Generate client secret shares rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, HASH_MPIN_ID, CS1) self.assertEqual(rtn, 0) self.assertEqual(vector['CS1'], toHex(CS1)) rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS2, HASH_MPIN_ID, CS2) self.assertEqual(rtn, 0) self.assertEqual(vector['CS2'], toHex(CS2)) # Combine client secret shares : TOKEN is the full client secret rtn = libmpin.MPIN_RECOMBINE_G1(CS1, CS2, TOKEN) self.assertEqual(rtn, 0) self.assertEqual(vector['CLIENT_SECRET'], toHex(TOKEN)) # Generate Time Permit shares rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS1, HASH_MPIN_ID, TP1) self.assertEqual(rtn, 0) self.assertEqual(vector['TP1'], toHex(TP1)) rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS2, HASH_MPIN_ID, TP2) self.assertEqual(rtn, 0) self.assertEqual(vector['TP2'], toHex(TP2)) # Combine Time Permit shares rtn = libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT) self.assertEqual(rtn, 0) self.assertEqual(vector['TIME_PERMIT'], toHex(TIME_PERMIT)) # Client extracts PIN from secret to create Token rtn = libmpin.MPIN_EXTRACT_PIN(MPIN_ID, PIN1, TOKEN) self.assertEqual(rtn, 0) self.assertEqual(vector['TOKEN'], toHex(TOKEN)) x = vector['X'].decode("hex") X = ffi.new("octet*") Xval = ffi.new("char [%s]" % PGS, x) X[0].val = Xval X[0].max = PGS X[0].len = PGS # Client first pass. Use X value from test vectors rtn = libmpin.MPIN_CLIENT_1(date, MPIN_ID, ffi.NULL, X, PIN2, TOKEN, SEC, U, UT, TIME_PERMIT) self.assertEqual(rtn, 0) self.assertEqual(vector['X'], toHex(X)) self.assertEqual(vector['U'], toHex(U)) self.assertEqual(vector['UT'], toHex(UT)) self.assertEqual(vector['SEC'], toHex(SEC)) # Server calculates H(ID) and H(T|H(ID)) libmpin.MPIN_SERVER_1(date, HASH_MPIN_ID, HID, HTID) # Server generates Random number Y and sends it to Client # rtn = libmpin.MPIN_RANDOM_GENERATE(RNG,Y) # self.assertEqual(rtn, 0) # Use Y value from test vectors y = vector['Y'].decode("hex") Y = ffi.new("octet*") Yval = ffi.new("char [%s]" % PGS, y) Y[0].val = Yval Y[0].max = PGS Y[0].len = PGS # Client second pass rtn = libmpin.MPIN_CLIENT_2(X, Y, SEC) self.assertEqual(rtn, 0) self.assertEqual(vector['V'], toHex(SEC)) # Server second pass rtn = libmpin.MPIN_SERVER_2(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F) self.assertEqual(rtn, vector['SERVER_OUTPUT'])
def test_9(self): """test_9 Test successful authentication for different master secrets""" for i in range(1, 1000): # Assign a seed value seed = os.urandom(32) RAW = ffi.new("octet*") RAWval = 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 = ffi.new("csprng*") libmpin.CREATE_CSPRNG(RNG, RAW) # Generate Client master secret share for MIRACL and Customer rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS1) self.assertEqual(rtn, 0) rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS2) self.assertEqual(rtn, 0) # Generate server secret shares rtn = libmpin.MPIN_GET_SERVER_SECRET(MS1, SS1) self.assertEqual(rtn, 0) rtn = libmpin.MPIN_GET_SERVER_SECRET(MS2, SS2) self.assertEqual(rtn, 0) # Combine server secret shares rtn = libmpin.MPIN_RECOMBINE_G2(SS1, SS2, SERVER_SECRET) self.assertEqual(rtn, 0) # Generate client secret shares rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, self.HASH_MPIN_ID, CS1) self.assertEqual(rtn, 0) rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS2, self.HASH_MPIN_ID, CS2) self.assertEqual(rtn, 0) # Combine client secret shares : TOKEN is the full client secret rtn = libmpin.MPIN_RECOMBINE_G1(CS1, CS2, TOKEN) self.assertEqual(rtn, 0) # Generate Time Permit shares rtn = libmpin.MPIN_GET_CLIENT_PERMIT(self.date, MS1, self.HASH_MPIN_ID, TP1) self.assertEqual(rtn, 0) rtn = libmpin.MPIN_GET_CLIENT_PERMIT(self.date, MS2, self.HASH_MPIN_ID, TP2) self.assertEqual(rtn, 0) # Combine Time Permit shares rtn = libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT) self.assertEqual(rtn, 0) # Client extracts PIN from secret to create Token PIN = 1234 rtn = libmpin.MPIN_EXTRACT_PIN(self.MPIN_ID, PIN, TOKEN) self.assertEqual(rtn, 0) # Client first pass rtn = libmpin.MPIN_CLIENT_1(self.date, self.MPIN_ID, RNG, X, PIN, TOKEN, SEC, U, UT, TIME_PERMIT) self.assertEqual(rtn, 0) # Server calculates H(ID) and H(T|H(ID)) libmpin.MPIN_SERVER_1(self.date, self.MPIN_ID, HID, HTID) # Server generates Random number Y and sends it to Client rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, Y) self.assertEqual(rtn, 0) # Client second pass rtn = libmpin.MPIN_CLIENT_2(X, Y, SEC) self.assertEqual(rtn, 0) # Server second pass rtn = libmpin.MPIN_SERVER_2(self.date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F) self.assertEqual(rtn, 0)
def test_1(self): """test_1 Good PIN and good token""" vectors = json.load(open("./MPINTestVectors.json", "r")) for vector in vectors: print "Test vector {}".format(vector['test_no']) PIN1 = vector['PIN1'] PIN2 = vector['PIN2'] date = vector['DATE'] # random number generator RNG = ffi.new("csprng*") libmpin.CREATE_CSPRNG(RNG, self.RAW) MS1_HEX = vector['MS1'] MS2_HEX = vector['MS2'] ms1_bin = MS1_HEX.decode("hex") MS1 = ffi.new("octet*") MS1val = ffi.new("char [%s]" % len(ms1_bin), ms1_bin) MS1[0].val = MS1val MS1[0].max = PGS MS1[0].len = PGS ms2_bin = MS2_HEX.decode("hex") MS2 = ffi.new("octet*") MS2val = ffi.new("char [%s]" % len(ms2_bin), ms2_bin) MS2[0].val = MS2val MS2[0].max = PGS MS2[0].len = PGS # Generate server secret shares rtn = libmpin.MPIN_GET_SERVER_SECRET(MS1, SS1) self.assertEqual(rtn, 0) self.assertEqual(vector['SS1'], toHex(SS1)) rtn = libmpin.MPIN_GET_SERVER_SECRET(MS2, SS2) self.assertEqual(rtn, 0) self.assertEqual(vector['SS2'], toHex(SS2)) # Combine server secret shares rtn = libmpin.MPIN_RECOMBINE_G2(SS1, SS2, SERVER_SECRET) self.assertEqual(rtn, 0) self.assertEqual(vector['SERVER_SECRET'], toHex(SERVER_SECRET)) mpin_id = vector['MPIN_ID_HEX'].decode("hex") MPIN_ID = ffi.new("octet*") MPIN_IDval = 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) # Hash value of MPIN_ID HASH_MPIN_ID = ffi.new("octet*") HASH_MPIN_IDval = ffi.new("char []", HASH_BYTES) HASH_MPIN_ID[0].val = HASH_MPIN_IDval HASH_MPIN_ID[0].max = HASH_BYTES HASH_MPIN_ID[0].len = HASH_BYTES libmpin.MPIN_HASH_ID(MPIN_ID, HASH_MPIN_ID) self.assertEqual(vector['HASH_MPIN_ID_HEX'], toHex(HASH_MPIN_ID)) # Generate client secret shares rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, HASH_MPIN_ID, CS1) self.assertEqual(rtn, 0) self.assertEqual(vector['CS1'], toHex(CS1)) rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS2, HASH_MPIN_ID, CS2) self.assertEqual(rtn, 0) self.assertEqual(vector['CS2'], toHex(CS2)) # Combine client secret shares : TOKEN is the full client secret rtn = libmpin.MPIN_RECOMBINE_G1(CS1, CS2, TOKEN) self.assertEqual(rtn, 0) self.assertEqual(vector['CLIENT_SECRET'], toHex(TOKEN)) # Generate Time Permit shares rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS1, HASH_MPIN_ID, TP1) self.assertEqual(rtn, 0) self.assertEqual(vector['TP1'], toHex(TP1)) rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS2, HASH_MPIN_ID, TP2) self.assertEqual(rtn, 0) self.assertEqual(vector['TP2'], toHex(TP2)) # Combine Time Permit shares rtn = libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT) self.assertEqual(rtn, 0) self.assertEqual(vector['TIME_PERMIT'], toHex(TIME_PERMIT)) # Client extracts PIN from secret to create Token rtn = libmpin.MPIN_EXTRACT_PIN(MPIN_ID, PIN1, TOKEN) self.assertEqual(rtn, 0) self.assertEqual(vector['TOKEN'], toHex(TOKEN)) x = vector['X'].decode("hex") X = ffi.new("octet*") Xval = ffi.new("char [%s]" % PGS, x) X[0].val = Xval X[0].max = PGS X[0].len = PGS # Client first pass. Use X value from test vectors rtn = libmpin.MPIN_CLIENT_1(date, MPIN_ID, ffi.NULL, X, PIN2, TOKEN, SEC, U, UT, TIME_PERMIT) self.assertEqual(rtn, 0) self.assertEqual(vector['X'], toHex(X)) self.assertEqual(vector['U'], toHex(U)) self.assertEqual(vector['UT'], toHex(UT)) self.assertEqual(vector['SEC'], toHex(SEC)) # Server calculates H(ID) and H(T|H(ID)) libmpin.MPIN_SERVER_1(date, MPIN_ID, HID, HTID) # Server generates Random number Y and sends it to Client # rtn = libmpin.MPIN_RANDOM_GENERATE(RNG,Y) # self.assertEqual(rtn, 0) # Use Y value from test vectors y = vector['Y'].decode("hex") Y = ffi.new("octet*") Yval = ffi.new("char [%s]" % PGS, y) Y[0].val = Yval Y[0].max = PGS Y[0].len = PGS # Client second pass rtn = libmpin.MPIN_CLIENT_2(X, Y, SEC) self.assertEqual(rtn, 0) self.assertEqual(vector['V'], toHex(SEC)) # Server second pass rtn = libmpin.MPIN_SERVER_2(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F) self.assertEqual(rtn, vector['SERVER_OUTPUT'])
def test_3(self): """test_3 Good PIN and bad token""" PIN1 = 1234 PIN2 = 1234 # random number generator RNG = ffi.new("csprng*") libmpin.MPIN_CREATE_CSPRNG(RNG, self.RAW) # Generate Client master secret share for MIRACL and Customer rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS1) self.assertEqual(rtn, 0) rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS2) self.assertEqual(rtn, 0) # Generate server secret shares rtn = libmpin.MPIN_GET_SERVER_SECRET(MS1, SS1) self.assertEqual(rtn, 0) rtn = libmpin.MPIN_GET_SERVER_SECRET(MS2, SS2) self.assertEqual(rtn, 0) # Combine server secret shares rtn = libmpin.MPIN_RECOMBINE_G2(SS1, SS2, SERVER_SECRET) self.assertEqual(rtn, 0) # Generate client secret shares rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, self.HASH_MPIN_ID, CS1) self.assertEqual(rtn, 0) rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS2, self.HASH_MPIN_ID, CS2) self.assertEqual(rtn, 0) # Combine client secret shares : TOKEN is the full client secret rtn = libmpin.MPIN_RECOMBINE_G1(CS1, CS2, TOKEN) self.assertEqual(rtn, 0) # Generate Time Permit shares rtn = libmpin.MPIN_GET_CLIENT_PERMIT(self.date, MS1, self.HASH_MPIN_ID, TP1) self.assertEqual(rtn, 0) rtn = libmpin.MPIN_GET_CLIENT_PERMIT(self.date, MS2, self.HASH_MPIN_ID, TP2) self.assertEqual(rtn, 0) # Combine Time Permit shares rtn = libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT) self.assertEqual(rtn, 0) # Client extracts PIN from secret to create Token PIN1 = 1234 rtn = libmpin.MPIN_EXTRACT_PIN(self.MPIN_ID, PIN1, TOKEN) self.assertEqual(rtn, 0) # Client first pass rtn = libmpin.MPIN_CLIENT_1(self.date, self.MPIN_ID, RNG, X, PIN2, TOKEN, SEC, U, UT, TIME_PERMIT) self.assertEqual(rtn, 0) # Server calculates H(ID) and H(T|H(ID)) libmpin.MPIN_SERVER_1(self.date, self.HASH_MPIN_ID, HID, HTID) # Server generates Random number Y and sends it to Client rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, Y) self.assertEqual(rtn, 0) # Client second pass rtn = libmpin.MPIN_CLIENT_2(X, Y, SEC) self.assertEqual(rtn, 0) # Server second pass # clientSecret aka V is equal to UT to model a bad token rtn = libmpin.MPIN_SERVER_2(self.date, HID, HTID, Y, SERVER_SECRET, U, UT, UT, E, F) self.assertEqual(rtn, -19)
def setUp(self): # Form MPin ID endUserData = { "issued": "2013-10-19T06:12:28Z", "userID": "*****@*****.**", "mobile": 1, "salt": "e985da112a378c222cfc2f7226097b0c" } mpin_id = json.dumps(endUserData) self.MPIN_ID = ffi.new("octet*") self.MPIN_IDval = ffi.new("char [%s]" % len(mpin_id), mpin_id) self.MPIN_ID[0].val = self.MPIN_IDval self.MPIN_ID[0].max = len(mpin_id) self.MPIN_ID[0].len = len(mpin_id) # Hash value of MPIN_ID self.HASH_MPIN_ID = ffi.new("octet*") self.HASH_MPIN_IDval = ffi.new("char []", HASH_BYTES) self.HASH_MPIN_ID[0].val = self.HASH_MPIN_IDval self.HASH_MPIN_ID[0].max = HASH_BYTES self.HASH_MPIN_ID[0].len = HASH_BYTES libmpin.MPIN_HASH_ID(self.MPIN_ID, self.HASH_MPIN_ID) # Assign a seed value seedHex = "3ade3d4a5c698e8910bf92f25d97ceeb7c25ed838901a5cb5db2cf25434c1fe76c7f79b7af2e5e1e4988e4294dbd9bd9fa3960197fb7aec373609fb890d74b16a4b14b2ae7e23b75f15d36c21791272372863c4f8af39980283ae69a79cf4e48e908f9e0" self.seed = seedHex.decode("hex") self.RAW = ffi.new("octet*") self.RAWval = ffi.new("char [%s]" % len(self.seed), self.seed) self.RAW[0].val = self.RAWval self.RAW[0].len = len(self.seed) self.RAW[0].max = len(self.seed) self.date = 16238 self.ms1Hex = "035fb3138d1dfa87cd7aab637faa7400f0c8416ab7e922ddea8dc0462bc0123a" self.ms2Hex = "1c9c8ad28f36fd10f5f33ea3b9db0a1eaf8ef7fc13cd55d1b47d7e607e3ca619" self.ss1Hex = "114658f8ccb93969fc7ec23257397dbe820a329016182d3168cb2d9b8ce9cbcc0d580feb5b621d6c00ed12e70688ec130a138a48b2c2fd57695bad71290c365d1d621117cbcd2061357965ca2f81468979ca527c9888ae87d84d8df0589e6814041a1ca3163dd77d9b0c29c0a6aadca1cbaa7c2905d8eb8ab12051ea06f12439" self.ss2Hex = "239b55f12040f70b6a5e53c45985aa4bfa368a3d26a000775f7960a2716023350b08851b5753c33bddba07c172f4745abb70e587902dca52e49199ee4c2562130a910fb6402c417e753a873b907153820ae5854a4c27948806000e82452d77f3127e66573cae233c07137e63fbac8f09ef39718c421f71f1b9be5f150a17bd12" self.serverSecretHex = "09aa0e36fa30c9b0cc9d5fa7b2be33595542f408a49ad0c91c4f7bba3d993cfc23eca9811699525fa8523069b6d6e1540deeb94eaa26c1e15776b4ab65e4603c0a161baa02d75fb1e966863b51ac5ee67872f663926b8537292dd170e83a136e098e2da97161db6c75a182088af1da6557d06a7816ec6ac7882262ce183fc605" self.cs1Hex = "04050de8b61fa91b4747017a7ed72ceb4b26056382435413eab2b9259a4c99f9161eb63db017296616b59b861f2433f44cc56a3d8d5ed600cf338de0f7ce62b900" self.cs2Hex = "0420b7333796a1d7a5abc553dcbacff281f5a4b8dea937da548ee6103c0089b6a218e0d1d617a55f9b789c4ebd25f5cf8aafd0f666306031cf5b6faa9e50d88f50" self.clientSecretHex = "040b98a2b31786a50f548bd692171f99d1d1be26129725519624d3cc90b98bd17321a24c5b9511ff887672e460d6157b1c5461114e4e4f62d6207f5e8d48919fad" self.tp1Hex = "04123c806b8366721e3718a731fa109c144561f033ff5fe44356091a3c2365c9182218b86526247eb7fd552575800ef3cc9da22c6655d7795377b216030c9f1f62" self.tp2Hex = "041cf3f5604e5f8ecb44bc3e36f5fa1fe68e873b0822646a3a8f0fcf0477f561241a6bda4a9e93a455a6b940126feae5959ca855870cd8275d7dd1a4df4ddb6211" self.timePermitHex = "0405198cbd152cfc860cc22d6c16d92ff1a1d5d6d9b268588c3a74c4e6fc056a0002d35c769458aaaf01ecc34cbaf7b6d8154deb2d26db332c5a421557f4fe1ba3" self.tokenHex = "04213945622f5c6638c13692d77f12983cb0664fb51f7f36a5664872894b87dc051786a8747cf01b749f78fb75aa64bc932e71c9a6e1ee261aa687564bf38be329" # Token self.token = self.tokenHex.decode("hex") self.TOKEN = ffi.new("octet*") self.TOKENval = ffi.new("char [%s]" % len(self.token), self.token) self.TOKEN[0].val = self.TOKENval self.TOKEN[0].len = len(self.token) self.TOKEN[0].max = len(self.token) # TIME_PERMIT self.timePermit = self.timePermitHex.decode("hex") self.TIMEPERMIT = ffi.new("octet*") self.TIMEPERMITval = ffi.new("char [%s]" % len(self.timePermit), self.timePermit) self.TIMEPERMIT[0].val = self.TIMEPERMITval self.TIMEPERMIT[0].len = len(self.timePermit) self.TIMEPERMIT[0].max = len(self.timePermit) # SERVER_SECRET self.serverSecret = self.serverSecretHex.decode("hex") self.SERVER_SECRET = ffi.new("octet*") self.SERVER_SECRETval = ffi.new("char [%s]" % len(self.serverSecret), self.serverSecret) self.SERVER_SECRET[0].val = self.SERVER_SECRETval self.SERVER_SECRET[0].len = len(self.serverSecret) self.SERVER_SECRET[0].max = len(self.serverSecret) self.ms1 = self.ms1Hex.decode("hex") self.clientSecret = self.clientSecretHex.decode("hex") self.timePermit = self.timePermitHex.decode("hex")