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 2019/08/01 14:05:25 UTC

[incubator-milagro-crypto-c] branch issue26 created (now 1efd096)

This is an automated email from the ASF dual-hosted git repository.

kmccusker pushed a change to branch issue26
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto-c.git.


      at 1efd096  add bls wrapper

This branch includes the following new commits:

     new 1efd096  add bls wrapper

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[incubator-milagro-crypto-c] 01/01: add bls wrapper

Posted by km...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kmccusker pushed a commit to branch issue26
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto-c.git

commit 1efd0962cde9acc0797adc37df6e821e11e7e421
Author: Kealan McCusker <ke...@gmail.com>
AuthorDate: Thu Aug 1 15:04:52 2019 +0100

    add bls wrapper
---
 CPackConfig.cmake                         |   2 +
 cmake/PythonSiteDirs.cmake                |  11 +
 wrappers/python/CMakeLists.txt            |   5 +
 wrappers/python/README.md                 |   5 +-
 wrappers/python/TestMPINInstall_ZZZ.py.in |  49 ++--
 wrappers/python/TestMPIN_BN254CX.py       | 140 ---------
 wrappers/python/TimeMPIN_ZZZ.py.in        |  58 ++--
 wrappers/python/bls_ZZZ.py.in             | 469 ++++++++++++++++++++++++++++++
 wrappers/python/mpin_ZZZ.py.in            |  78 ++---
 wrappers/python/wcc_ZZZ.py.in             |  85 +++---
 10 files changed, 631 insertions(+), 271 deletions(-)

diff --git a/CPackConfig.cmake b/CPackConfig.cmake
index f46fc79..fd584ae 100644
--- a/CPackConfig.cmake
+++ b/CPackConfig.cmake
@@ -44,6 +44,8 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
   list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}/lib")
   list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${PYTHON_SITE_LIB}")
   list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${PYTHON_SITE_PACKAGES}")
+  list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${PYTHON3_SITE_LIB}")
+  list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${PYTHON3_SITE_PACKAGES}")  
   set(CPACK_GENERATOR "RPM")
 endif()
 
diff --git a/cmake/PythonSiteDirs.cmake b/cmake/PythonSiteDirs.cmake
index ea57c06..bf0f968 100644
--- a/cmake/PythonSiteDirs.cmake
+++ b/cmake/PythonSiteDirs.cmake
@@ -27,3 +27,14 @@ execute_process(COMMAND
   python -c "from distutils.sysconfig import get_python_lib; from os.path import dirname; print dirname(get_python_lib())"
   OUTPUT_VARIABLE PYTHON_SITE_LIB
 )
+
+execute_process(COMMAND
+  python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
+  OUTPUT_VARIABLE PYTHON3_SITE_PACKAGES
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+execute_process(COMMAND
+  python3 -c "from distutils.sysconfig import get_python_lib; from os.path import dirname; print(dirname(get_python_lib()))"
+  OUTPUT_VARIABLE PYTHON3_SITE_LIB
+)
diff --git a/wrappers/python/CMakeLists.txt b/wrappers/python/CMakeLists.txt
index 8063948..a0a7961 100644
--- a/wrappers/python/CMakeLists.txt
+++ b/wrappers/python/CMakeLists.txt
@@ -50,5 +50,10 @@ foreach(curve ${AMCL_CURVE})
     amcl_configure_file_curve(wcc_ZZZ.py.in wcc_${TC}.py ${curve} amcl_wcc_${TC}_GEN_PYS)
     install(FILES "${amcl_wcc_${TC}_GEN_PYS}" DESTINATION ${PYTHON_SITE_PACKAGES})
   endif()
+
+  if(TARGET amcl_bls_${TC})
+    amcl_configure_file_curve(bls_ZZZ.py.in bls_${TC}.py ${curve} amcl_bls_${TC}_GEN_PYS)
+    install(FILES "${amcl_bls_${TC}_GEN_PYS}" DESTINATION ${PYTHON3_SITE_PACKAGES})
+  endif()
   
 endforeach()
diff --git a/wrappers/python/README.md b/wrappers/python/README.md
index 16688af..a65806e 100644
--- a/wrappers/python/README.md
+++ b/wrappers/python/README.md
@@ -3,5 +3,6 @@ interacts with the c code using CFFI.
 
 To run all MPIN tests
 
-    ./TestMPINInstall.py -v
-
+```
+./TestMPINInstall.py -v
+```
diff --git a/wrappers/python/TestMPINInstall_ZZZ.py.in b/wrappers/python/TestMPINInstall_ZZZ.py.in
index 28f3a1b..1b46807 100644
--- a/wrappers/python/TestMPINInstall_ZZZ.py.in
+++ b/wrappers/python/TestMPINInstall_ZZZ.py.in
@@ -24,9 +24,6 @@ import json
 import hashlib
 import mpin_ZZZ
 
-HASH_TYPE_MPIN_ZZZ = mpin_ZZZ.SHA256
-
-
 class TestMPIN(unittest.TestCase):
     """Tests M-Pin crypto code"""
 
@@ -42,7 +39,7 @@ class TestMPIN(unittest.TestCase):
         self.mpin_id = json.dumps(endUserData)
 
         # Hash value of MPIN_ID
-        self.hash_mpin_id = mpin_ZZZ.hash_id(HASH_TYPE_MPIN_ZZZ, self.mpin_id)
+        self.hash_mpin_id = mpin_ZZZ.hash_id(mpin_ZZZ.HASH_TYPE_ZZZ, self.mpin_id)
 
         # Assign a seed value
         seedHex = "3ade3d4a5c698e8910bf92f25d97ceeb7c25ed838901a5cb5db2cf25434c1fe76c7f79b7af2e5e1e4988e4294dbd9bd9fa3960197fb7aec373609fb890d74b16a4b14b2ae7e23b75f15d36c21791272372863c4f8af39980283ae69a79cf4e48e908f9e0"
@@ -86,10 +83,10 @@ class TestMPIN(unittest.TestCase):
 
         # Generate Time Permit shares
         rtn, tp1 = mpin_ZZZ.get_client_permit(
-            HASH_TYPE_MPIN_ZZZ, self.date, ms1, self.hash_mpin_id)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, ms1, self.hash_mpin_id)
         self.assertEqual(rtn, 0)
         rtn, tp2 = mpin_ZZZ.get_client_permit(
-            HASH_TYPE_MPIN_ZZZ, self.date, ms2, self.hash_mpin_id)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, ms2, self.hash_mpin_id)
         self.assertEqual(rtn, 0)
 
         # Combine Time Permit shares
@@ -98,17 +95,17 @@ class TestMPIN(unittest.TestCase):
 
         # Client extracts PIN from secret to create Token
         rtn, token = mpin_ZZZ.extract_pin(
-            HASH_TYPE_MPIN_ZZZ, self.mpin_id, PIN1, client_secret)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.mpin_id, PIN1, client_secret)
         self.assertEqual(rtn, 0)
 
         # Client first pass
         rtn, x, u, ut, sec = mpin_ZZZ.client_1(
-            HASH_TYPE_MPIN_ZZZ, self.date, self.mpin_id, rng, None, PIN2, token, time_permit)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, self.mpin_id, rng, None, PIN2, token, time_permit)
         self.assertEqual(rtn, 0)
 
         # Server calculates H(ID) and H(T|H(ID))
         HID, HTID = mpin_ZZZ.server_1(
-            HASH_TYPE_MPIN_ZZZ, self.date, self.mpin_id)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, self.mpin_id)
 
         # Server generates Random number Y and sends it to Client
         rtn, y = mpin_ZZZ.random_generate(rng)
@@ -159,10 +156,10 @@ class TestMPIN(unittest.TestCase):
 
         # Generate Time Permit shares
         rtn, tp1 = mpin_ZZZ.get_client_permit(
-            HASH_TYPE_MPIN_ZZZ, self.date, ms1, self.hash_mpin_id)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, ms1, self.hash_mpin_id)
         self.assertEqual(rtn, 0)
         rtn, tp2 = mpin_ZZZ.get_client_permit(
-            HASH_TYPE_MPIN_ZZZ, self.date, ms2, self.hash_mpin_id)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, ms2, self.hash_mpin_id)
         self.assertEqual(rtn, 0)
 
         # Combine Time Permit shares
@@ -171,17 +168,17 @@ class TestMPIN(unittest.TestCase):
 
         # Client extracts PIN from secret to create Token
         rtn, token = mpin_ZZZ.extract_pin(
-            HASH_TYPE_MPIN_ZZZ, self.mpin_id, PIN1, client_secret)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.mpin_id, PIN1, client_secret)
         self.assertEqual(rtn, 0)
 
         # Client first pass
         rtn, x, u, ut, sec = mpin_ZZZ.client_1(
-            HASH_TYPE_MPIN_ZZZ, self.date, self.mpin_id, rng, None, PIN2, token, time_permit)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, self.mpin_id, rng, None, PIN2, token, time_permit)
         self.assertEqual(rtn, 0)
 
         # Server calculates H(ID) and H(T|H(ID))
         HID, HTID = mpin_ZZZ.server_1(
-            HASH_TYPE_MPIN_ZZZ, self.date, self.mpin_id)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, self.mpin_id)
 
         # Server generates Random number Y and sends it to Client
         rtn, y = mpin_ZZZ.random_generate(rng)
@@ -232,10 +229,10 @@ class TestMPIN(unittest.TestCase):
 
         # Generate Time Permit shares
         rtn, tp1 = mpin_ZZZ.get_client_permit(
-            HASH_TYPE_MPIN_ZZZ, self.date, ms1, self.hash_mpin_id)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, ms1, self.hash_mpin_id)
         self.assertEqual(rtn, 0)
         rtn, tp2 = mpin_ZZZ.get_client_permit(
-            HASH_TYPE_MPIN_ZZZ, self.date, ms2, self.hash_mpin_id)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, ms2, self.hash_mpin_id)
         self.assertEqual(rtn, 0)
 
         # Combine Time Permit shares
@@ -244,17 +241,17 @@ class TestMPIN(unittest.TestCase):
 
         # Client extracts PIN from secret to create Token
         rtn, token = mpin_ZZZ.extract_pin(
-            HASH_TYPE_MPIN_ZZZ, self.mpin_id, PIN1, client_secret)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.mpin_id, PIN1, client_secret)
         self.assertEqual(rtn, 0)
 
         # Client first pass
         rtn, x, u, ut, sec = mpin_ZZZ.client_1(
-            HASH_TYPE_MPIN_ZZZ, self.date, self.mpin_id, rng, None, PIN2, token, time_permit)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, self.mpin_id, rng, None, PIN2, token, time_permit)
         self.assertEqual(rtn, 0)
 
         # Server calculates H(ID) and H(T|H(ID))
         HID, HTID = mpin_ZZZ.server_1(
-            HASH_TYPE_MPIN_ZZZ, self.date, self.mpin_id)
+            mpin_ZZZ.HASH_TYPE_ZZZ, self.date, self.mpin_id)
 
         # Server generates Random number Y and sends it to Client
         rtn, y = mpin_ZZZ.random_generate(rng)
@@ -283,7 +280,7 @@ class TestMPIN(unittest.TestCase):
         match = 0
         for i in range(1, 1000):
             rand_val = os.urandom(32)
-            hash_mpin_id = mpin_ZZZ.hash_id(HASH_TYPE_MPIN_ZZZ, rand_val)
+            hash_mpin_id = mpin_ZZZ.hash_id(mpin_ZZZ.HASH_TYPE_ZZZ, rand_val)
 
             # Generate client secret shares
             rtn, cs1 = mpin_ZZZ.get_client_secret(ms1, hash_mpin_id)
@@ -329,8 +326,8 @@ class TestMPIN(unittest.TestCase):
     def test_7(self):
         """test_7 AES-GCM: Successful encryption and decryption"""
 
-        # Generate 16 byte key
-        key = os.urandom(mpin_ZZZ.PAS)
+        # Generate key
+        key = os.urandom(mpin_ZZZ.AESKEY_ZZZ)
 
         # Generate 12 byte IV
         iv = os.urandom(mpin_ZZZ.IVL)
@@ -353,8 +350,8 @@ class TestMPIN(unittest.TestCase):
     def test_8(self):
         """test_8 AES-GCM: Failed encryption and decryption by changing a ciphertext byte"""
 
-        # Generate 16 byte key
-        key = os.urandom(mpin_ZZZ.PAS)
+        # Generate key
+        key = os.urandom(mpin_ZZZ.AESKEY_ZZZ)
 
         # Generate 12 byte IV
         iv = os.urandom(mpin_ZZZ.IVL)
@@ -381,8 +378,8 @@ class TestMPIN(unittest.TestCase):
     def test_9(self):
         """test_9 AES-GCM: Failed encryption and decryption by changing a header byte"""
 
-        # Generate 16 byte key
-        key = os.urandom(mpin_ZZZ.PAS)
+        # Generate key
+        key = os.urandom(mpin_ZZZ.AESKEY_ZZZ)
 
         # Generate 12 byte IV
         iv = os.urandom(mpin_ZZZ.IVL)
diff --git a/wrappers/python/TestMPIN_BN254CX.py b/wrappers/python/TestMPIN_BN254CX.py
deleted file mode 100644
index 1939704..0000000
--- a/wrappers/python/TestMPIN_BN254CX.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/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.
-"""
-import unittest
-import json
-import mpin_BN254CX
-
-HASH_TYPE_MPIN_ZZZ = mpin_BN254CX.SHA256
-
-
-class TestMPIN(unittest.TestCase):
-    """Tests M-Pin crypto code"""
-
-    def setUp(self):
-        pass
-
-    def test_1(self):
-        """test_1 Test Vector test"""
-        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']
-
-            MS1_HEX = vector['MS1']
-            MS2_HEX = vector['MS2']
-
-            ms1 = MS1_HEX.decode("hex")
-            ms2 = MS2_HEX.decode("hex")
-
-            # Generate server secret shares
-            rtn, ss1 = mpin_BN254CX.get_server_secret(ms1)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['SS1'], ss1.encode("hex"))
-            rtn, ss2 = mpin_BN254CX.get_server_secret(ms2)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['SS2'], ss2.encode("hex"))
-
-            # Combine server secret shares
-            rtn, server_secret = mpin_BN254CX.recombine_G2(ss1, ss2)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(
-                vector['SERVER_SECRET'],
-                server_secret.encode("hex"))
-
-            mpin_id = vector['MPIN_ID_HEX'].decode("hex")
-
-            # Hash value of MPIN_ID
-            hash_mpin_id = mpin_BN254CX.hash_id(HASH_TYPE_MPIN_ZZZ, mpin_id)
-            self.assertEqual(
-                vector['HASH_MPIN_ID_HEX'],
-                hash_mpin_id.encode("hex"))
-
-            # Generate client secret shares
-            rtn, cs1 = mpin_BN254CX.get_client_secret(ms1, hash_mpin_id)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['CS1'], cs1.encode("hex"))
-            rtn, cs2 = mpin_BN254CX.get_client_secret(ms2, hash_mpin_id)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['CS2'], cs2.encode("hex"))
-
-            # Combine client secret shares : TOKEN is the full client secret
-            rtn, client_secret = mpin_BN254CX.recombine_G1(cs1, cs2)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(
-                vector['CLIENT_SECRET'],
-                client_secret.encode("hex"))
-
-            # Generate Time Permit shares
-            rtn, tp1 = mpin_BN254CX.get_client_permit(
-                HASH_TYPE_MPIN_ZZZ, date, ms1, hash_mpin_id)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['TP1'], tp1.encode("hex"))
-            rtn, tp2 = mpin_BN254CX.get_client_permit(
-                HASH_TYPE_MPIN_ZZZ, date, ms2, hash_mpin_id)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['TP2'], tp2.encode("hex"))
-
-            # Combine Time Permit shares
-            rtn, time_permit = mpin_BN254CX.recombine_G1(tp1, tp2)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['TIME_PERMIT'], time_permit.encode("hex"))
-
-            # Client extracts PIN from secret to create Token
-            rtn, token = mpin_BN254CX.extract_pin(
-                HASH_TYPE_MPIN_ZZZ, mpin_id, PIN1, client_secret)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['TOKEN'], token.encode("hex"))
-
-            x = vector['X'].decode("hex")
-
-            # Client first pass. Use X value from test vectors
-            rtn, x, u, ut, sec = mpin_BN254CX.client_1(
-                HASH_TYPE_MPIN_ZZZ, date, mpin_id, None, x, PIN2, token, time_permit)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['X'], x.encode("hex"))
-            self.assertEqual(vector['U'], u.encode("hex"))
-            self.assertEqual(vector['UT'], ut.encode("hex"))
-            self.assertEqual(vector['SEC'], sec.encode("hex"))
-
-            # Server calculates H(ID) and H(T|H(ID))
-            HID, HTID = mpin_BN254CX.server_1(
-                HASH_TYPE_MPIN_ZZZ, date, mpin_id)
-
-            # Use Y value from test vectors
-            y = vector['Y'].decode("hex")
-
-            # Client second pass
-            rtn, v = mpin_BN254CX.client_2(x, y, sec)
-            self.assertEqual(rtn, 0)
-            self.assertEqual(vector['V'], v.encode("hex"))
-
-            # Server second pass
-            rtn, E, F = mpin_BN254CX.server_2(
-                date, HID, HTID, y, server_secret, u, ut, v, None)
-            self.assertEqual(rtn, vector['SERVER_OUTPUT'])
-
-
-if __name__ == '__main__':
-    # Run tests
-    unittest.main()
diff --git a/wrappers/python/TimeMPIN_ZZZ.py.in b/wrappers/python/TimeMPIN_ZZZ.py.in
index 548a4bc..8305fb0 100755
--- a/wrappers/python/TimeMPIN_ZZZ.py.in
+++ b/wrappers/python/TimeMPIN_ZZZ.py.in
@@ -38,8 +38,6 @@ def time_func(stmt, n=10, setup='from __main__ import *'):
 
 nIter = 100
 
-HASH_TYPE_MPIN_ZZZ = mpin_ZZZ.SHA256
-
 if __name__ == "__main__":
     # Print hex values
     DEBUG = False
@@ -65,7 +63,7 @@ if __name__ == "__main__":
     mpin_id = "alice@milagro.com"
 
     # Hash mpin_id
-    hash_mpin_id = mpin_ZZZ.hash_id(HASH_TYPE_MPIN_ZZZ, mpin_id)
+    hash_mpin_id = mpin_ZZZ.hash_id(mpin_ZZZ.HASH_TYPE_ZZZ, mpin_id)
     if DEBUG:
         print "mpin_id: %s" % mpin_id.encode("hex")
         print "hash_mpin_id: %s" % hash_mpin_id.encode("hex")
@@ -127,16 +125,16 @@ if __name__ == "__main__":
     if DEBUG:
         print "Date %s" % date
     time_func(
-        'rtn, tp1 = mpin_ZZZ.get_client_permit(HASH_TYPE_MPIN_ZZZ, date, ms1, hash_mpin_id)',
+        'rtn, tp1 = mpin_ZZZ.get_client_permit(mpin_ZZZ.HASH_TYPE_ZZZ, date, ms1, hash_mpin_id)',
         nIter)
     rtn, tp1 = mpin_ZZZ.get_client_permit(
-        HASH_TYPE_MPIN_ZZZ, date, ms1, hash_mpin_id)
+        mpin_ZZZ.HASH_TYPE_ZZZ, date, ms1, hash_mpin_id)
     if rtn != 0:
-        print "get_client_permit(HASH_TYPE_MPIN_ZZZ, date, ms1, hash_mpin_id) Error %s" % rtn
+        print "get_client_permit(mpin_ZZZ.HASH_TYPE_ZZZ, date, ms1, hash_mpin_id) Error %s" % rtn
     rtn, tp2 = mpin_ZZZ.get_client_permit(
-        HASH_TYPE_MPIN_ZZZ, date, ms2, hash_mpin_id)
+        mpin_ZZZ.HASH_TYPE_ZZZ, date, ms2, hash_mpin_id)
     if rtn != 0:
-        print "get_client_permit(HASH_TYPE_MPIN_ZZZ, date, ms2, hash_mpin_id) Error %s" % rtn
+        print "get_client_permit(mpin_ZZZ.HASH_TYPE_ZZZ, date, ms2, hash_mpin_id) Error %s" % rtn
     if DEBUG:
         print "tp1: %s" % tp1.encode("hex")
         print "tp2: %s" % tp2.encode("hex")
@@ -151,12 +149,12 @@ if __name__ == "__main__":
     # Client extracts PIN from secret to create Token
     PIN = 1234
     time_func(
-        'rtn, token = mpin_ZZZ.extract_pin(HASH_TYPE_MPIN_ZZZ, mpin_id, PIN, client_secret)',
+        'rtn, token = mpin_ZZZ.extract_pin(mpin_ZZZ.HASH_TYPE_ZZZ, mpin_id, PIN, client_secret)',
         nIter)
     rtn, token = mpin_ZZZ.extract_pin(
-        HASH_TYPE_MPIN_ZZZ, mpin_id, PIN, client_secret)
+        mpin_ZZZ.HASH_TYPE_ZZZ, mpin_id, PIN, client_secret)
     if rtn != 0:
-        print "extract_pin(HASH_TYPE_MPIN_ZZZ, mpin_id, PIN, token) Error %s" % rtn
+        print "extract_pin(mpin_ZZZ.HASH_TYPE_ZZZ, mpin_id, PIN, token) Error %s" % rtn
     print "Token: %s" % token.encode("hex")
 
     if ONE_PASS:
@@ -176,10 +174,10 @@ if __name__ == "__main__":
 
         # Client MPIN
         time_func(
-            'rtn, x, u, ut, v, y = mpin_ZZZ.client(HASH_TYPE_MPIN_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit, None, epoch_time)',
+            'rtn, x, u, ut, v, y = mpin_ZZZ.client(mpin_ZZZ.HASH_TYPE_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit, None, epoch_time)',
             nIter)
         rtn, x, u, ut, v, y = mpin_ZZZ.client(
-            HASH_TYPE_MPIN_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit, None, epoch_time)
+            mpin_ZZZ.HASH_TYPE_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit, None, epoch_time)
         if rtn != 0:
             print "MPIN_CLIENT ERROR %s" % rtn
 
@@ -192,10 +190,10 @@ if __name__ == "__main__":
 
         # Server MPIN
         time_func(
-            'rtn, HID, HTID, E, F, y2 = mpin_ZZZ.server(HASH_TYPE_MPIN_ZZZ, date, server_secret, u, ut, v, mpin_id, None, epoch_time, None)',
+            'rtn, HID, HTID, E, F, y2 = mpin_ZZZ.server(mpin_ZZZ.HASH_TYPE_ZZZ, date, server_secret, u, ut, v, mpin_id, None, epoch_time, None)',
             nIter)
         rtn, HID, HTID, E, F, y2 = mpin_ZZZ.server(
-            HASH_TYPE_MPIN_ZZZ, date, server_secret, u, ut, v, mpin_id, None, epoch_time, None)
+            mpin_ZZZ.HASH_TYPE_ZZZ, date, server_secret, u, ut, v, mpin_id, None, epoch_time, None)
         if DEBUG:
             print "y2 ", y2.encode("hex")
         if rtn != 0:
@@ -225,22 +223,22 @@ if __name__ == "__main__":
 
         if MPIN_FULL:
             time_func(
-                'HM = mpin_ZZZ.hash_all(HASH_TYPE_MPIN_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)',
+                'HM = mpin_ZZZ.hash_all(mpin_ZZZ.HASH_TYPE_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)',
                 nIter)
             HM = mpin_ZZZ.hash_all(
-                HASH_TYPE_MPIN_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)
+                mpin_ZZZ.HASH_TYPE_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)
 
             time_func(
-                'rtn, client_aes_key = mpin_ZZZ.client_key(HASH_TYPE_MPIN_ZZZ, pc1, pc2, PIN, r, x, HM, T)',
+                'rtn, client_aes_key = mpin_ZZZ.client_key(mpin_ZZZ.HASH_TYPE_ZZZ, pc1, pc2, PIN, r, x, HM, T)',
                 nIter)
             rtn, client_aes_key = mpin_ZZZ.client_key(
-                HASH_TYPE_MPIN_ZZZ, pc1, pc2, PIN, r, x, HM, T)
+                mpin_ZZZ.HASH_TYPE_ZZZ, pc1, pc2, PIN, r, x, HM, T)
             if rtn != 0:
                 print "ERROR: Generating client_aes_key %s" % rtn
             print "Client AES Key: %s" % client_aes_key.encode("hex")
 
             rtn, server_aes_key = mpin_ZZZ.server_key(
-                HASH_TYPE_MPIN_ZZZ, Z, server_secret, w, HM, HID, u, ut)
+                mpin_ZZZ.HASH_TYPE_ZZZ, Z, server_secret, w, HM, HID, u, ut)
             if rtn != 0:
                 print "ERROR: Generating server_aes_key %s" % rtn
             print "Server AES Key: %s" % server_aes_key.encode("hex")
@@ -258,10 +256,10 @@ if __name__ == "__main__":
 
         # Client first pass
         time_func(
-            'rtn, x, u, ut, sec = mpin_ZZZ.client_1(HASH_TYPE_MPIN_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit)',
+            'rtn, x, u, ut, sec = mpin_ZZZ.client_1(mpin_ZZZ.HASH_TYPE_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit)',
             nIter)
         rtn, x, u, ut, sec = mpin_ZZZ.client_1(
-            HASH_TYPE_MPIN_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit)
+            mpin_ZZZ.HASH_TYPE_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit)
         if rtn != 0:
             print "client_1  ERROR %s" % rtn
         if DEBUG:
@@ -270,9 +268,9 @@ if __name__ == "__main__":
         # 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.
         time_func(
-            'HID, HTID = mpin_ZZZ.server_1(HASH_TYPE_MPIN_ZZZ, date, mpin_id)',
+            'HID, HTID = mpin_ZZZ.server_1(mpin_ZZZ.HASH_TYPE_ZZZ, date, mpin_id)',
             nIter)
-        HID, HTID = mpin_ZZZ.server_1(HASH_TYPE_MPIN_ZZZ, date, mpin_id)
+        HID, HTID = mpin_ZZZ.server_1(mpin_ZZZ.HASH_TYPE_ZZZ, date, mpin_id)
 
         # Server generates Random number y and sends it to Client
         time_func('rtn, y = mpin_ZZZ.random_generate(rng)', nIter)
@@ -324,25 +322,25 @@ if __name__ == "__main__":
                 print "ERROR: Generating T %s" % rtn
 
             time_func(
-                'HM = mpin_ZZZ.hash_all(HASH_TYPE_MPIN_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)',
+                'HM = mpin_ZZZ.hash_all(mpin_ZZZ.HASH_TYPE_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)',
                 nIter)
             HM = mpin_ZZZ.hash_all(
-                HASH_TYPE_MPIN_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)
+                mpin_ZZZ.HASH_TYPE_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)
 
             time_func(
-                'rtn, client_aes_key = mpin_ZZZ.client_key(HASH_TYPE_MPIN_ZZZ, pc1, pc2, PIN, r, x, HM, T)',
+                'rtn, client_aes_key = mpin_ZZZ.client_key(mpin_ZZZ.HASH_TYPE_ZZZ, pc1, pc2, PIN, r, x, HM, T)',
                 nIter)
             rtn, client_aes_key = mpin_ZZZ.client_key(
-                HASH_TYPE_MPIN_ZZZ, pc1, pc2, PIN, r, x, HM, T)
+                mpin_ZZZ.HASH_TYPE_ZZZ, pc1, pc2, PIN, r, x, HM, T)
             if rtn != 0:
                 print "ERROR: Generating client_aes_key %s" % rtn
             print "Client AES Key: %s" % client_aes_key.encode("hex")
 
             time_func(
-                'rtn, server_aes_key = mpin_ZZZ.server_key(HASH_TYPE_MPIN_ZZZ, Z, server_secret, w, HM, HID, u, ut)',
+                'rtn, server_aes_key = mpin_ZZZ.server_key(mpin_ZZZ.HASH_TYPE_ZZZ, Z, server_secret, w, HM, HID, u, ut)',
                 nIter)
             rtn, server_aes_key = mpin_ZZZ.server_key(
-                HASH_TYPE_MPIN_ZZZ, Z, server_secret, w, HM, HID, u, ut)
+                mpin_ZZZ.HASH_TYPE_ZZZ, Z, server_secret, w, HM, HID, u, ut)
             if rtn != 0:
                 print "ERROR: Generating server_aes_key %s" % rtn
             print "Server AES Key: %s" % server_aes_key.encode("hex")
diff --git a/wrappers/python/bls_ZZZ.py.in b/wrappers/python/bls_ZZZ.py.in
new file mode 100755
index 0000000..2f78793
--- /dev/null
+++ b/wrappers/python/bls_ZZZ.py.in
@@ -0,0 +1,469 @@
+#!/usr/bin/env python3
+
+"""
+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.
+"""
+
+
+"""
+bls
+
+This module use cffi to access the c functions in the BLS library.
+
+There is also an example usage program in this file.
+
+"""
+import cffi
+import platform
+import os
+
+ffi = cffi.FFI()
+ffi.cdef("""
+typedef struct {
+unsigned int ira[21];  /* random number...   */
+int rndptr;   /* ...array & pointer */
+unsigned int borrow;
+int pool_ptr;
+char pool[32];    /* random pool */
+} csprng;
+
+typedef struct
+{
+  int len;
+  int max;
+  char *val;
+} octet;
+
+extern void CREATE_CSPRNG(csprng *R,octet *S);
+extern void KILL_CSPRNG(csprng *R);
+extern void OCT_clear(octet *O);
+
+extern int BLS_ZZZ_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W);
+extern int BLS_ZZZ_SIGN(octet *SIG,char *m,octet *S);
+extern int BLS_ZZZ_VERIFY(octet *SIG,char *m,octet *W);
+extern int BLS_ZZZ_ADD_G1(octet *R1,octet *R2,octet *R);
+extern int BLS_ZZZ_ADD_G2(octet *W1,octet *W2,octet *W);
+
+
+""")
+
+if (platform.system() == 'Windows'):
+    libamcl_bls_ZZZ = ffi.dlopen("libamcl_bls_ZZZ.dll")
+    libamcl_core = ffi.dlopen("libamcl_core.dll")
+elif (platform.system() == 'Darwin'):
+    libamcl_bls_ZZZ = ffi.dlopen("libamcl_bls_ZZZ.dylib")
+    libamcl_core = ffi.dlopen("libamcl_core.dylib")
+else:
+    libamcl_bls_ZZZ = ffi.dlopen("libamcl_bls_ZZZ.so")
+    libamcl_core = ffi.dlopen("libamcl_core.so")
+
+# Group Size
+BGS = @NB@
+# Field Size
+BFS = @NB@
+
+CURVE_SECURITY = @CS@
+
+G1LEN = BFS+1
+
+if CURVE_SECURITY == 128:
+    G2LEN = 4*BFS
+
+if CURVE_SECURITY == 192:
+    G2LEN = 8*BFS
+
+if CURVE_SECURITY == 256:
+    G2LEN = 16*BFS
+    
+
+def to_hex(octet_value):
+    """Converts an octet type into a string
+
+    Add all the values in an octet into an array. This arrays is then
+    converted to a string and hex encoded.
+
+    Args::
+
+        octet_value. An octet pointer type
+
+    Returns::
+
+        String
+
+    Raises:
+        Exception
+    """
+    i = 0
+    val = []
+    while i < octet_value.len:
+        val.append(octet_value.val[i])
+        i = i + 1
+    out=b''
+    for x in val:
+        out = out + x
+    return out.hex()
+
+def make_octet(length, value=None):
+    """Generates an octet pointer
+
+    Generates an empty octet or one filled with the input value
+
+    Args::
+
+        length: Length of empty octet
+        value:  Data to assign to octet
+
+    Returns::
+
+        oct_ptr: octet pointer
+        val: data associated with octet to prevent garbage collection
+
+    Raises:
+
+    """
+    oct_ptr = ffi.new("octet*")
+    if value:
+        val = ffi.new("char [%s]" % len(value), value)
+        oct_ptr.val = val
+        oct_ptr.max = len(value)
+        oct_ptr.len = len(value)
+    else:
+        val = ffi.new("char []", length)
+        oct_ptr.val = val
+        oct_ptr.max = length
+        oct_ptr.len = length
+    return oct_ptr, val
+
+def create_csprng(seed):
+    """Make a Cryptographically secure pseudo-random number generator instance
+
+    Make a Cryptographically secure pseudo-random number generator instance
+
+    Args::
+
+        seed:   random seed value
+
+    Returns::
+
+        rng: Pointer to cryptographically secure pseudo-random number generator instance
+
+    Raises:
+
+    """
+    seed_oct, seed_val = make_octet(None, seed)
+
+    # random number generator
+    rng = ffi.new('csprng*')
+    libamcl_core.CREATE_CSPRNG(rng, seed_oct)
+    libamcl_core.OCT_clear(seed_oct)
+
+    return rng
+
+
+def kill_csprng(rng):
+    """Kill a random number generator
+
+    Deletes all internal state
+
+    Args::
+
+        rng: Pointer to cryptographically secure pseudo-random number generator instance
+
+    Returns::
+
+
+
+    Raises:
+
+    """
+    libamcl_core.KILL_CSPRNG(rng)
+
+    return 0
+
+def key_pair_generate(rng):
+    """Generate key pair
+
+    Generate key pair
+
+    Args::
+
+        rng: Pointer to cryptographically secure pseudo-random number generator instance
+
+    Returns::
+
+        error_code: error from the C function
+        sk: secret key
+        pk: public key
+
+    Raises:
+
+    """
+    sk1, sk1val = make_octet(BGS)
+    pk1, pk1val = make_octet(G2LEN)    
+    error_code = libamcl_bls_ZZZ.BLS_ZZZ_KEY_PAIR_GENERATE(rng, sk1,pk1)
+
+    sk_hex = to_hex(sk1)
+    pk_hex = to_hex(pk1)    
+
+    # clear memory
+    libamcl_core.OCT_clear(sk1)
+    libamcl_core.OCT_clear(pk1)    
+
+    sk = bytes.fromhex(sk_hex)
+    pk = bytes.fromhex(pk_hex)        
+    return error_code, sk, pk
+
+def sign(message, sk):
+    """Calculate a signature
+
+    Generate key pair
+
+    Args::
+
+        message: Message to sign
+        sk: BLS secret key
+
+    Returns::
+
+        error_code: Zero for success or else an error code
+        signature: BLS signature
+
+    Raises:
+
+    """
+    sk1, sk1_val = make_octet(None, sk)
+    signature1, signature1_val = make_octet(G1LEN)    
+    error_code = libamcl_bls_ZZZ.BLS_ZZZ_SIGN(signature1, message, sk1)
+
+    signature_hex = to_hex(signature1)
+
+    # clear memory
+    libamcl_core.OCT_clear(sk1)
+    libamcl_core.OCT_clear(signature1)    
+
+    signature = bytes.fromhex(signature_hex)
+    return error_code, signature
+
+def verify(signature, message, pk):
+    """Verify a signature
+
+    Verify a signature
+
+    Args::
+
+        message: Message to verify
+        signature: BLS signature
+        pk: BLS public key
+
+    Returns::
+
+        error_code: Zero for success or else an error code
+
+    Raises:
+
+    """
+    pk1, pk1_val = make_octet(None, pk)
+    signature1, signature1_val = make_octet(None, signature)
+    error_code = libamcl_bls_ZZZ.BLS_ZZZ_VERIFY(signature1, message, pk1)
+
+    # clear memory
+    libamcl_core.OCT_clear(pk1)
+    libamcl_core.OCT_clear(signature1)    
+
+    return error_code
+
+def add_G1(R1, R2):
+    """Add two members from the group G1
+
+    Add two members from the group G1
+
+    Args::
+
+        R1:   member of G1
+        R2:   member of G1
+
+    Returns::
+
+        R:          member of G1. R = R1+R2
+        error_code: Zero for success or else an error code
+
+    Raises:
+
+    """
+    R11, R11_val = make_octet(None, R1)
+    R21, R21_val = make_octet(None, R2)    
+    R1, R1_val = make_octet(G1LEN)        
+    error_code = libamcl_bls_ZZZ.BLS_ZZZ_ADD_G1(R11, R21, R1)
+
+    R_hex = to_hex(R1)
+    
+    # clear memory
+    libamcl_core.OCT_clear(R11)
+    libamcl_core.OCT_clear(R21)
+    libamcl_core.OCT_clear(R1)    
+
+    R = bytes.fromhex(R_hex)
+    return error_code, R
+
+def add_G2(R1, R2):
+    """Add two members from the group G2
+
+    Add two members from the group G2
+
+    Args::
+
+        R1:   member of G2
+        R2:   member of G2
+
+    Returns::
+
+        R:          member of G2. R = R1+R2
+        error_code: Zero for success or else an error code
+
+    Raises:
+
+    """
+    R11, R11_val = make_octet(None, R1)
+    R21, R21_val = make_octet(None, R2)    
+    R1, R1_val = make_octet(G2LEN)        
+    error_code = libamcl_bls_ZZZ.BLS_ZZZ_ADD_G2(R11, R21, R1)
+
+    R_hex = to_hex(R1)
+    
+    # clear memory
+    libamcl_core.OCT_clear(R11)
+    libamcl_core.OCT_clear(R21)
+    libamcl_core.OCT_clear(R1)    
+
+    R = bytes.fromhex(R_hex)
+    return error_code, R
+
+if __name__ == "__main__":
+    # Print hex values
+    DEBUG = False
+
+    # Seed
+    seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30"
+    seed = bytes.fromhex(seed_hex)
+
+    # Message
+    message = b"test message"
+
+    # random number generator
+    rng = create_csprng(seed)
+
+    # Generate key pairs
+    rtn, sk1, pk1 = key_pair_generate(rng)
+    if rtn != 0:
+        print("Error: key_pair_generate {}".format(rtn))                
+        raise SystemExit(0)        
+    print("sk1: {}".format(sk1.hex()))
+    print("pk1: {}".format(pk1.hex()))
+
+    rtn, sk2, pk2 = key_pair_generate(rng)
+    if rtn != 0:
+        print("Error: key_pair_generate {}".format(rtn))        
+        raise SystemExit(0)        
+    print("sk2: {}".format(sk2.hex()))
+    print("pk2: {}".format(pk2.hex()))
+
+    rtn, sk3, pk3 = key_pair_generate(rng)
+    if rtn != 0:
+        print("Error: key_pair_generate {}".format(rtn))        
+        raise SystemExit(0)        
+    print("sk3: {}".format(sk3.hex()))
+    print("pk3: {}".format(pk3.hex()))
+
+    # Sign and verify
+    rtn, sig1 = sign(message, sk1)
+    if rtn != 0:
+        print("Error: sign {}".format(rtn))
+        raise SystemExit(0)                
+    print("sig1: {}".format(sig1.hex()))
+
+    rtn = verify(sig1, message, pk1)
+    if rtn != 0:
+        print("Error: Invalid signature {}".format(rtn))
+        raise SystemExit(0)
+    print("Success: Signature is valid")
+
+    rtn, sig2 = sign(message, sk2)
+    if rtn != 0:
+        print("Error: sign {}".format(rtn))
+        raise SystemExit(0)                
+    print("sig2: {}".format(sig2.hex()))
+
+    rtn = verify(sig2, message, pk2)
+    if rtn != 0:
+        print("Error: Invalid signature {}".format(rtn))
+        raise SystemExit(0)
+    print("Success: Signature is valid")
+    
+    rtn, sig3 = sign(message, sk3)
+    if rtn != 0:
+        print("Error: sign {}".format(rtn))
+        raise SystemExit(0)                
+    print("sig3: {}".format(sig3.hex()))
+    
+    rtn = verify(sig3, message, pk3)
+    if rtn != 0:
+        print("Error: Invalid signature {}".format(rtn))
+        raise SystemExit(0)
+    print("Success: Signature is valid")
+
+    # Add Signatures
+    rtn, sig12 = add_G1(sig1, sig2)
+    if rtn != 0:
+        print("Error: add_G1 {}".format(rtn))
+        raise SystemExit(0)
+    print("sig12: {}".format(sig12.hex()))    
+
+    rtn, sig123 = add_G1(sig12, sig3)
+    if rtn != 0:
+        print("Error: add_G1 {}".format(rtn))
+        raise SystemExit(0)
+    print("sig123: {}".format(sig123.hex()))    
+
+    # Add Public keys
+    rtn, pk12 = add_G2(pk1, pk2)
+    if rtn != 0:
+        print("Error: add_G2 {}".format(rtn))
+        raise SystemExit(0)
+    print("pk12: {}".format(pk12.hex()))    
+
+    rtn, pk123 = add_G2(pk12, pk3)
+    if rtn != 0:
+        print("Error: add_G2 {}".format(rtn))
+        raise SystemExit(0)
+    print("pk123: {}".format(pk123.hex()))    
+
+    # Verify aggretated values
+    rtn = verify(sig123, message, pk123)
+    if rtn != 0:
+        print("Error: Invalid aggregated signature {}".format(rtn))
+        raise SystemExit(0)
+    print("Success: Aggregated signature is valid")
+    
+    # Clear memory    
+    kill_csprng(rng)
+    del sk1
+    del pk1    
+    del sk2
+    del pk2    
+    del sk3
+    del pk3    
diff --git a/wrappers/python/mpin_ZZZ.py.in b/wrappers/python/mpin_ZZZ.py.in
index 8535820..0632cc8 100644
--- a/wrappers/python/mpin_ZZZ.py.in
+++ b/wrappers/python/mpin_ZZZ.py.in
@@ -32,7 +32,6 @@ import cffi
 import platform
 import os
 
-
 ffi = cffi.FFI()
 ffi.cdef("""
 typedef struct {
@@ -101,22 +100,33 @@ else:
     libamcl_mpin_ZZZ = ffi.dlopen("libamcl_mpin_ZZZ.so")
     libamcl_core = ffi.dlopen("libamcl_core.so")
 
-# MPIN Group Size
+# Group Size
 PGS = @NB@
-# MPIN Field Size
+# Field Size
 PFS = @NB@
+
+CURVE_SECURITY = @CS@
+
+if CURVE_SECURITY == 128:
+    G2 = 4*PFS
+    HASH_TYPE_ZZZ = 32
+    AESKEY_ZZZ = 16    
+    
+if CURVE_SECURITY == 192:
+    G2 = 8*PFS
+    HASH_TYPE_ZZZ = 48    
+    AESKEY_ZZZ = 24
+    
+if CURVE_SECURITY == 256:
+    G2 = 16*PFS
+    HASH_TYPE_ZZZ = 64
+    AESKEY_ZZZ = 32
+    
 G1 = 2 * PFS + 1
-G2 = 4 * PFS
-GT = 12 * PFS
+GT = 3*G2
+
 # AES-GCM IV length
 IVL = 12
-# MPIN Symmetric Key Size
-PAS = 16
-
-# Hash function choice
-SHA256 = 32
-SHA384 = 48
-SHA512 = 64
 
 
 def to_hex(octet_value):
@@ -1164,7 +1174,7 @@ def client_key(hash_type, pc1, pc2, pin, r, x, hm, t):
     x1, x1_val = make_octet(None, x)
     hm1, hm1_val = make_octet(None, hm)
     t1, t1_val = make_octet(None, t)
-    client_aes_key1, client_aes_key_val1 = make_octet(PAS)
+    client_aes_key1, client_aes_key_val1 = make_octet(AESKEY_ZZZ)
     error_code = libamcl_mpin_ZZZ.MPIN_ZZZ_CLIENT_KEY(
         hash_type,
         pc11,
@@ -1225,7 +1235,7 @@ def server_key(hash_type, z, server_secret, w, hm, HID, u, ut):
     HID1, HID1_val = make_octet(None, HID)
     u1, u1_val = make_octet(None, u)
 
-    server_aes_key1, server_aes_key1_val = make_octet(PAS)
+    server_aes_key1, server_aes_key1_val = make_octet(AESKEY_ZZZ)
     error_code = libamcl_mpin_ZZZ.MPIN_ZZZ_SERVER_KEY(
         hash_type,
         z1,
@@ -1278,7 +1288,7 @@ def aes_gcm_encrypt(aes_key, iv, header, plaintext):
     iv1, iv1_val = make_octet(None, iv)
     header1, header1_val = make_octet(None, header)
     plaintext1, plaintext1_val = make_octet(None, plaintext)
-    tag1, tag1_val = make_octet(PAS)
+    tag1, tag1_val = make_octet(AESKEY_ZZZ)
     ciphertext1, ciphertext1_val = make_octet(len(plaintext))
 
     libamcl_core.AES_GCM_ENCRYPT(
@@ -1326,7 +1336,7 @@ def aes_gcm_decrypt(aes_key, iv, header, ciphertext):
     iv1, iv1_val = make_octet(None, iv)
     header1, header1_val = make_octet(None, header)
     ciphertext1, ciphertext1_val = make_octet(None, ciphertext)
-    tag1, tag1_val = make_octet(PAS)
+    tag1, tag1_val = make_octet(AESKEY_ZZZ)
     plaintext1, plaintext1_val = make_octet(len(ciphertext))
 
     libamcl_core.AES_GCM_DECRYPT(
@@ -1412,7 +1422,7 @@ if __name__ == "__main__":
     MPIN_ZZZ_FULL = True
     PIN_ERROR = True
 
-    HASH_TYPE_MPIN_ZZZ = SHA256
+
 
     if TIME_PERMITS:
         date = today()
@@ -1433,7 +1443,7 @@ if __name__ == "__main__":
         mpin_id = "user@milagro.com"
 
     # Hash mpin_id
-    hash_mpin_id = hash_id(HASH_TYPE_MPIN_ZZZ, mpin_id)
+    hash_mpin_id = hash_id(HASH_TYPE_ZZZ, mpin_id)
     if DEBUG:
         print "mpin_id: %s" % mpin_id.encode("hex")
         print "hash_mpin_id: %s" % hash_mpin_id.encode("hex")
@@ -1489,13 +1499,13 @@ if __name__ == "__main__":
         if DEBUG:
             print "Date %s" % date
         rtn, tp1 = get_client_permit(
-            HASH_TYPE_MPIN_ZZZ, date, ms1, hash_mpin_id)
+            HASH_TYPE_ZZZ, date, ms1, hash_mpin_id)
         if rtn != 0:
-            print "get_client_permit(HASH_TYPE_MPIN_ZZZ, date, ms1, hash_mpin_id) Error %s" % rtn
+            print "get_client_permit(HASH_TYPE_ZZZ, date, ms1, hash_mpin_id) Error %s" % rtn
         rtn, tp2 = get_client_permit(
-            HASH_TYPE_MPIN_ZZZ, date, ms2, hash_mpin_id)
+            HASH_TYPE_ZZZ, date, ms2, hash_mpin_id)
         if rtn != 0:
-            print "get_client_permit(HASH_TYPE_MPIN_ZZZ, date, ms2, hash_mpin_id) Error %s" % rtn
+            print "get_client_permit(HASH_TYPE_ZZZ, date, ms2, hash_mpin_id) Error %s" % rtn
         if DEBUG:
             print "tp1: %s" % tp1.encode("hex")
             print "tp2: %s" % tp2.encode("hex")
@@ -1515,9 +1525,9 @@ if __name__ == "__main__":
             raw_input("Please enter four digit PIN to create M-Pin Token:"))
     else:
         PIN = 1234
-    rtn, token = extract_pin(HASH_TYPE_MPIN_ZZZ, mpin_id, PIN, client_secret)
+    rtn, token = extract_pin(HASH_TYPE_ZZZ, mpin_id, PIN, client_secret)
     if rtn != 0:
-        print "extract_pin(HASH_TYPE_MPIN_ZZZ, mpin_id, PIN, token) Error %s" % rtn
+        print "extract_pin(HASH_TYPE_ZZZ, mpin_id, PIN, token) Error %s" % rtn
     print "Token: %s" % token.encode("hex")
 
     if ONE_PASS:
@@ -1536,7 +1546,7 @@ if __name__ == "__main__":
 
         # Client MPIN
         rtn, x, u, ut, v, y = client(
-            HASH_TYPE_MPIN_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit, None, epoch_time)
+            HASH_TYPE_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit, None, epoch_time)
         if rtn != 0:
             print "MPIN_ZZZ_CLIENT ERROR %s" % rtn
 
@@ -1546,7 +1556,7 @@ if __name__ == "__main__":
 
         # Server MPIN
         rtn, HID, HTID, E, F, y2 = server(
-            HASH_TYPE_MPIN_ZZZ, date, server_secret, u, ut, v, mpin_id, None, epoch_time)
+            HASH_TYPE_ZZZ, date, server_secret, u, ut, v, mpin_id, None, epoch_time)
         if DEBUG:
             print "y2 ", y2.encode("hex")
         if rtn != 0:
@@ -1571,16 +1581,16 @@ if __name__ == "__main__":
                 print "ERROR: Generating T %s" % rtn
 
         if MPIN_ZZZ_FULL:
-            HM = hash_all(HASH_TYPE_MPIN_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)
+            HM = hash_all(HASH_TYPE_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)
 
             rtn, client_aes_key = client_key(
-                HASH_TYPE_MPIN_ZZZ, pc1, pc2, PIN, r, x, HM, T)
+                HASH_TYPE_ZZZ, pc1, pc2, PIN, r, x, HM, T)
             if rtn != 0:
                 print "ERROR: Generating client_aes_key %s" % rtn
             print "Client AES Key: %s" % client_aes_key.encode("hex")
 
             rtn, server_aes_key = server_key(
-                HASH_TYPE_MPIN_ZZZ, Z, server_secret, w, HM, HID, u, ut)
+                HASH_TYPE_ZZZ, Z, server_secret, w, HM, HID, u, ut)
             if rtn != 0:
                 print "ERROR: Generating server_aes_key %s" % rtn
             print "Server AES Key: %s" % server_aes_key.encode("hex")
@@ -1598,7 +1608,7 @@ if __name__ == "__main__":
 
         # Client first pass
         rtn, x, u, ut, sec = client_1(
-            HASH_TYPE_MPIN_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit)
+            HASH_TYPE_ZZZ, date, mpin_id, rng, None, PIN, token, time_permit)
         if rtn != 0:
             print "client_1  ERROR %s" % rtn
         if DEBUG:
@@ -1606,7 +1616,7 @@ if __name__ == "__main__":
 
         # 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.
-        HID, HTID = server_1(HASH_TYPE_MPIN_ZZZ, date, mpin_id)
+        HID, HTID = server_1(HASH_TYPE_ZZZ, date, mpin_id)
 
         # Server generates Random number y and sends it to Client
         rtn, y = random_generate(rng)
@@ -1647,16 +1657,16 @@ if __name__ == "__main__":
             if rtn != 0:
                 print "ERROR: Generating T %s" % rtn
 
-            HM = hash_all(HASH_TYPE_MPIN_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)
+            HM = hash_all(HASH_TYPE_ZZZ, hash_mpin_id, u, ut, v, y, Z, T)
 
             rtn, client_aes_key = client_key(
-                HASH_TYPE_MPIN_ZZZ, pc1, pc2, PIN, r, x, HM, T)
+                HASH_TYPE_ZZZ, pc1, pc2, PIN, r, x, HM, T)
             if rtn != 0:
                 print "ERROR: Generating client_aes_key %s" % rtn
             print "Client AES Key: %s" % client_aes_key.encode("hex")
 
             rtn, server_aes_key = server_key(
-                HASH_TYPE_MPIN_ZZZ, Z, server_secret, w, HM, HID, u, ut)
+                HASH_TYPE_ZZZ, Z, server_secret, w, HM, HID, u, ut)
             if rtn != 0:
                 print "ERROR: Generating server_aes_key %s" % rtn
             print "Server AES Key: %s" % server_aes_key.encode("hex")
diff --git a/wrappers/python/wcc_ZZZ.py.in b/wrappers/python/wcc_ZZZ.py.in
index 4457f12..2b083e8 100644
--- a/wrappers/python/wcc_ZZZ.py.in
+++ b/wrappers/python/wcc_ZZZ.py.in
@@ -31,25 +31,6 @@ There is also an example usage program in this file.
 import cffi
 import platform
 
-# WCC Group Size
-PGS = @NB@
-# WCC Field Size
-PFS = @NB@
-G1 = 2 * PFS + 1
-G2 = 4 * PFS
-# Length of hash
-HASH_BYTES = 32
-# AES-GCM IV length
-IVL = 12
-# AES Key length
-PAS = 16
-
-# Hash function choice
-SHA256 = 32
-SHA384 = 48
-SHA512 = 64
-HASH_TYPE_WCC_ZZZ = SHA256
-
 ffi = cffi.FFI()
 ffi.cdef("""
 typedef struct {
@@ -94,6 +75,32 @@ else:
     libamcl_wcc_ZZZ = ffi.dlopen("libamcl_wcc_ZZZ.so")
     libamcl_core = ffi.dlopen("libamcl_core.so")
 
+# Group Size
+PGS = @NB@
+# Field Size
+PFS = @NB@
+
+CURVE_SECURITY = @CS@
+
+if CURVE_SECURITY == 128:
+    G2 = 4*PFS
+    HASH_TYPE_ZZZ = 32
+    AESKEY_ZZZ = 16    
+    
+if CURVE_SECURITY == 192:
+    G2 = 8*PFS
+    HASH_TYPE_ZZZ = 48    
+    AESKEY_ZZZ = 24
+    
+if CURVE_SECURITY == 256:
+    G2 = 16*PFS
+    HASH_TYPE_ZZZ = 64
+    AESKEY_ZZZ = 32
+    
+G1 = 2 * PFS + 1
+
+# AES-GCM IV length
+IVL = 12
 
 def toHex(octetValue):
     """Converts an octet type into a string
@@ -151,10 +158,10 @@ if __name__ == "__main__":
 
     # Hash value of IdA
     HIdA = ffi.new("octet*")
-    HIdAval = ffi.new("char []", HASH_BYTES)
+    HIdAval = ffi.new("char []", PFS)
     HIdA[0].val = HIdAval
-    HIdA[0].max = HASH_BYTES
-    HIdA[0].len = HASH_BYTES
+    HIdA[0].max = PFS
+    HIdA[0].len = PFS
 
     # Bob Identity
     bob_id = raw_input("Please enter Bob's identity:")
@@ -166,10 +173,10 @@ if __name__ == "__main__":
 
     # Hash value of IdB
     HIdB = ffi.new("octet*")
-    HIdBval = ffi.new("char []", HASH_BYTES)
+    HIdBval = ffi.new("char []", PFS)
     HIdB[0].val = HIdBval
-    HIdB[0].max = HASH_BYTES
-    HIdB[0].len = HASH_BYTES
+    HIdB[0].max = PFS
+    HIdB[0].len = PFS
 
     # Sender keys
     A1KeyG1 = ffi.new("octet*")
@@ -211,16 +218,16 @@ if __name__ == "__main__":
 
     # AES Keys
     KEY1 = ffi.new("octet*")
-    KEY1val = ffi.new("char []", PAS)
+    KEY1val = ffi.new("char []", AESKEY_ZZZ)
     KEY1[0].val = KEY1val
-    KEY1[0].max = PAS
-    KEY1[0].len = PAS
+    KEY1[0].max = AESKEY_ZZZ
+    KEY1[0].len = AESKEY_ZZZ
 
     KEY2 = ffi.new("octet*")
-    KEY2val = ffi.new("char []", PAS)
+    KEY2val = ffi.new("char []", AESKEY_ZZZ)
     KEY2[0].val = KEY2val
-    KEY2[0].max = PAS
-    KEY2[0].len = PAS
+    KEY2[0].max = AESKEY_ZZZ
+    KEY2[0].len = AESKEY_ZZZ
 
     X = ffi.new("octet*")
     Xval = ffi.new("char []", PGS)
@@ -284,13 +291,13 @@ if __name__ == "__main__":
     libamcl_core.CREATE_CSPRNG(RNG, SEED)
 
     # Hash IdA
-    libamcl_core.HASH_ID(HASH_TYPE_WCC_ZZZ, IdA, HIdA)
+    libamcl_core.HASH_ID(HASH_TYPE_ZZZ, IdA, HIdA)
     if DEBUG:
         print "IdA: %s" % toHex(IdA)
         print "HIdA: %s" % toHex(HIdA)
 
     # Hash IdB
-    libamcl_core.HASH_ID(HASH_TYPE_WCC_ZZZ, IdB, HIdB)
+    libamcl_core.HASH_ID(HASH_TYPE_ZZZ, IdB, HIdB)
     if DEBUG:
         print "IdB: %s" % toHex(IdB)
         print "HIdB: %s" % toHex(HIdB)
@@ -377,18 +384,18 @@ if __name__ == "__main__":
         print "PbG2: %s" % toHex(PbG2)
 
     # PIA = Hq(PaG1,PbG2,PgG1,IdB)
-    libamcl_wcc_ZZZ.WCC_ZZZ_Hq(HASH_TYPE_WCC_ZZZ, PaG1, PbG2, PgG1, IdB, PIA)
+    libamcl_wcc_ZZZ.WCC_ZZZ_Hq(HASH_TYPE_ZZZ, PaG1, PbG2, PgG1, IdB, PIA)
     if DEBUG:
         print "PIA: %s" % toHex(PIA)
 
     # PIB = Hq(PbG2,PaG1,PgG1,IdA)
-    libamcl_wcc_ZZZ.WCC_ZZZ_Hq(HASH_TYPE_WCC_ZZZ, PbG2, PaG1, PgG1, IdA, PIB)
+    libamcl_wcc_ZZZ.WCC_ZZZ_Hq(HASH_TYPE_ZZZ, PbG2, PaG1, PgG1, IdA, PIB)
     if DEBUG:
         print "PIB: %s" % toHex(PIB)
 
     # Alice calculates AES Key
     rtn = libamcl_wcc_ZZZ.WCC_ZZZ_SENDER_KEY(
-        HASH_TYPE_WCC_ZZZ,
+        HASH_TYPE_ZZZ,
         X,
         PIA,
         PIB,
@@ -398,12 +405,12 @@ if __name__ == "__main__":
         IdB,
         KEY1)
     if rtn != 0:
-        print "libamcl_wcc_ZZZ.WCC_ZZZ_SENDER_KEY(HASH_TYPE_WCC_ZZZ, X, PIA, PIB, PbG2, PgG1, AKeyG1, IdB, KEY1) Error %s" % rtn
+        print "libamcl_wcc_ZZZ.WCC_ZZZ_SENDER_KEY(HASH_TYPE_ZZZ, X, PIA, PIB, PbG2, PgG1, AKeyG1, IdB, KEY1) Error %s" % rtn
     print "{0}'s AES Key: {1}".format(alice_id, toHex(KEY1))
 
     # Bob calculates AES Key
     rtn = libamcl_wcc_ZZZ.WCC_ZZZ_RECEIVER_KEY(
-        HASH_TYPE_WCC_ZZZ,
+        HASH_TYPE_ZZZ,
         Y,
         W,
         PIA,
@@ -414,7 +421,7 @@ if __name__ == "__main__":
         IdA,
         KEY2)
     if rtn != 0:
-        print "libamcl_wcc_ZZZ.WCC_ZZZ_RECEIVER_KEY(HASH_TYPE_WCC_ZZZ, Y, W, PIA, PIB, PaG1, PgG1, BKeyG2, IdA, KEY2) Error %s" % rtn
+        print "libamcl_wcc_ZZZ.WCC_ZZZ_RECEIVER_KEY(HASH_TYPE_ZZZ, Y, W, PIA, PIB, PaG1, PgG1, BKeyG2, IdA, KEY2) Error %s" % rtn
     print "{0}'s AES Key: {1}".format(bob_id, toHex(KEY2))
 
     libamcl_core.KILL_CSPRNG(RNG)